Как справиться с ошибкой UniqueConstraint в Django Meta Class? - PullRequest
2 голосов
/ 05 июня 2019

Я создал метакласс UniqueConstraint для своей модели, и он работает, когда я тестирую его, намеренно создавая дубликат, но получаю страницу с ошибкой вместо того, чтобы перенаправляться обратно на исходную страницу.Куда мне вставить код, чтобы вернуться на страницу, на которой я только что находился?

Я предполагаю, что проблема в представлении, но я понятия не имею, какой код поместить туда, и документы Django не содержат ничегоссылаясь на эту проблему.

Модель:

class StudentScheduledClass(models.Model):
    student = models.ForeignKey("users.User", on_delete=models.CASCADE, db_column="Student")
    scheduled_class = models.ForeignKey("ScheduledClass", on_delete=models.CASCADE, db_column="ScheduledClass")
    grade = models.FloatField(db_column="Grade", blank=True, null=True)

    class Meta:
        managed = True
        db_table = "StudentScheduledClass"
        verbose_name_plural = "StudentsScheduledClasses"
        constraints = [
            models.UniqueConstraint(fields=['student', 'scheduled_class'], name='student scheduled class restraint')
        ]

Просмотр:

class StudentScheduledClassCreateView(LoginRequiredMixin, CreateView):
    model = StudentScheduledClass
    context_object_name = "student_scheduled_class"
    fields = ["student"]

    def form_valid(self, form):
        scheduled_class = self.kwargs["scheduled_class"]
        form.instance.scheduled_class = ScheduledClass(scheduled_class)
        return super().form_valid(form)

    def get_success_url(self):
        scheduled_class = self.kwargs["scheduled_class"]
        return reverse("scheduled-class-detail", args={scheduled_class})

Я хотел бы просто вернуться на исходную страницу с сообщением об ошибке,вместо этого я получаю эту ошибку целостности:

IntegrityError at /classes/student_scheduled_class_create/1/
UNIQUE constraint failed: StudentScheduledClass.Student, StudentScheduledClass.ScheduledClass
Request Method: POST
Request URL:    http://localhost:8000/classes/student_scheduled_class_create/1/
Django Version: 2.2.2
Exception Type: IntegrityError
Exception Value:    
UNIQUE constraint failed: StudentScheduledClass.Student, StudentScheduledClass.ScheduledClass

Ответы [ 2 ]

1 голос
/ 05 июня 2019

Ваша форма требует только поля student, поэтому она действительна, потому что вы не указали для ее экземпляра значение scheduled_class, когда она будет проверена.

Вы должны инициализировать форму с instanceдля которого scheduled_class уже установлено.Вы можете сделать это в get_form_kwargs() или, поскольку этот метод передает self.object как instance, вы можете сделать это еще проще в post():

def post(self, request, *args, **kwargs):
    self.object = StudentScheduledClass(scheduled_class=kwargs['scheduled_class'])
    return super().post(request, *args, **kwargs)

В качестве альтернативы, хотя и немного менее чисто(Мне нравится думать, что после вызова form_valid() все должно быть в порядке):

def form_valid(self, form):
    scheduled_class = self.kwargs["scheduled_class"]
    form.instance.scheduled_class = ScheduledClass(scheduled_class)
    try:
        return super().form_valid(form)
    except IntegrityError:
        return self.form_invalid(form)

Проблема с последней заключается в том, что в форме не будет отображаться никаких ошибок, поэтому вы должнывероятно, вы хотите добавить сообщение Django в self.request перед возвратом (при условии, что вы отображаете любое сообщение в своем шаблоне).

0 голосов
/ 05 июня 2019

Это код, который я использовал в итоге:

Вид:

class StudentScheduledClassCreateView(LoginRequiredMixin, CreateView):
    model = StudentScheduledClass
    context_object_name = "student_scheduled_class"
    fields = ["student"]

    def form_valid(self, form):
        try:
            scheduled_class = self.kwargs["scheduled_class"]
            form.instance.scheduled_class = ScheduledClass(scheduled_class)
            return super().form_valid(form)
        except IntegrityError as error:
            scheduled_class = self.kwargs["scheduled_class"]
            return self.form_invalid(form)

    def get_success_url(self):
        scheduled_class = self.kwargs["scheduled_class"]
        return reverse("scheduled-class-detail", args={scheduled_class})

Модель осталась прежней:

class StudentScheduledClass(models.Model):
    student = models.ForeignKey("users.User", on_delete=models.CASCADE, db_column="Student")
    scheduled_class = models.ForeignKey("ScheduledClass", on_delete=models.CASCADE, db_column="ScheduledClass")
    grade = models.FloatField(db_column="Grade", blank=True, null=True)

    class Meta:
        managed = True
        db_table = "StudentScheduledClass"
        verbose_name_plural = "StudentsScheduledClasses"
        constraints = [
            models.UniqueConstraint(fields=['student', 'scheduled_class'], name='student scheduled class restraint')
        ]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...