Django ModelChoiceField передает None

Я очень новичок в Django.
Я делаю форму для добавления расписания в определенный филиал.
Поэтому у меня есть модель 'Branch' и модель 'Timetable'.
Модель 'Branch' находится в приложении 'branches', а модель 'Timetable' находится в приложении 'schedules'.
Я ожидаю, что когда пользователи заполнят форму для добавления расписания, они смогут выбрать филиал для добавления из поля выбора.

Вот мои коды
branches/models.py

from django.core.validators import RegexValidator
from django.db import models
from django.urls import reverse

# Create your models here.
phone_validator = RegexValidator(
    regex="\d{2,4}-?\d{3,4}(-?\d{4})?",
    message="It's not correct phone number format.",
)


class Branch(models.Model):
    srl = models.BigAutoField(primary_key=True, verbose_name="Serial")
    name = models.TextField(verbose_name="Branch name")
    postcode = models.CharField(max_length=5, verbose_name="Postcode")
    address1 = models.TextField(verbose_name="Road address")
    address2 = models.TextField(verbose_name="Detail address", blank=True)
    phone1 = models.CharField(max_length=13, validators=[phone_validator], verbose_name="Phone 1")
    phone2 = models.CharField(max_length=13, validators=[phone_validator], verbose_name="Phone 2", blank=True)
    is_opened = models.BooleanField(default=True, verbose_name="Is opened?")

    class Meta:
        verbose_name = "Branch"
        verbose_name_plural = "Branches"
        ordering = ["srl"]

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse("branches:detail", kwargs={"srl": self.srl})

schedules/models.py

import datetime

from django.conf import settings
from django.db import models


class Timetable(models.Model):
    srl = models.BigAutoField(
        primary_key=True,
        verbose_name="Serial",
    )
    branch_srl = models.ForeignKey(
        "branches.Branch",
        on_delete=models.CASCADE,
        verbose_name="Branch Serial",
    )
    period = models.DecimalField(
        max_digits=2,
        decimal_places=0,
        verbose_name="Period",
    )
    period_length = models.DurationField(
        default=datetime.timedelta(minutes=50),
        verbose_name="Period Length",
    )
    is_holiday = models.BooleanField(
        default=False,
        verbose_name="Is holiday?",
    )
    start_time = models.TimeField(
        default=datetime.time(10, 00),
        verbose_name="Start time",
    )
    end_time = models.TimeField(
        default=datetime.time(23, 00),
        verbose_name="End time",
    )

schedules/forms.py

from django import forms
from django.forms import ModelChoiceField, ModelForm

from branches.models import Branch
from schedules.models import Schedule, Timetable


class TimetableForm(ModelForm):
    branch_choices = ModelChoiceField(
        queryset=Branch.objects.all(),
        required=True,
        label="Branch",
        widget=forms.Select(attrs={"class": "form-select"}),
    )

    class Meta:
        model = Timetable
        fields = (
            "branch_choices",
            "period",
            "period_length",
            "is_holiday",
            "start_time",
            "end_time",
        )
        labels = {
            "period": "Period",
            "period_length": "Period Length",
            "is_holiday": "Is Holiday?",
            "start_time": "Start Time",
            "end_time": "End Time",
        }
        widgets = {
            "period": forms.NumberInput(attrs={"class": "form-control"}),
            "period_length": forms.TimeInput(
                format="%H:%M:%S",
                attrs={
                    "class": "form-control",
                },
            ),
            "is_holiday": forms.RadioSelect(
                choices=[(True, "Yes"), (False, "No")],
                attrs={
                    "class": "form-check-input",
                },
            ),
            "start_time": forms.TimeInput(
                attrs={
                    "type": "time",
                    "class": "form-control",
                },
            ),
            "end_time": forms.TimeInput(
                attrs={
                    "type": "time",
                    "class": "form-control",
                },
            ),
        }

Сообщение об ошибке вот такое
. Сообщение об ошибке из режима отладки Django

Более простой способ установки связанных с кверисетом вариантов на форме модели - это переопределение метода __init__() формы, а не создание поля формы вручную.

class TimetableForm(ModelForm):
    ...

    def __init__(self, *args, **kwargs):
        self.branches = Branch.objects.all()
        super(TimetableForm, self).__init__(*args, **kwargs)
        self.fields['branch_srl'].queryset = self.branches
<<<Кроме того, поскольку вы используете

, многие метки и определения полей должны быть автоматическими на основе того, что вы определили в модели. Старайтесь избегать повторения этих деклараций, если вы можете этого избежать.ModelForm

Благодаря CodenameTim с Django Forum, я нашел решение
. Поэтому я скопировал решение ниже для тех, кто испытывает ту же проблему.

Ошибка говорит, что поле branch_srl является нулевым при вставке, поэтому оно нарушает NOT NULL CONSTRAINT. Если вы проверите свою форму, то форма не использует это поле, а вместо него используется branch_choices. Вам нужно сопоставить выбранное значение для этого поля с branch_srl где-нибудь. Это может быть в TimetableForm.save(), AddTimetableView.form_valid() или вы можете переименовать поле branch_choices в branch_srl, чтобы оно сохранилось в базе данных.

Вернуться на верх