如何在创建model B时inline生成多对多关联model A 类似Admin的TabularInline功能
实现创建Model B时inline创建多对多关联Model A的方案
以下实现效果和Django Admin原生TabularInline完全一致,分Admin端和自定义表单两种场景:
前置准备:模型定义
首先定义存在多对多关联的两个模型:
from django.db import models # 被关联的Model A class ModelA(models.Model): name = models.CharField(max_length=100) # 可自行补充其他字段 def __str__(self): return self.name # 主模型Model B class ModelB(models.Model): title = models.CharField(max_length=100) # 多对多关联字段 related_a = models.ManyToManyField(ModelA, related_name="related_b") # 可自行补充其他字段 def __str__(self): return self.title
场景1:Django Admin后台实现
直接定义Inline类并绑定到ModelB的Admin注册配置即可:
from django.contrib import admin from .models import ModelA, ModelB class ModelAInline(admin.TabularInline): # 多对多关联必须指定中间表,通过关联字段的through属性获取 model = ModelB.related_a.through # 配置默认显示的空白新增行数量 extra = 1 # 可自行配置fields、exclude、readonly_fields等参数自定义显示效果 @admin.register(ModelB) class ModelBAdmin(admin.ModelAdmin): # 把ModelA的Inline配置加入到ModelB的Admin配置中 inlines = [ModelAInline]
注意:不需要给ModelA的Admin配置绑定该Inline,除非你需要在编辑ModelA时也能操作关联的ModelB。
场景2:自定义前端页面实现(非Admin场景)
需要配合Django Formset实现批量新增ModelA的逻辑,核心实现如下:
后端逻辑示例
from django.shortcuts import render, redirect from django.forms import formset_factory from .models import ModelB from .forms import ModelBForm, ModelAForm def create_model_b(request): # 定义ModelA的Formset,extra参数控制初始空白行数量 ModelAFormSet = formset_factory(ModelAForm, extra=1, can_delete=True) if request.method == "POST": b_form = ModelBForm(request.POST) a_formset = ModelAFormSet(request.POST) if b_form.is_valid() and a_formset.is_valid(): # 先保存ModelB实例 b_instance = b_form.save() # 遍历Formset保存所有提交的ModelA实例,绑定关联 for form in a_formset: # 跳过空行和标记为删除的行 if form.cleaned_data and not form.cleaned_data.get("DELETE"): a_instance = form.save() b_instance.related_a.add(a_instance) return redirect("your_success_page") else: b_form = ModelBForm() a_formset = ModelAFormSet() return render(request, "create_model_b.html", { "b_form": b_form, "a_formset": a_formset })
前端逻辑说明
前端页面可以通过JS实现动态添加/删除ModelA的表单行,提交时将所有表单数据一起传给后端即可,效果和Admin的TabularInline完全一致。
内容的提问来源于stack exchange,提问作者Matteo Biffoni
相关产品推荐
相关产品推荐

