Django, сохранить ModelForm
Я создал модель Студент, которая простирается от Django User и является внешним ключом для другой модели, в то время как у нее есть целое поле, называемое year. Я пытаюсь сохранить форму, содержащую 2 поля. Один из них - это id курса, а другой - целое поле год. Когда я нажимаю submit, я получаю сообщение об ошибке Не могу назначить "u'2": "Student.course" должен быть экземпляром "Course".
models.py
class Student(models.Model):
user = models.OneToOneField(User)
course = models.ForeignKey(Course)
year = models.IntegerField(validators=[MinValueValidator(1),
MaxValueValidator(7)])
view.py
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
forms.py
class SelectCourseYear(forms.ModelForm):
course = forms.CharField()
year = forms.IntegerField(required=True)
class Meta:
model = Student
fields = ['user', 'course', 'year']
Ответы
Ответ 1
Вам не нужно переопределять поля в ModelForm
, если вы уже упоминали их в атрибуте fields
. Итак, ваша форма должна выглядеть так:
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
fields = ['course', 'year'] # removing user. we'll handle that in view
И мы можем легко обрабатывать форму в представлении -
def step3(request):
user = request.user
if request.method == 'POST':
form = SelectCourseYear(request.POST)
if form.is_valid():
student = form.save(commit=False)
# commit=False tells Django that "Don't send this to database yet.
# I have more things I want to do with it."
student.user = request.user # Set the user object here
student.save() # Now you can send it to DB
return render_to_response("registration/complete.html", RequestContext(request))
else:
form = SelectCourseYear()
return render(request, 'registration/step3.html',)
Ответ 2
course
должен быть экземпляром модели курса, а не только первичного ключа экземпляра. Вы все равно можете принять идентификатор в форме в виде текстового ввода, но вам нужно будет извлечь экземпляр фактического курса и присвоить значение.
Вам нужно проверить, что идентификатор курса действителен, поэтому включение этого кода в чистый метод - неплохая идея. Обратите внимание также, как поле course
исключено здесь? В противном случае форма ожидает, что она будет присутствовать. Вам также не нужно переопределять поле year, так как ModelForm наследует это поле от модели Student.
# forms.py
class SelectCourseYear(forms.ModelForm):
class Meta:
model = Student
exclude = ['user', 'course']
course_id = forms.IntegerField()
def __init__(self, *args, **kwargs):
self.user = kwargs.pop('user')
super(SelectCourseYear, self).__init__(*args, **kwargs)
def clean_course_id(self):
course_id = self.cleaned_data.get('course_id')
try:
self.course = Course.objects.get(pk=course_id)
except Course.DoesNotExist:
raise forms.ValidationError('Sorry, that course id is not valid.')
return course_id
def save(self, commit=True):
instance = super(SelectCourseYear, self).save(commit=False)
instance.course = self.course
instance.user = self.user
if commit:
instance.save()
return instance
# views.py
def step3(request):
if request.method == 'POST':
form = SelectCourseYear(request.POST or None, user=request.user)
if form.is_valid():
form.save()
return render_to_response("registration/complete.html",
RequestContext(request))
return render(request, 'registration/step3.html',)
Теперь, когда вы вызываете .save()
в модели, поле курса будет назначено экземпляр course