I want to use queryset
with distinct()
to avoid duplication value in label_from_instance
.
But then I have an error like below.
'str' object has no attribute 'name'
How could I use queryset
with distinct()
in label_from_instance
?
Here are the code in forms.py:
from django.forms import ModelChoiceField
class NameChoiceField(ModelChoiceField):
def label_from_instance(self, obj):
return f'{obj.name}'
class MyModelForm(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
CodePudding user response:
How could I use queryset with
distinct()
in label_from_instance?
You don't. Imagine that you use .distinct()
and thus got unique names and a person selects an option "foo", if there are multiple MyModel
s with "foo" as name, then which one should be selected: by making a distinct, you thus "destroy" the way to backlink to the original item. The label should be sufficient to canonically specify what model item to use.
You should fix the problem at the other end: preventing that one can use multiple MyModel
s with the same name
, you can mark the name
field as unique and thus work with:
class MyModel(models.Model):
name = models.CharField(max_length=128, unique=True)
# …
It is also possible that items should be unique per user for example. In that case you construct a UniqueConstraint
[Django-doc] with:
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')
]
In that case you filter the queryset in the form with the user
with:
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')
where you then construct the MyModelForm
with MyModelForm(user=request.user)
for example.