如何在自定义表单中实现Django admin页ManyToMany字段同款组件
实现Django admin同款多对多字段组件方案
Django admin 中带新增+号的多对多选择组件是通过RelatedFieldWidgetWrapper包装默认表单控件实现的,按以下步骤调整即可复现该效果:
前置确认
- 确保
Ingredient、RecipeIngredient模型已在admin后台完成注册,+号跳转的新增页为admin默认提供的页面,未注册会返回404 - 自定义表单的前端模板需要加载admin官方的静态资源,否则组件样式和弹窗交互会失效,在模板的
<head>标签中加入以下引用:
{% load static %} <link rel="stylesheet" href="{% static 'admin/css/widgets.css' %}"> <script src="{% static 'admin/js/core.js' %}"></script> <script src="{% static 'admin/js/vendor/jquery/jquery.js' %}"></script> <script src="{% static 'admin/js/jquery.init.js' %}"></script> <script src="{% static 'admin/js/admin/RelatedObjectLookups.js' %}"></script>
调整表单代码
修改你的AddRecipeForm类,手动给多对多字段的控件套上admin的包装器:
from django import forms from django.contrib.admin.widgets import RelatedFieldWidgetWrapper from django.contrib.admin.sites import site from .models import Recipe class AddRecipeForm(forms.ModelForm): class Meta: model = Recipe fields = ['name', 'ingredients', 'date_created'] def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) # 包装ingredients字段的原有控件 self.fields['ingredients'].widget = RelatedFieldWidgetWrapper( widget=self.fields['ingredients'].widget, rel=self.instance._meta.get_field('ingredients').remote_field, admin_site=site, can_add_related=True )
可选模型优化(非必须)
你当前的模型设计可以简化,直接将RecipeIngredient作为Recipe和Ingredient多对多关系的中间表,更符合Django的设计规范:
class Recipe(models.Model): recipe_id = models.AutoField(primary_key=True) name = models.CharField(max_length=200) # 通过through参数指定中间表 ingredients = models.ManyToManyField(Ingredient, through='RecipeIngredient') date_created = models.DateTimeField('Date Created') def __str__(self): return self.name
内容的提问来源于stack exchange,提问作者Guillermo
相关产品推荐
相关产品推荐

