Как использовать 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), например,