web-dev-qa-db-fra.com

Django, enregistrez ModelForm

J'ai créé un modèle Student qui s'étend de Django User et est une clé étrangère vers un autre modèle alors qu'il a un champ entier appelé year. Ce que j'essaie de faire, c'est d'enregistrer un formulaire qui comporte 2 champs. L'un est le id du cours et l'autre est le champ entier année. Lorsque je clique sur Soumettre, je reçois une erreur Impossible d'attribuer "u'2 '": "Student.course" doit être une instance de "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']
21
manosim

Vous n'avez pas besoin de redéfinir les champs de ModelForm si vous les avez déjà mentionnés dans l'attribut fields. Votre formulaire devrait donc ressembler à ceci -

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

Et nous pouvons gérer le formulaire avec facilité dans la vue -

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',)
41
Bibhas Debnath

course doit être une instance d'un modèle de cours, pas seulement la clé primaire de l'instance. Vous pouvez toujours accepter un identifiant dans le formulaire comme entrée de texte, mais vous devrez récupérer l'instance de cours réelle et attribuer la valeur.

Vous devrez vérifier que l'ID du cours est valide, donc mettre ce code dans la méthode propre n'est pas une mauvaise idée. Remarquez également comment le champ course est exclu ici? Sinon, le formulaire s'attendra à ce qu'il soit présent. Vous n'avez pas non plus besoin de redéfinir le champ année, car ModelForm héritera de ce champ du modèle 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',)

Maintenant, lorsque vous appelez .save() sur le modèle, le champ de cours se verra attribuer une instance de Course

4
Brandon