Проверка Django ModelForm unique_together

У меня есть модель Джанго, которая выглядит следующим образом.

class Solution(models.Model):
    '''
    Represents a solution to a specific problem.
    '''
    name = models.CharField(max_length=50)
    problem = models.ForeignKey(Problem)
    description = models.TextField(blank=True)
    date = models.DateTimeField(auto_now_add=True)

    class Meta:
        unique_together = ("name", "problem")

Я использую форму для добавления моделей, которая выглядит следующим образом:

class SolutionForm(forms.ModelForm):
    class Meta:
        model = Solution
        exclude = ['problem']

Моя проблема в том, что SolutionForm не проверяет ограничение Solution unique_together и, таким образом, возвращает IntegrityError при попытке сохранить форму. Я знаю, что мог бы использовать validate_unique для ручной проверки этого, но мне было интересно, есть ли способ поймать это в проверке формы и автоматически вернуть ошибку формы.

Спасибо.

57
задан 26 January 2010 в 20:01

2 ответа

Мое решение базируется от Django 2.1

, Оставляют SolutionForm в покое, имеют сохранение (), метод в Решении

class Solution(models.Model):
...
   def save(self, *args, **kwargs):
      self.clean()
      return super(Solution, self).save(*args, **kwargs)


  def clean():
      # have your custom model field checks here
      # They can raise Validation Error

      # Now this is the key to enforcing unique constraint
      self.validate_unique()

, Звоня full_clean () в сохранении () не работает, поскольку ValidationError будет не обработан

0
ответ дан 1 November 2019 в 16:50

Я должен был исключить company поле в моем случае и добавить его в представлении form_valid функция. Я закончил тем, что делал следующее (берущий вдохновение из различных ответов). В моем CreateView

    def form_valid(self, form):
        cleaned_data = form.cleaned_data
        user_company = self.request.user.profile.company
        if UnitCategory.objects.filter(code=cleaned_data['code'],
                                    company=user_company).exists():
            form.add_error('code',                           _(
                'A UnitCategory with this Code already exists for this company.'))
            return super(UnitCategoryCreateView, self).form_invalid(form)
        if UnitCategory.objects.filter(color=cleaned_data['color'],
                                    company=user_company).exists():
            form.add_error('color',                           _(
                'A UnitCategory with this Color already exists for this company.'))
            return super(UnitCategoryCreateView, self).form_invalid(form)
        form.instance.company = user_company
        return super(UnitCategoryCreateView, self).form_valid(form)

В моем UpdateView я должен был исключить текущий экземпляр объекта в проверке, если запрос существует с помощью exclude(pk=self.kwargs['pk'])

    def form_valid(self, form):
        cleaned_data = form.cleaned_data
        user_company = self.request.user.profile.company
        if UnitCategory.objects.filter(code=cleaned_data['code'],
                                       company=user_company).exclude(pk=self.kwargs['pk']).exists():
            form.add_error(
                'code', _('A UnitCategory with this Code already exists for this company.'))
            return super(UnitCategoryUpdateView, self).form_invalid(form)
        if UnitCategory.objects.filter(color=cleaned_data['color'],
                                       company=user_company).exclude(pk=self.kwargs['pk']).exists():
            form.add_error('color', _(
                'A UnitCategory with this Color already exists for this company.'))
            return super(UnitCategoryUpdateView, self).form_invalid(form)
        # Return form_valid if no errors raised
        # Add logged-in user's company as form's company field
        form.instance.company = user_company
        return super(UnitCategoryUpdateView, self).form_valid(form)

Не самое чистое решение, я надеялся на, но думал, что это могло бы принести пользу кому-то.

0
ответ дан 1 November 2019 в 16:50

Другие вопросы по тегам:

Похожие вопросы: