Как заставить поле выбора модели Django принимать несколько критериев

С моделью, определенной как таковая

class Product(models.Model):
    code = models.CharField(max_length=20, unique=True)
    name = models.CharField(max_length=100) # intended to be left as NOT unique

Я хочу выбрать продукт либо по его коду, либо по его названию. Например, если код продукта 1 - SUS304, а название - Stainless Steel 304, введите в форму SUS304 или Stainless Steel 304, чтобы оба варианта выбрали этот продукт.

Я пытаюсь использовать union queryset в качестве source queryset, но Django жалуется, что .filter после .union не поддерживается.

class OrderForm(forms.ModelForm):
    codes = Product.objects.annotate(full=F('code'))
    names = Product.objects.annotate(full=F('name'))
    product = forms.ModelChoiceField(codes.union(names), to_field_name='full')
    class Meta:
        # Order is another model that have a ForeignKey to Product
        model = Order
        fields = ['product']

Как я могу этого добиться (особенно с помощью Django)?

PS1. Возможно, что несколько продуктов имеют одинаковое название, или название одного продукта является кодом другого. В таком случае я бы ожидал ошибку ValidationError.

PS2. Несмотря на ограничение длины, не существует эффективного способа определить, является ли данная строка кодом или названием. SUS304 также может быть названием продукта.

Как насчет переопределения label_from_instance для получения настроенных меток отображения модели в вашем настроенном ModelChoiceField? (Документ здесь)

Основываясь на этом:

class ProductModelChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return f"{obj.code} ({obj.name})"

В наборе запросов, где требуется отфильтровать по двум или более полям с помощью логики ИЛИ, используется Q(keyword=value) | Q(otherkeyword=othervalue). (Q-объекты). В контексте поля ModelChoiceField это будет использоваться для ограничения диапазона объектов, из которых пользователь может выбрать. Это не имеет никакого отношения к тому, что является меткой для выбора.

Возможно, я не совсем понял вопрос.

Вернуться на верх