Save new foreign key with django form

前端 未结 2 1306
傲寒
傲寒 2020-12-24 00:08

I have two models:

class Studio(models.Model):
    name = models.CharField(\"Studio\", max_length=30, unique=True)

class Film(models.Model):
    studio = mo         


        
相关标签:
2条回答
  • I stumbled across this question and I think I got a better answer for future seekers.

    Django comes with something called Inline Formsets which helps you manage relationships in a form.

    You just have to create your model like you did with their respective ForeignKeys. Then in the Forms.py import this

    from django.forms.models import inlineformset_factory
    

    Then:

    YOUR_FORMSET = inlineformset_factory(Model1,Model2)
    

    Back on yout views.py you should import both your Form and your new created YOUR_FORMSET.

    After doing this, your method should use the inlineformset like this:

    def add_question(request):
    
        if request.method == 'POST':
    
    
          form =AddQuestionForm(request.POST, request.FILES)
          if form.is_valid():
              new_question = form.save(commit=False)
    
              question_formset = QuestionFormset(request.POST, instance=new_question)
              if question_formset.is_valid():
                  form.save()
                  question_formset.save()
                  return HttpResponseRedirect(reverse('polls:detail',args=(new_question.pk,)))
          else:
              print(form.errors)
        else:
            form = AddQuestionForm()
            question_formset = QuestionFormset(instance=Question())
        return render(request, 'polls/add.html', {'form':form, 'question_formset':question_formset,})
    

    I'm using my own example but the idea is explained.

    If you want to read a more specific explication read this awesome blog post that I found.

    0 讨论(0)
  • 2020-12-24 00:32

    Really, your only problem is that you've used a standard Form instead of a ModelForm. Form doesn't have a save method because it's not inherently tied to anything (i.e. it doesn't know what to save or where to save to).

    However, if you use a ModelForm you need to take care of all logic involved in creating a new studio in the form. This is actually better, though, because then you can just use the form and not worry about anything else: the form holds all the logic needed to properly save itself.

    class FilmForm(forms.ModelForm):
        class Meta:
            model = Film
    
        # only need to define `new_studio`, other fields come automatically from model
        new_studio = forms.CharField(max_length=30, required=False, label = "New Studio Name")
    
        def __init__(self, *args, **kwargs):
            super(FilmForm, self).__init__(*args, **kwargs)
            # make `studio` not required, we'll check for one of `studio` or `new_studio` in the `clean` method
            self.fields['studio'].required = False
    
        def clean(self):
            studio = self.cleaned_data.get('studio')
            new_studio = self.cleaned_data.get('new_studio')
            if not studio and not new_studio:
                # neither was specified so raise an error to user
                raise forms.ValidationError('Must specify either Studio or New Studio!')
            elif not studio:
                # get/create `Studio` from `new_studio` and use it for `studio` field
                studio, created = Studio.objects.get_or_create(name=new_studio)
                self.cleaned_data['studio'] = studio
    
            return super(FilmForm, self).clean()
    

    Then, in your view, all you need is:

    if form.is_valid():
        form.save()
    
    0 讨论(0)
提交回复
热议问题