为多对多关系形成、创建和更新视图

Posted

技术标签:

【中文标题】为多对多关系形成、创建和更新视图【英文标题】:Form, Create and Update View for Many-To-Many Relationship 【发布时间】:2015-03-24 08:40:45 【问题描述】:

这是我在这里的第一个问题,我正在写作是因为我对此感到很生气,即使在阅读了文档和这里的很多答案之后也是如此。非常感谢你,对不起我的英语不好!

我有这些模型:

class Profile(models.Model):
    name = models.CharField(max_length = 255, blank = False)
    user = models.ForeignKey(User, blank = True, null = True)

class Category(models.Model):
    name = models.CharField(max_length = 50, blank = False)

class ProfileCategory(models.Model):
    profile = models.ForeignKey(Profile)
    category = models.ForeignKey(Category)

    class Meta:
        unique_together = ('profile', 'category')

这个模型正确吗? 我想已经保存了类别的数据库。我需要一个页面,用户可以在其中创建新配置文件并从复选框列表中选择类别。我应该在同一页面中使用两个表单,一个用于个人资料,一个用于选择类别还是一个表单?我想我需要一个 ModelMultipleChoiceField 类别。 我还需要一个视图,该视图显示已填入配置文件的相同表单以及用户可以更改配置文件名称以及添加或删除类别的类别。

如果您需要更多信息,请告诉我,非常感谢。

【问题讨论】:

欢迎来到 Stack Overflow!如果您指定您发布的代码片段出了什么问题,您将在此处获得更好的帮助 - 您是否尝试过创建模型?发生了什么?发生了什么故障/行为不符合您的预期? 是的,我创建了模型。 1)我不知道模型是否正确。 2) 我不知道如何为 ProfileCategory 模型创建正确的表单 3) 我认为 ProfileCategory 模型中的类别字段是 ModelMultipleChoiceField 字段,但我不知道如何在插入或更新的情况下使用该字段查看。 【参考方案1】:

ProfileCategory 模型在这里是不必要的。使用ManyToMany 字段可以达到同样的效果:

class Category(models.Model):
    name = models.CharField(max_length=50, blank=False)

class Profile(models.Model):
    name = models.CharField(max_length=255, blank=False)
    user = models.ForeignKey(User, blank=True, null=True)
    categories = models.ManyToManyField(Category, blank=True)

现在您可以像任何其他模型一样使用单个表单来编辑配置文件。您唯一应该记住的是调用save_m2m(),以防您覆盖表单的save() 方法。

app/forms.py

from django import forms
from app.models import Profile

class ProfileForm(forms.ModelForm):
    class Meta:
        model = Profile
        widgets = 
            'categories': forms.CheckboxSelectMultiple,
        

app/views.py

从 django.views.generic.edit 导入 CreateView

from app.forms import ProfileForm
from app.models import Profile

class ProfileCreate(CreateView):
    form_class = ProfileForm
    model = Profile

templates/app/profile_form.html

<form action="" method="post">
    % csrf_token %
     form.as_p 
    <input type="submit" value="Create" />
</form>

app/urls.py

from app.views import ProfileCreate

urlpatterns = patterns('',
    ...
    url(r'^profile/create/', ProfileCreate.as_view()),
)

要更新配置文件,请使用具有相同 ProfileForm 类和模板的 UpdateView。

编辑:如果您需要 ProfileCategory 模型中的其他字段,则可以使用 ManyToManyField 的 through 参数将其设置为中间模型。要编辑此类模型,您必须使用表单集。阅读更多关于它的信息here、here 和 here。

【讨论】:

非常感谢您!这就像一个魅力,我认为这个解决方案比我的更好。因此,如果我的多对多关系中没有任何字段,在这种情况下我不需要第三个模块(ProfileCategory)。但是如果我有这个第三个模型,我可以使用一个表单和 save_m2m( )?我对此感到困惑..你能给我一个例子吗?谢谢。 使用中间模型,事情变得更加复杂。查看更新后的答案。 有效!但在前端,它显示的是Category object,而不是类别的名称。

以上是关于为多对多关系形成、创建和更新视图的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET MVC 4、EF 和 LINQ:为多对多关系创建特定的 LINQ 查询

将 jQuery 数据从 View 传递到 Controller 并将其保存为多对多

如何在不破坏范式的情况下为多对多关系构建连接表

如何在 Rails 中为多对多关系(和中间表)做一个选择字段?

将表拆分为多对多关系:数据迁移

在 Sequelize.js 中为多对多关系添加默认角色