use two models in a single view that you can save and edit in django

Viewed 271

lovers of zero and one. How can I make a view have two forms with two different models but saving one form doesn't affect the other?

two models in one views

try to use a modelform use it in a single view. but I would like to know how to solve it or the best practice for these cases.

3 Answers

You can use the name attribute of the button on the form. For example;

<form>
...
<input type="submit" name="save-user" value="Save user" />
</form>
<form>
...
<input type="submit" name="save-category" value="Save category" />
</form>

Then in python you can detect which button was clicked like this;

if 'save-user' in request.POST:
    # save the user
elif 'save-category' in request.POST:
    # save the category

Okay so you want to show up two different forms in template and save them individually to database.

For me I usually stick to the simplest way and best way for me so far.

Here's it, take this one as an example

def update_profile(request):
    if request.method == 'POST':
        user_form = UserForm(request.POST, instance=request.user)
        profile_form = ProfileForm(request.POST, instance=request.user.profile)
        if user_form.is_valid() and profile_form.is_valid():
            user_form.save()
            profile_form.save()
            # redirect to somewhere else

        else:
            # message.error
    user_form = UserForm(instance=request.user)
    profile_form = ProfileForm(instance=request.user.profile)
return render(request, 'profiles/profile.html', {
    'user_form': user_form,
    'profile_form': profile_form
})

Django is very smart handling ModelForms, after performing a number of behind the scene validation when

form.is_valid()

Is called.

It'll will save fields that were changed and leave out those with no changes.

Here's template render of the forms

<form method="post">
{% csrf_token %}
{{ user_form.as_p }}
{{ profile_form.as_p }}
<button type="submit">Save changes</button>
</form>

And here's the forms.oh

class UserForm(forms.ModelForm):
    class Meta:
        model = User
        fields = ('first_name', 'last_name', 'email')

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        fields = ('url', 'location', 'company')

Like I mentioned earlier, Django is smart enough to handle your ModelForms as long as you call it's form.is_valid() it'll will do the lifting for you.

This has been an easier approach for me

If you want something more controlled Check out Django Formset

create two Models and use it in the ModelForm:

class UserUpdateForm(ModelForm):

    class Meta:
        model = User
        fields = ["username", "email", "phone_number", "bioghraphy", "avatar"]

class AddressForm(ModelForm):
    class Meta:
        model = Address
        fields = "__all__"

in views.py:

class AccountFormView(TemplateView):
      ...

  def post(self, request, *args, **kwargs):

    user_form = UserUpdateForm(
        request.POST, prefix="user", instance=self.get_object()
    )
    address_form = AddressForm(
        request.POST, prefix="address", instance=self.get_object_address()
    )

    if user_form.is_valid():
        user_form.save()
        return HttpResponseRedirect(
            reverse_lazy(
                "neeko.apps.accounts:accounts-landing",
                kwargs={"pk": self.get_object().pk},
            )
        )

    if address_form.is_valid():
        address_form.save()
        return HttpResponseRedirect(
            reverse_lazy(
                "neeko.apps.accounts:accounts-landing",
                kwargs={"pk": self.get_object().pk},
            )
        )

    return self.render_to_response(
        self.get_context_data(user_form=user_form, address_form=address_form)
    )

Template:

<form method="post">
    {% csrf_token %}
    {{ user_form.as_p }}
<button type="submit">form 1</button>
</form>
<h1>form segin</h1>

<form method="post">
    {% csrf_token %}
    {{ address_form.as_p }}
    <button type="submit">form 2 </button>
</form>

example

https://gist.github.com/josuedjh3/7ea29c70a0167ff34a1216edb5dbed05

Related