Используя flask-admin, Как я могу получить поле тегов, поддерживающее несуществующие теги?
Я получил две модели Product и Tag, а также установил отношение многие ко многим в SQLAlchemy.
Используя это, как показывают примеры flask-admin:
admin.add_view(ProductAdmin(db.session))
Я получаю форму create и могу только выбрать существующие теги.
Я знаю, что flask-admin использует select2, и select2 получает стиль добавления новых тегов.
И я нашел класс Slect2TagsField в Form.py под колбой-папки администратора.
Итак, как я могу получить поле тега, которое поддерживает добавление нового тега, в моей форме создания продукта, используя фляжка-админ?
Заранее благодарю.
2 ответов:
К сожалению, Flask-Admin не предоставляет никаких конечных точек AJAX, поэтому невозможно создавать новые модели в полях Select2.
Однако есть способ заставить его работать:
- исключить поле теги из формы администратора
- Добавьте новое поле Select2TagsField в форму с другим именем (чтобы не было коллизии имен)
- перед отображением нового / редактируемого представления сериализуйте список тегов в виде массива строк и внесите вклад в поле Select2tags
- Перед отправкой модели (on_model_change) пройдите по списку, выполните поиск в базе данных, чтобы найти существующие теги и создать модели для отсутствующих тегов
- добавить список моделей тегов в модель
Вы можете создать свой собственный
TagFieldи добавить его к своемуModelView.вам придется переопределить некоторые функции поля.Я собрал демонстрационное приложение , которое использует select2 версии 4 и немного более подробно, чем этот ответ.
Поле тега:
class CustomTagField(Select2TagsField): widget = CustomTagWidget(multiple=True) def pre_validate(self, form): pass def process_formdata(self, valuelist): if valuelist: self.data = [] for tagname in valuelist: rv = Tag.query.filter_by(name=tagname).first() if rv: self.data.append(rv) else: self.data.append(Tag(name=tagname)) else: self.data = [] def iter_choices(self): self.blank_text = "" tags = list(set([str(tag.name) for tag in Tag.query.all()])) model_tags = [tag.name for tag in self.object_data] self.choices = [[tag, tag] for tag in tags] # Yield empty object in order to have an empty placeholder yield (u'__None', self.blank_text, self.data is None) for value, label in self.choices: yield (value, label, value in model_tags)Пользовательский виджет: (похож на
Select2TagsWidget, но не устанавливаетdata-role, поэтомуform.jsне сделает его обычным полем select2)class CustomTagWidget(widgets.Select): def __call__(self, field, **kwargs): kwargs.setdefault('data-tags', '1') # Or call select2 in tags mode allow_blank = getattr(field, 'allow_blank', False) if allow_blank and not self.multiple: kwargs['data-allow-blank'] = u'1' return super(CustomTagWidget, self).__call__(field, **kwargs)В вашем админе:
form_extra_fields = { 'tags': CustomTagField( 'Tags', ), }Затем переопределите своего администратора шаблон для вызова select2 в режиме тегов на вашем поле (
admin/js/form.jsтакже попытается стилизовать поле):$('#tags').select2({ tags: true, });
Comments