问题
I need to check if a user exists before saving a form. The fields are name, surname, and a role which can have one or many values. How can I do that?
def save(self, commit=True):
profile = super(ProfileForm, self).save(commit=False)
first_name = self.cleaned_data['first_name']
surname = self.cleaned_data['surname']
role = self.cleaned_data['role']
if Profile.objects.filter(first_name=self.cleaned_data['first_name'], surname=self.cleaned_data['surname']).exists()
raise forms.ValidationError("This profile already exists")
elif commit:
profile.save()
Profile.objects.filter(first_name=self.cleaned_data['first_name'], surname=self.cleaned_data['surname'], role__in[role]).exists()
gives me invalid syntax
error. Of course I want to check if name & surname & role are all present within the same profile.
My models
class Role(models.Model):
type= models.CharField(max_length=30)
def __str__(self):
return self.type
class Profile(models.Model):
first_name = models.CharField(max_length=120, null=True, blank=True)
surname = models.CharField(max_length=120, null=True, blank=True)
role = models.ManyToManyField(Role, blank=True)
回答1:
Pleasde do not check this in the form, you can check this in the model. Indeed, you can implement this with a UniqueConstraint [Django-doc]:
class Profile(models.Model):
first_name = models.CharField(max_length=128)
surname = models.CharField(max_length=128)
role = models.CharField(max_length=128)
class Meta:
constraints = [
models.UniqueConstraint(
field=['first_name', 'last_name', 'role'],
name='unique_name_and_role'
)
]
The validation is done automatically in the ModelForm
, so no need to worry about that, and this will also be enforced at the database level (if your database supports that).
Prior to django-2.2, you can specify unique_together [Djanog-doc]:
class Profile(models.Model):
first_name = models.CharField(max_length=128)
surname = models.CharField(max_length=128)
role = models.CharField(max_length=128)
class Meta:
unique_together = [['first_name', 'last_name', 'role']]
In case it is a ManyToManyField
, you better enforce this at the .clean(..)
method of the Profile
model:
class ProfileForm(forms.ModelForm):
# …
def clean(self):
cleaned_data = super().clean()
first_name = self.cleaned_data['first_name']
surname = self.cleaned_data['surname']
role = self.cleaned_data['role']
if Profile.objects.exclude(pk=self.instance.pk).filter(
first_name=first_name,
surname=surname,
role__in=role
).exists():
raise ValidationError('A profile already exists.')
return cleaned_data
In the view, you can then for example handle this with:
def my_view(request):
if request.method == 'POST':
form = ProfileForm(request.POST, request.FILES)
if form.is_valid():
# …
else:
return HttpResponseBadRequest('invalid data')
# …
回答2:
invalid syntax is because of missing '=' sign after __in. It should be something like below
Profile.objects.filter(first_name=self.cleaned_data['first_name'], surname=self.cleaned_data['surname'], role__in=self.cleaned_data[role]).exists()
来源:https://stackoverflow.com/questions/61826009/filter-queryset-with-multiple-checks-including-value-is-in-array-in-a-django-vi