Как использовать queryset с distinct, чтобы избежать дублирования значений в label_from_instance?

Я хочу использовать queryset с distinct(), чтобы избежать дублирования значения в label_from_instance.

Но затем у меня возникает ошибка, как показано ниже.

у объекта 'str' нет атрибута 'name'

Как я могу использовать queryset с distinct() в label_from_instance?


Вот код в файле forms.py:

from django.forms import ModelChoiceField


class NameChoiceField(ModelChoiceField):

    def label_from_instance(self, obj):
        return f'{obj.name}'
        

class MS_KansokujoForm(forms.ModelForm):
    code = NameChoiceField(queryset=MyModel.objects.all().values_list('name',flat=True).order_by('name').distinct())

python 3.8

Django 3.2

Mysql 5.7

Как я могу использовать queryset с distinct() в label_from_instance?

Вы не . Представьте, что вы используете .distinct() и таким образом получили уникальные имена, и человек выбирает вариант "foo", если есть несколько MyModel с "foo" в качестве имени, то какой из них должен быть выбран: делая отличительный, вы таким образом "уничтожаете" способ обратной ссылки на исходный элемент. Метка должна быть достаточной, чтобы канонически указать, какой элемент модели следует использовать.

Вы должны решить проблему с другой стороны: предотвращая возможность использования нескольких MyModel с одним и тем же name, вы можете пометить поле name как уникальное и, таким образом, работать с:

class MyModel(models.Model):
    name = models.CharField(max_length=128, unique=True)
    # …

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

from django.conf import settings

class MyModel(models.Model):
    name = models.CharField(max_length=128)
    user = models.ForeignKey(
        settings.AUTH_USER_MODEL,
        on_delete=models.CASCADE
    )
    
    class Meta:
        constraints = [
            models.UniqueConstraint(fields=('name', 'user'), name='unique_name_per_user')
        ]

В этом случае вы фильтруете набор запросов в форме с user с:

class MyModelForm(forms.ModelForm):
    code = NameChoiceField(queryset=MyModel.objects.order_by('name'))

    def __init__(self, *args, user=None, **kwargs):
        super().__init__(*args, **kwargs)
        if user is not None:
            self.field['code'].queryset = MyModel.objects.filter(
                user=user
            ).order_by('name')

где вы затем построите MyModelForm с помощью MyModelForm(user=request.user), например,

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