2014-03-06 36 views
4

按照Kevin Dias在this article中的说明,我尝试为两个相关模型生成一个表单。这似乎适用于一对多关系,但是我遇到了使用多对多关系的问题。对于多对多关系的嵌入式套件吊坠

下面是用户角色管理一些示例代码:

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

这些设置会导致错误信息<class 'rightmanagement.models.Role'> has no ForeignKey to <class 'rightmanagement.models.User'>

做一些研究我发现这个:Django inlineformset_factory and ManyToMany fields。似乎内嵌套件仅适用于ForeignKey,但不适用于ManyToManyField。也可以这样解释the docs

但是,我认为在特定情况下,外键而不是多对多关系是没有意义的。 Django内置内联formset的挂件对于多对多关系看起来如何?其目的是构建一个表单,允许将用户分配给已存在的角色或创建新角色,并在用户尚不存在时将其分配给用户。

回答

3

正如您可能知道的那样,您无法使用内嵌窗体组编辑多对多关系。但是,您可以编辑模型。因此,对于您的内联套件,您只需将模型设置为穿透模型,如下所示:

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

谢谢!这样做,我不再收到错误消息。但是,我可以在表单中添加*新角色吗?毕竟,角色模型既不包含在'forms.py'也不包含在'views.py'中。 – speendo