You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Django和xadmin中移除已注册模型的Admin类菜单入口

解决方案

嘿,针对你的需求,结合Python3/Django2.0/xadmin的技术栈,我整理了两种实用的实现方式——既能在C的新增/编辑页面创建关联的A、B数据,又能把A、B的专属管理菜单完全隐藏起来:

方法一:注册A、B但隐藏菜单,用xadmin自带的弹窗新增功能

这种方式最省心,直接利用xadmin原生的关联对象交互能力:

  1. 注册A、B模型,但隐藏它们的菜单入口
    在你的adminx.py文件里,注册A和B模型,同时通过hidden_menu属性把它们的菜单从系统导航里藏掉:

    import xadmin
    from .models import A, B, C
    
    class AAdmin(object):
        # 让该模型不在系统菜单中显示
        hidden_menu = True
        # 可按需配置其他属性,比如列表页显示的字段
        list_display = ['name']  # 假设A模型有name字段
    
    class BAdmin(object):
        hidden_menu = True
        list_display = ['name']  # 假设B模型有name字段
    
    xadmin.site.register(A, AAdmin)
    xadmin.site.register(B, BAdmin)
    
  2. 配置C模型的xadmin,启用外键弹窗新增
    默认情况下,xadmin的外键字段旁会自带一个"+"按钮,点击就能弹窗创建关联的A/B数据(我们已经注册了A、B,只是菜单被隐藏了)。如果想优化选择体验,还可以配置外键的显示样式:

    class CAdmin(object):
        # 给所有外键字段配置ajax选择+弹窗新增的样式
        relfield_style = 'fk-ajax'
        # 也可以单独给某个外键指定样式,比如:
        # relfield_style = {'product': 'fk-ajax', 'product_module': 'fk-select'}
    
        # 配置C模型的列表显示和编辑字段
        list_display = ['product', 'product_module']
        fields = ['product', 'product_module']
    
    xadmin.site.register(C, CAdmin)
    

    要是担心有人通过URL直接访问A/B的管理页,还可以在AAdmin和BAdmin里加权限限制,彻底禁止访问:

    class AAdmin(object):
        hidden_menu = True
        def has_permission(self):
            # 禁止所有用户访问A的管理页
            return False
    

方法二:不注册A、B,自定义表单嵌入A/B字段

如果完全不想把A、B注册到xadmin,那可以通过自定义表单,在C的编辑页面直接嵌入A、B的字段,提交时自动创建关联对象:

  1. 编写自定义表单
    在应用的forms.py里,定义C的表单,同时包含A、B的字段(要和A、B模型的实际字段对应):

    from django import forms
    from .models import A, B, C
    
    class CForm(forms.ModelForm):
        # 假设A模型有name必填字段,添加对应的表单字段
        a_name = forms.CharField(label='TestA名称', required=True)
        # 如果A有其他必填字段,也要同步添加,比如:
        # a_description = forms.CharField(label='TestA描述', widget=forms.Textarea)
    
        # 同理添加B的字段,假设B有name必填字段
        b_name = forms.CharField(label='TestB名称', required=True)
    
        class Meta:
            model = C
            fields = ['a_name', 'b_name']
    
        def save(self, commit=True):
            # 先创建A的实例
            a_instance = A.objects.create(
                name=self.cleaned_data['a_name']
                # 有其他字段的话在这里补充赋值
                # description=self.cleaned_data['a_description']
            )
            # 再创建B的实例
            b_instance = B.objects.create(
                name=self.cleaned_data['b_name']
            )
            # 创建C的实例并关联A、B
            c_instance = super().save(commit=False)
            c_instance.product = a_instance
            c_instance.product_module = b_instance
            if commit:
                c_instance.save()
            return c_instance
    
  2. 在xadmin中配置C使用自定义表单
    回到adminx.py,注册C模型并指定使用刚才的自定义表单:

    import xadmin
    from .models import C
    from .forms import CForm
    
    class CAdmin(object):
        form = CForm
        # 配置C的列表显示字段
        list_display = ['product', 'product_module']
    
    xadmin.site.register(C, CAdmin)
    

    这种方式下,A、B完全没注册到xadmin,系统菜单里肯定看不到它们,用户编辑C时直接填写A、B的信息,提交后就会自动创建关联的A、B实例。

小提醒

  • 方法一中的hidden_menu只是隐藏菜单,若要彻底禁止访问A/B的管理页,一定要加上has_permission返回False的配置。
  • 方法二中,要确保A、B的所有必填字段都在自定义表单里体现,不然保存时会触发数据库校验错误。

内容的提问来源于stack exchange,提问作者Bob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 03:40:06