Список выбора django (динамический выбор)

у меня есть список вариантов:

CATEGORY_CHOICES = (
("T-shirts", "T-shirts"),
("Hoodies", "Hoodies"),
("Shorts", "Shorts"),

)

но я хочу сделать этот список динамическим, чтобы я мог добавлять и удалять варианты, я создал новую модель Category, что я хочу сделать, это что-то вроде этого:

CATEGORY_CHOICES = (
for choice in Category.object.all():
    (choice.category, "choice.category"),
 )

но это не работает


person NAS    schedule 31.07.2020    source источник
comment
Вы можете использовать ForeignKey. В ModelForm будет использоваться ModelChoiceField.   -  person Willem Van Onsem    schedule 01.08.2020


Ответы (1)


В этом случае вам не следует использовать CharField или какое-либо другое поле с вариантами выбора, а следует использовать ForeignKey [Django-doc].

Например:

class Category(models.Model):
    category = models.CharField(max_length=128, unique=True)

    def __str__(self):
        return self.category

class MyModel(models.Model):
    category = models.ForeignKey(Category, on_delete=models.CASCADE)

Если вы создадите ModelForm, по умолчанию будет использоваться ModelChoiceField [Django-doc], а виджет по умолчанию представляет собой раскрывающийся список с параметрами Category.

Если вы хотите выбрать несколько Category, используйте ManyToManyField [Django-doc]:

class Category(models.Model):
    category = models.CharField(max_length=128, unique=True)

    def __str__(self):
        return self.category

class MyModel(models.Model):
    categories = models.ManyToManyField(Category)

Затем в фильтре вы можете использовать ModelMultipleChoiceFilter [читать документы]:

class MyModelFilter(django_filters.FilterSet):
    categories = django_filters.ModelMultipleChoiceFilter(
        queryset=Category.objects.all()
    )
    class Meta:
        model = MyModel
        fields = ['categories']

Но обычно, без указания чего-либо, это поле по умолчанию будет использоваться.

Вы можете изменить виджет на CheckboxSelectMultiple [Django-doc] для работы с последовательностью флажков:

class MyModelFilter(django_filters.FilterSet):
    categories = django_filters.ModelMultipleChoiceFilter(
        queryset=Category.objects.all(),
        widget=forms.CheckboxSelectMultiple()
    )
    class Meta:
        model = MyModel
        fields = ['categories']
person Willem Van Onsem    schedule 31.07.2020
comment
это именно то, что я сделал, у меня есть модель продукта и модель категории, модель категории является внешним ключом в модели продукта, но я использую форму фильтрации: категории = фильтры. widget=forms.CheckboxSelectMultiple()), поэтому я должен предоставить варианты в этом формате, в любом случае цикл for работает: для выбора в Category.object.all(): ^ SyntaxError: недопустимый синтаксис - person NAS; 01.08.2020
comment
@Nas: но тебе это не нужно. Если вы хотите выбрать несколько, вам не нужно использовать ManyToManyField, поскольку теперь он не сможет хранить несколько категорий. - person Willem Van Onsem; 01.08.2020
comment
@ Виллем Ван Онсем, хорошо, но в интерфейсе я хочу отображать варианты выбора в виде списка флажков, как это сделать с помощью ManyToManyField ?? - person NAS; 01.08.2020
comment
@NAS: с виджетом CheckboxSelectMultiple см. редактирование. - person Willem Van Onsem; 01.08.2020
comment
@ Виллем, спасибо, вывод (флажок) работает, но он не фильтрует. Это проблема, когда я добавляю null = True и пустое = True в ManyToManyField ?? - person NAS; 01.08.2020
comment
@NAS: это не проблема. Вы уверены, что отправили форму соответствующим образом? - person Willem Van Onsem; 01.08.2020
comment
я обнаружил проблему, на самом деле я использую настройки виджета Django для ручного рендеринга ввода формы, чтобы я мог добавить стиль к флажку: {% для выбора в filter_form.category %} ‹div class=custom-control custom-checkbox› ‹ тип ввода = класс флажка = идентификатор пользовательского элемента управления = {{ selection.id_for_label }} значение = {{ selection.choice_label }} имя = категория › ‹ class метки = пользовательский элемент управления меткой для = {{ selection.id_for_label } }›{{ selection.choice_label }}‹/label› ‹/div› {% endfor %} - person NAS; 01.08.2020
comment
он отлично работал со старым статическим списком выбора, но не с полем ManyToMany, со статическим списком выбора параметры URL-адреса выглядят так:?categories=shoes, параметры URL-адреса с полем MTM выглядят так:..... ? category=1, поэтому фильтрация основана на первичном ключе и выглядит не очень красиво. - person NAS; 01.08.2020
comment
@NAS: не должен value="{{ value }}"? - person Willem Van Onsem; 01.08.2020
comment
ну, django-filter поставляется со своими собственными тегами шаблона, и я не знаком с ним, я просто следовал руководству и внес несколько изменений, поэтому он все равно может работать с бутстрапом, это исходный тег шаблона: {{filter_form.categories }} и вот что он отображает: ‹ тип ввода = имя флажка = значение категорий = 1 id = id_categories_0 проверено = › обувь - person NAS; 01.08.2020