Уникальная проверка трудно получить полностью правильно, поэтому я бы рекомендовал использовать ModelForm в любом случае:
class EditUserProfileForm(forms.ModelForm):
# "notifications" are created from a different model, not the UserProfile
notifications = forms.MultipleChoiceField(
label="Email Notifications",
required=False,
widget=forms.CheckboxSelectMultiple,)
class Meta:
model = UserProfile
fields = ('display_name',)
Создать форму из нескольких моделей непросто, но в этом случае вы можете просто добавить поле notifications
в ModelForm и вытянуть его из .cleaned_data
как обычно:
# view
if request.method == 'POST':
form = EditUserProfileForm(request.POST, instance=user_profile)
if form.is_valid():
user_profile = form.save()
notifications = form.cleaned_data['notifications']
# Do something with notifications.
Вот как я бы это сделал, но если вы настроены на проверку уникальности самостоятельно, вы всегда можете сделать что-то вроде:
def clean_display_name(self):
display_name = self.cleaned_data['display_name']
if UserProfile.objects.filter(display_name=display_name).count() > 0:
raise ValidationError('This display name is already in use.')
return display_name
Здесь я вижу две проблемы. Во-первых, вы можете столкнуться с проблемами параллелизма, когда два человека отправляют одно и то же имя, оба проходят уникальные проверки, но затем один получает ошибку БД. Другая проблема заключается в том, что вы не можете редактировать профиль пользователя, потому что у вас нет идентификатора, который нужно исключить из поиска. Вы должны сохранить его в своем __init__
, а затем использовать его для очистки:
def __init__(self, *args, **kwargs):
...
if 'instance' in kwargs:
self.id = kwargs['instance'].id
...
def clean_display_name(self):
display_name = self.cleaned_data['display_name']
qs = UserProfile.objects.filter(display_name=display_name)
if self.id:
qs = qs.exclude(pk=self.id)
if qs.count() > 0:
raise ValidationError('This display name is already in use.')
return display_name
Но в этот момент вы просто дублируете логику в ModelForms.