Commit c88bbf8d authored by PJ Janse van Rensburg's avatar PJ Janse van Rensburg

Move ChoiceType logic to contrib/sqla/form.py.

parent f09d81dd
...@@ -10,6 +10,8 @@ from flask_admin.contrib import sqla ...@@ -10,6 +10,8 @@ from flask_admin.contrib import sqla
from flask_admin.contrib.sqla import filters from flask_admin.contrib.sqla import filters
from flask_admin.base import MenuLink from flask_admin.base import MenuLink
from sqlalchemy_utils.types import ChoiceType, EmailType
# Create application # Create application
app = Flask(__name__) app = Flask(__name__)
...@@ -26,10 +28,15 @@ db = SQLAlchemy(app) ...@@ -26,10 +28,15 @@ db = SQLAlchemy(app)
# Create models # Create models
class User(db.Model): class User(db.Model):
AVAILABLE_TYPES = [
(u'admin', u'Admin'),
(u'regular-user', u'Regular user')
]
id = db.Column(db.Integer, primary_key=True) id = db.Column(db.Integer, primary_key=True)
first_name = db.Column(db.String(100)) first_name = db.Column(db.String(100))
last_name = db.Column(db.String(100)) last_name = db.Column(db.String(100))
email = db.Column(db.String(120), unique=True) type = db.Column(ChoiceType(AVAILABLE_TYPES), nullable=True)
email = db.Column(EmailType, unique=True, nullable=False)
def __str__(self): def __str__(self):
return "{}, {}".format(self.last_name, self.first_name) return "{}, {}".format(self.last_name, self.first_name)
...@@ -101,6 +108,7 @@ class UserAdmin(sqla.ModelView): ...@@ -101,6 +108,7 @@ class UserAdmin(sqla.ModelView):
'last_name', 'last_name',
'first_name', 'first_name',
'email', 'email',
'type',
] ]
column_default_sort = [('last_name', False), ('first_name', False)] # sort on multiple columns column_default_sort = [('last_name', False), ('first_name', False)] # sort on multiple columns
inline_models = (UserInfo,) inline_models = (UserInfo,)
......
...@@ -244,7 +244,7 @@ class AdminModelConverter(ModelConverterBase): ...@@ -244,7 +244,7 @@ class AdminModelConverter(ModelConverterBase):
return override(**kwargs) return override(**kwargs)
# Check choices # Check choices
form_choices = getattr(self.view, 'form_choices', None) form_choices = getattr(self.view, 'form_choices', getattr(self.view, 'choices', None))
if mapper.class_ == self.view.model and form_choices: if mapper.class_ == self.view.model and form_choices:
choices = form_choices.get(prop.key) choices = form_choices.get(prop.key)
...@@ -271,12 +271,16 @@ class AdminModelConverter(ModelConverterBase): ...@@ -271,12 +271,16 @@ class AdminModelConverter(ModelConverterBase):
if hasattr(column.type, 'length') and isinstance(column.type.length, int) and column.type.length: if hasattr(column.type, 'length') and isinstance(column.type.length, int) and column.type.length:
field_args['validators'].append(validators.Length(max=column.type.length)) field_args['validators'].append(validators.Length(max=column.type.length))
@converts('String') # includes VARCHAR, CHAR, and Unicode @converts('String', 'ChoiceType') # includes VARCHAR, CHAR, and Unicode
def conv_String(self, column, field_args, **extra): def conv_String(self, column, field_args, **extra):
available_choices = []
if hasattr(column.type, 'enums'): if hasattr(column.type, 'enums'):
accepted_values = list(column.type.enums) available_choices = [(f, f) for f in column.type.enums]
elif hasattr(column.type, 'choices'):
field_args['choices'] = [(f, f) for f in column.type.enums] available_choices = column.type.choices
if available_choices:
field_args['choices'] = available_choices
accepted_values = [key for key, val in available_choices]
if column.nullable: if column.nullable:
field_args['allow_blank'] = column.nullable field_args['allow_blank'] = column.nullable
...@@ -321,7 +325,7 @@ class AdminModelConverter(ModelConverterBase): ...@@ -321,7 +325,7 @@ class AdminModelConverter(ModelConverterBase):
def convert_email(self, field_args, **extra): def convert_email(self, field_args, **extra):
field_args['validators'].append(validators.Email()) field_args['validators'].append(validators.Email())
return fields.StringField(**field_args) return fields.StringField(**field_args)
@converts('Integer') # includes BigInteger and SmallInteger @converts('Integer') # includes BigInteger and SmallInteger
def handle_integer_types(self, column, field_args, **extra): def handle_integer_types(self, column, field_args, **extra):
unsigned = getattr(column.type, 'unsigned', False) unsigned = getattr(column.type, 'unsigned', False)
......
from sqlalchemy.ext.associationproxy import _AssociationList from sqlalchemy.ext.associationproxy import _AssociationList
from flask_admin.model.typefmt import BASE_FORMATTERS, list_formatter from flask_admin.model.typefmt import BASE_FORMATTERS, EXPORT_FORMATTERS, \
DETAIL_FORMATTERS, list_formatter
from sqlalchemy.orm.collections import InstrumentedList from sqlalchemy.orm.collections import InstrumentedList
from sqlalchemy_utils.types import Choice
def choice_formatter(view, choice):
"""
Return label of selected choice
:param choice:
sqlalchemy_utils Choice, which has a `code` and a `value`
"""
return choice.value
DEFAULT_FORMATTERS = BASE_FORMATTERS.copy() DEFAULT_FORMATTERS = BASE_FORMATTERS.copy()
EXPORT_FORMATTERS = EXPORT_FORMATTERS.copy()
DETAIL_FORMATTERS = DETAIL_FORMATTERS.copy()
DEFAULT_FORMATTERS.update({ DEFAULT_FORMATTERS.update({
InstrumentedList: list_formatter, InstrumentedList: list_formatter,
_AssociationList: list_formatter _AssociationList: list_formatter,
Choice: choice_formatter,
})
EXPORT_FORMATTERS.update({
Choice: choice_formatter,
})
DETAIL_FORMATTERS.update({
Choice: choice_formatter,
}) })
...@@ -117,13 +117,6 @@ class Select2Field(fields.SelectField): ...@@ -117,13 +117,6 @@ class Select2Field(fields.SelectField):
self.allow_blank = allow_blank self.allow_blank = allow_blank
self.blank_text = blank_text or ' ' self.blank_text = blank_text or ' '
try:
from sqlalchemy_utils.types.choice import Choice
except ImportError:
class Choice(object):
pass
self.choice_cls = Choice
def iter_choices(self): def iter_choices(self):
if self.allow_blank: if self.allow_blank:
yield (u'__None', self.blank_text, self.data is None) yield (u'__None', self.blank_text, self.data is None)
...@@ -136,10 +129,7 @@ class Select2Field(fields.SelectField): ...@@ -136,10 +129,7 @@ class Select2Field(fields.SelectField):
self.data = None self.data = None
else: else:
try: try:
if isinstance(value, self.choice_cls): self.data = self.coerce(value)
self.data = self.coerce(value.code)
else:
self.data = self.coerce(value)
except (ValueError, TypeError): except (ValueError, TypeError):
self.data = None self.data = None
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment