当前位置: 首页 > 面试题库 >

Django ModelForm用于多对多字段

隗轶
2023-03-14
问题内容

考虑以下模型和形式:

class Pizza(models.Model):
    name = models.CharField(max_length=50)

class Topping(models.Model):
    name = models.CharField(max_length=50)
    ison = models.ManyToManyField(Pizza, blank=True)

class ToppingForm(forms.ModelForm):
    class Meta:
        model = Topping

当你查看ToppingForm时,它使你可以选择浇头所用的披萨,而一切都太花哨了。

我的问题是:如何为披萨定义一个ModelForm,让我利用披萨和馅料之间的多对多关系,并让我选择披萨上的馅料?


问题答案:

我想你会在这里新添加ModelMultipleChoiceField到你PizzaForm,并手动链接,表单字段与模型领域,如Django会不会为你做自动。

以下代码段可能会有所帮助:

class PizzaForm(forms.ModelForm):
    class Meta:
        model = Pizza

    # Representing the many to many related field in Pizza
    toppings = forms.ModelMultipleChoiceField(queryset=Topping.objects.all())

    # Overriding __init__ here allows us to provide initial
    # data for 'toppings' field
    def __init__(self, *args, **kwargs):
        # Only in case we build the form from an instance
        # (otherwise, 'toppings' list should be empty)
        if kwargs.get('instance'):
            # We get the 'initial' keyword argument or initialize it
            # as a dict if it didn't exist.                
            initial = kwargs.setdefault('initial', {})
            # The widget for a ModelMultipleChoiceField expects
            # a list of primary key for the selected data.
            initial['toppings'] = [t.pk for t in kwargs['instance'].topping_set.all()]

        forms.ModelForm.__init__(self, *args, **kwargs)

    # Overriding save allows us to process the value of 'toppings' field    
    def save(self, commit=True):
        # Get the unsave Pizza instance
        instance = forms.ModelForm.save(self, False)

        # Prepare a 'save_m2m' method for the form,
        old_save_m2m = self.save_m2m
        def save_m2m():
           old_save_m2m()
           # This is where we actually link the pizza with toppings
           instance.topping_set.clear()
           instance.topping_set.add(*self.cleaned_data['toppings'])
        self.save_m2m = save_m2m

        # Do we need to save all changes now?
        if commit:
            instance.save()
            self.save_m2m()

        return instance

PizzaForm然后可以使用无处不在,甚至在admin:

# yourapp/admin.py
from django.contrib.admin import site, ModelAdmin
from yourapp.models import Pizza
from yourapp.forms import PizzaForm

class PizzaAdmin(ModelAdmin):
  form = PizzaForm

site.register(Pizza, PizzaAdmin)

注意

save()方法可能有点过于冗长,但是如果你不需要支持这种commit=False情况,则可以将其简化,如下所示:

def save(self):
  instance = forms.ModelForm.save(self)
  instance.topping_set.clear()
  instance.topping_set.add(*self.cleaned_data['toppings'])
  return instance


 类似资料:
  • 我使用的是Spring数据r2dbc,它不支持多对多映射。 表格:- 通常,一个用户可以有多个映射。 Sql查询, 从user u、user\u role\u mapping urm、user\u role ur中选择*其中u.user\u id=:userId和u.org\u id=:orgId和u.user\u id=urm。用户id和ur。role\u id=urm。角色\u id 这里,我

  • 我目前正在用Laravel构建我的第一个应用程序,我偶然发现了一个问题,即我不知道如何设置模型(用户和组)之间的多对多关系。 我已经创建了一个板,其中存储了所有用户和他们所在的组之间的关系。我的问题是,我不知道如何访问和设置这在Laravel。我不确定我是否必须用户has很多或属性。 我正试图找到一种方法,将用户添加到组中,以便在UserGroups表中创建一个新条目。 我的桌子: 用户 ID 集

  • 问题内容: 我有一个包含 产品* 列表的表 订单 。对于与特定订单相对应的每个 产品 ,我需要存储一个 地址 列表,在该 地址 中应将单个产品(每个订单基于每个产品)发送到 * 所以我有这张表,在 订单 和 产品 上有很多很多,我需要的是将上表中的每个条目映射到 地址 列表。所以我需要像 并将上表中的条目映射到地址列表,我需要上述PK和地址ID(我的地址表的主键)上的多对多表 这里PK_Order

  • 我有一个具有一对多关联的hibernate实体: *为清晰起见,删除了一些注释 子实体映射到具有复合主键(key和PARENT_ID)的表。问题是,当两个用户将相同的子项(使用相同的密钥)添加到相同的父项时,级联保存(session.saveOrUpdate(Parent))失败,子项的主键冲突而不是乐观锁失败。 如果除了集合之外,用户还更改了父实体中的其他一些属性,乐观锁也能正常工作。 我可以在

  • 多对多关联模型 满足条件:一个学生可以选择多个课程,一个课程也可以被多个学生选择 示例: student 学生表 class 课程表 student_has_class 中间表 >[danger] 多对多,需要借助第三个中间表,中间表包含了2个外键,分别是两个表的主键 我们假设有这样的一个场景,文章(Post)可以有多个标签(Tag),同样,一个Tag也可以对应多个Post,我们需要一张关联表Po

  • 问题内容: 假设我有一个数据库,其中包含人员,杂货店和您可以在商店中购买的商品,如下所示: 我还有一个表格可以跟踪哪些商店销售什么: 我还有一张桌子上有购物清单 我的问题是,给定一个人或他们的ID,找出他们可以去的商店的最佳方法是什么,以便他们将所有物品都列入清单。MySQL中是否有针对这些类型的计算的模式? 我的尝试(非常丑陋和凌乱)是这样的: 谢谢你的时间! 使用数据编辑SQL 问题答案: 如