本文介绍了吊坠到内联形式的多对多关系的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

遵循Kevin Dias在。似乎内联表单仅适用于 ForeignKey 但不是 ManyToManyField 。另外可以这样解释。



然而,我认为在特定情况下是外键而不是多对多许多关系没有任何意义。 Django的内置内联格式的吊坠如何看起来像多对多的关系?目的是构建一个表单,允许将用户分配给已经存在的角色或创建新角色,并将其分配给用户(如果尚不存在)。

解决方案

您可能知道,您无法使用内联表单来编辑多对多关系。但是,您可以编辑通过模型。因此,对于您的内联表单,您只需要将模型设置为直通模型,如下所示:

  RoleFormSet = inlineformset_factory(UserRole ,User.role.though)


Following Kevin Dias instructions in this article, I try to generate one form for two related models. This seems to work for one-to-many relations, however I run into problems using many-to-many relations.

Here is some example code for a user-role management:

#models.py
from django.db import models

class Role(models.Model): # for each role there can be multiple users
    role_name=models.CharField(max_length=20)

class User(models.Model): # each user can have multiple roles
    name=models.CharField(max_length=20)
    role=models.ManyToManyField(Role, through='UserRole')

class UserRole(models.Model): # table to store which user has which roles
    role=models.ForeignKey(Role)
    user=models.ForeignKey(User)

# forms.py
from django.forms import ModelForm
from django.forms.models import inlineformset_factory

from rightmanagement.models import Role, User

class UserForm(ModelForm):
    class Meta:
        model = User

RoleFormSet = inlineformset_factory(User, Role) # this is probably the line that causes the problem

# views.py
from django.http import HttpResponseRedirect
from rightmanagement.models import User
from rightmanagement.forms import RoleFormSet, UserForm

# Create view
from django.views.generic import CreateView
class UserCreate(CreateView):
    model = User
    form_class = UserForm

def get(self, request, *args, **kwargs):
        """
        Handles GET requests and instantiates blank versions of the form
        and its inline formsets.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        role_form = RoleFormSet()
        return self.render_to_response(
            self.get_context_data(form=form,
                                  role_form=role_form))

def post(self, request, *args, **kwargs):
        """
        Handles POST requests, instantiating a form instance and its inline
        formsets with the passed POST variables and then checking them for
        validity.
        """
        self.object = None
        form_class = self.get_form_class()
        form = self.get_form(form_class)
        role_form = RoleFormSet(self.request.POST)
        if (form.is_valid() and role_form.is_valid()):
            return self.form_valid(form, role_form)
        else:
            return self.form_invalid(form, role_form)

def form_valid(self, form, role_form):
        """
        Called if all forms are valid. Creates a Recipe instance along with
        associated Ingredients and Instructions and then redirects to a
        success page.
        """
        self.object = form.save()
        role_form.instance = self.object
        role_form.save()
        return HttpResponseRedirect(self.get_success_url())

def form_invalid(self, form, role_form):
        """
        Called if a form is invalid. Re-renders the context data with the
        data-filled forms and errors.
        """
        return self.render_to_response(
            self.get_context_data(form=form,
                                  role_form=role_form))

These settings lead to the error message <class 'rightmanagement.models.Role'> has no ForeignKey to <class 'rightmanagement.models.User'>.

Doing some research I found this: Django inlineformset_factory and ManyToMany fields. It seems like inline formsets are only for ForeignKey but not for ManyToManyField. Also the docs can be interpreted like this.

However, I think in the particular case a foreign key instead of a many-to-many relation wouldn't make any sense. How would a pendant to Django's built-in inline formset look like for many-to-many relations? The aim would be to build a form that allows to either assign the user to roles that already exist or create new roles and assign them to the user if they do not exist yet.

解决方案

As you're probably aware, you can't edit many-to-many relationships with inline formsets. You can, however, edit the through model. So for your inline formset, you just need to set the model to the through model, like so:

RoleFormSet = inlineformset_factory(UserRole, User.role.though)

这篇关于吊坠到内联形式的多对多关系的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-30 00:38