在Django Admin中为新建ModelB外键预设父级初始值的方法
解决方案
当然可以实现,核心就是修改ModelA编辑页面里extra_data字段的"+"按钮URL,带上当前ModelA实例的something ID,再在ModelB的Admin里读取这个参数设置初始值。具体分两步来做:
第一步:修改ModelA Admin里的添加按钮URL
在ModelA的Admin类中,重写formfield_for_foreignkey方法,为extra_data字段的widget添加自定义的URL参数:
from django.contrib import admin from django.urls import reverse from .models import ModelA, ModelB, Something class ModelAAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): field = super().formfield_for_foreignkey(db_field, request, **kwargs) if db_field.name == 'extra_data' and request.resolver_match.kwargs.get('object_id'): # 获取当前编辑的ModelA实例 model_a_instance = ModelA.objects.get(pk=request.resolver_match.kwargs['object_id']) # 修改添加ModelB的URL,带上something的ID参数 add_url = reverse('admin:yourapp_modelb_add') add_url += f'?something={model_a_instance.something.pk}' field.widget.add_url = add_url return field admin.site.register(ModelA, ModelAAdmin)
注意把yourapp换成你的实际应用名称。
第二步:在ModelB Admin中读取URL参数设置初始值
接下来在ModelB的Admin类里,重写get_form方法,从请求的GET参数里获取something的ID,设置为表单的初始值:
class ModelBAdmin(admin.ModelAdmin): def get_form(self, request, obj=None, **kwargs): form = super().get_form(request, obj, **kwargs) # 从URL参数中获取something的ID something_id = request.GET.get('something') if something_id: form.base_fields['something'].initial = something_id return form admin.site.register(ModelB, ModelBAdmin)
这样操作后,当你在ModelA的编辑页面点击extra_data字段的"+"按钮时,打开的ModelB新建页面里,something字段会自动选中当前ModelA对应的Something实例。
另外要注意:如果ModelA是新建状态(还没保存),此时没有object_id,这种情况没法获取something的值,所以这个逻辑只对已保存的ModelA实例生效,新建ModelA时点击"+"按钮不会带参数,这是合理的——因为新建的ModelA本身还没设置something。
内容的提问来源于stack exchange,提问作者Alejandro Garcia
相关产品推荐
相关产品推荐

