Django代理模型Foreign Key字段编辑添加图标丢失及自动补全报错问题
解决方案
解决问题1:找回Foreign Key操作图标
这是因为代理模型改了app_label后,Django Admin没法正确关联原模型的Admin配置,导致操作图标生成失败。可以通过重写Admin类的formfield_for_foreignkey方法,手动给Foreign Key字段加上操作图标对应的URL:
from django.contrib import admin from django.contrib.admin.widgets import RelatedFieldWidgetWrapper from django.urls import reverse class MyModelAdmin(admin.ModelAdmin): def formfield_for_foreignkey(self, db_field, request, **kwargs): field = super().formfield_for_foreignkey(db_field, request, **kwargs) rel_model = db_field.remote_field.model # 检查关联模型是否在Admin有注册(确保能拿到URL) if rel_model in self.admin_site._registry: # 拼接关联模型的添加、编辑列表URL add_url = reverse(f"admin:{rel_model._meta.app_label}_{rel_model._meta.model_name}_add") change_list_url = reverse(f"admin:{rel_model._meta.app_label}_{rel_model._meta.model_name}_changelist") # 重新包装widget,加上操作图标 field.widget = RelatedFieldWidgetWrapper( field.widget, db_field.remote_field, self.admin_site, add_url=add_url, change_url=change_list_url ) return field
这段代码会自动给所有Foreign Key字段补全操作图标,不用单独指定每个关联模型。
解决问题2:autocomplete_fields报错处理
autocomplete_fields需要依赖关联模型的Admin注册状态,因为它要调用原模型的列表搜索接口。不想显示原模型的话,有两种简单的处理方式:
方式1:注册原模型但隐藏它
给原模型写一个Admin类,设置has_module_permission=False,这样原模型不会出现在Admin侧边栏,但仍能提供autocomplete需要的接口:
from django.contrib import admin # 原模型的Admin类,仅用于提供autocomplete接口,不显示在侧边栏 class HiddenMyModelAdmin(admin.ModelAdmin): def has_module_permission(self, request): return False # 注册原模型(隐藏)和代理模型 admin.site.register(MyModel, HiddenMyModelAdmin) admin.site.register(MyModelProxy, MyModelAdmin)
这种方法最简单,不用额外写视图或路由,推荐使用。
方式2:自定义Autocomplete视图(进阶)
如果完全不想注册原模型,可以自己写一个Autocomplete视图来替代原模型的Admin接口:
- 先创建自定义视图:
from django.contrib.admin.views.autocomplete import AutocompleteJsonView from django.utils.decorators import method_decorator from django.views.decorators.csrf import csrf_exempt from .models import MyModel @method_decorator(csrf_exempt, name='dispatch') def my_model_autocomplete(request): # 指定要搜索的模型和字段 view = AutocompleteJsonView.as_view( model=MyModel, search_fields=['name'] # 替换成你需要搜索的字段 ) return view(request)
- 在项目的
urls.py里添加路由:
from django.urls import path from .views import my_model_autocomplete urlpatterns = [ # 其他路由... path('admin/my-model-autocomplete/', my_model_autocomplete, name='my-model-autocomplete'), ]
- 在代理模型的Admin类里指定自定义的autocomplete URL:
class MyModelAdmin(admin.ModelAdmin): autocomplete_fields = ['foreign_key_field'] # 替换成你的Foreign Key字段名 def get_autocomplete_urls(self): from django.urls import path urls = super().get_autocomplete_urls() # 添加自定义的autocomplete路由 urls.append( path('foreign_key_field/autocomplete/', self.admin_site.admin_view(my_model_autocomplete), name='my-model-autocomplete') ) return urls
内容的提问来源于stack exchange,提问作者RPH
相关产品推荐
相关产品推荐

