Используя flask-admin, Как я могу получить поле тегов, поддерживающее несуществующие теги?



Я получил две модели Product и Tag, а также установил отношение многие ко многим в SQLAlchemy.
Используя это, как показывают примеры flask-admin:



 admin.add_view(ProductAdmin(db.session))


Я получаю форму create и могу только выбрать существующие теги.
Я знаю, что flask-admin использует select2, и select2 получает стиль добавления новых тегов.
И я нашел класс Slect2TagsField в Form.py под колбой-папки администратора.



Итак, как я могу получить поле тега, которое поддерживает добавление нового тега, в моей форме создания продукта, используя фляжка-админ?



Заранее благодарю.

560   2  

2 ответов:

К сожалению, Flask-Admin не предоставляет никаких конечных точек AJAX, поэтому невозможно создавать новые модели в полях Select2.

Однако есть способ заставить его работать:

  1. исключить поле теги из формы администратора
  2. Добавьте новое поле Select2TagsField в форму с другим именем (чтобы не было коллизии имен)
  3. перед отображением нового / редактируемого представления сериализуйте список тегов в виде массива строк и внесите вклад в поле Select2tags
  4. Перед отправкой модели (on_model_change) пройдите по списку, выполните поиск в базе данных, чтобы найти существующие теги и создать модели для отсутствующих тегов
  5. добавить список моделей тегов в модель

Вы можете создать свой собственный 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

    Ничего не найдено.