Model Converters
Model Converters are special classes used to convert SQLAlchemy model properties into web interface form fields. They allow you to customize how backend SQLAlchemy models are represented in the admin interface, providing flexibility in handling different data types and validation rules.
Overview
The ModelConverter
class is the base class for converting SQLAlchemy model properties into form fields. It provides default conversions for common SQLAlchemy types (e.g., String
, Integer
, JSON
) and allows you to customize or extend these conversions.
Base Model Converter
The base ModelConverter
class looks like this:
class ModelConverter(ModelConverterBase):
@staticmethod
def _string_common(prop: ColumnProperty) -> list[Validator]:
li = []
column: Column = prop.columns[0]
if isinstance(column.type.length, int) and column.type.length:
li.append(validators.Length(max=column.type.length))
return li
@converts("String", "CHAR") # includes Unicode
def conv_string(
self, model: type, prop: ColumnProperty, kwargs: dict[str, Any]
) -> UnboundField:
extra_validators = self._string_common(prop)
kwargs.setdefault("validators", [])
kwargs["validators"].extend(extra_validators)
return StringField(**kwargs)
@converts("Text", "LargeBinary", "Binary") # includes UnicodeText
def conv_text(
self, model: type, prop: ColumnProperty, kwargs: dict[str, Any]
) -> UnboundField:
kwargs.setdefault("validators", [])
extra_validators = self._string_common(prop)
kwargs["validators"].extend(extra_validators)
return TextAreaField(**kwargs)
This class includes methods like conv_string
and conv_text
to handle specific SQLAlchemy types. You can extend this class to add custom behavior or override existing conversions.
Customizing Model Converters
You can inherit from ModelConverter
to create your own converter and customize how specific SQLAlchemy types are handled. For example, you can define a custom converter for JSON
fields:
from typing import Any
import json
from wtforms import JSONField
from sqladmin import ModelConverter
class CustomJSONField(JSONField):
def _value(self) -> str:
if self.raw_data:
return self.raw_data[0]
elif self.data:
return str(json.dumps(self.data, ensure_ascii=False))
else:
return ""
class CustomModelConverter(ModelConverter):
@converts("JSON", "JSONB")
def conv_json(self, model: type, prop: ColumnProperty, kwargs: dict[str, Any]) -> UnboundField:
return CustomJSONField(**kwargs)
In this example:
- CustomJSONField
is a custom field that formats JSON data for display.
- CustomModelConverter
overrides the conv_json
method to use CustomJSONField
for JSON
and JSONB
SQLAlchemy types.
Using Custom Model Converters in Admin Views
To use your custom model converter in the admin interface, specify it in your ModelView
class:
from sqladmin import ModelView
class BaseAdmin(ModelView):
form_converter: ClassVar[Type[CustomModelConverter]] = CustomModelConverter
This ensures that all form fields in the admin interface are generated using your custom converter.
Example: Full Workflow
Here’s a complete example of defining a SQLAlchemy model, creating a custom model converter, and using it in the admin interface:
Step 1: Define SQLAlchemy Models
from sqlalchemy import Column, Integer, String, JSON, create_engine
from sqlalchemy.orm import declarative_base
Base = declarative_base()
engine = create_engine("sqlite:///example.db", connect_args={"check_same_thread": False})
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
preferences = Column(JSON)
Base.metadata.create_all(engine) # Create tables
Step 2: Create Custom Model Converter
from sqladmin import ModelConverter
from wtforms import JSONField
import json
class CustomJSONField(JSONField):
def _value(self) -> str:
if self.raw_data:
return self.raw_data[0]
elif self.data:
return str(json.dumps(self.data, ensure_ascii=False))
else:
return ""
class CustomModelConverter(ModelConverter):
@converts("JSON", "JSONB")
def conv_json(self, model: type, prop: ColumnProperty, kwargs: dict[str, Any]) -> UnboundField:
return CustomJSONField(**kwargs)
Step 3: Use Custom Converter in Admin Interface
from sqladmin import ModelView
class UserAdmin(BaseAdmin):
form_converter = CustomModelConverter