Django, guarda ModelForm

He creado un modelo de Estudiante que se extiende desde el Usuario de Django y es una clave externa para otro modelo, mientras que tiene un campo entero llamado año. Lo que estoy tratando de hacer es guardar un formulario, que tiene 2 campos. El uno es el ID del curso y el otro es el año del campo del número entero. Cuando hago clic en enviar, aparece un error. No se puede asignar “u’2 ‘”: “Student.course” debe ser una instancia de “Curso”.

modelos.py

class Student(models.Model): user = models.OneToOneField(User) course = models.ForeignKey(Course) year = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(7)]) 

ver.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'] 

No es necesario que ModelForm a definir los campos en ModelForm si ya los ha mencionado en el atributo fields . Así que tu forma debería verse así:

 class SelectCourseYear(forms.ModelForm): class Meta: model = Student fields = ['course', 'year'] # removing user. we'll handle that in view 

Y podemos manejar el formulario con facilidad en la vista –

 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',) 

course debe ser una instancia de un modelo de curso, no solo la clave principal de la instancia. Aún puede aceptar una identificación en el formulario como una entrada de texto, pero tendrá que recuperar la instancia del curso real y asignar el valor.

Deberá verificar que la identificación del curso sea válida, por lo que poner ese código en el método de limpieza no es una mala idea. Observe también cómo el campo del course se excluye aquí? De lo contrario, la forma esperará que esté presente. Tampoco es necesario que vuelva a definir el campo del año, ya que ModelForm heredará ese campo del modelo de Estudiante.

 # 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',) 

Ahora, cuando llama a .save() en el modelo, al campo del curso se le asignará una instancia de Course