Django 管理后台的特定用例

2 投票
3 回答
1132 浏览
提问于 2025-04-15 15:14

我有几个关于Django后台管理的特殊使用场景,想听听大家的看法:

  1. 我想用一个定制版的后台,让用户可以编辑网站上的某些对象(让它看起来更像网站的其他部分)。目前用户只能编辑自己拥有的对象,但我最终想把这个功能开放成一种维基风格,任何用户都可以编辑任何对象。换句话说,我会把所有用户都设定为“工作人员”,并允许他们编辑这些对象。

  2. 我还考虑对其他对象进行类似的操作,但并不是所有用户都能编辑所有对象。我会使用一个自定义视图,确保用户只能编辑自己的对象。这样做的好处是,我可以从后台自动生成的编辑界面开始,然后用ModelAdmin进行定制,因为后台的功能已经很接近我想要的样子。

我觉得第一个建议可能是可以接受的,而第二个可能就不太行。在查看了一些其他资源后(比如Django后台的有效使用案例?以及那篇问题中Django书籍的引用),似乎有些Django开发者认为这个想法不太对。

我想问的是:为什么呢?从性能、稳定性、安全性、可用性等方面来看,有没有什么好的理由不使用定制的后台视图来授予每个对象的权限?我觉得这可能会为某些应用节省很多时间(而且我可能还是会这样做),但我想理解为什么要在后台和其他部分之间做这样的区分。

3 个回答

1

我们限制了Django后台管理系统的使用,只让我们的管理员和支持人员访问,而不让普通用户或客户使用。我们只是对样式表做了一些小改动,让颜色和网站其他部分一致,其他的没有改动。

对于用户(我们的客户),我们提供了合适的视图功能来处理各种交易。即使是经过精心设计的表单,我们仍然需要检查和控制一些事情。

Django的更新交易写起来非常简单,尝试去定制后台管理系统似乎比直接写交易要麻烦得多。

我们的交易复杂度其实和这个链接上展示的差不多。

一般来说,我们的交易页面几乎总是包含一些工作流程元素(或相关内容),这让它们比内置的后台管理界面稍微复杂一些。我们通常会在基础代码的基础上增加大约六行左右的代码。

我们的使用场景并不是简单的添加、修改或删除,所以我们需要比默认的后台应用提供更多的功能。

2

我之前做过一个django应用,能够实现这个功能,而不需要改动实际的管理代码。具体做法是创建一个admin.ModelAdmin的子类,并在其中扩展几个方法,加入查询集过滤器。这样就能只显示属于用户的记录(在这个例子中,business是AUTH_PROFILE_MODEL)。网上有很多博客讲解如何做到这一点。

你可以用这种方法来过滤列表、表单选择框、验证表单字段的保存等等。

到目前为止,这个方法从NFA版本一路用到1.0和1.1,但它对API的变化比较敏感。

在实际操作中,我发现这样为新模型生成行级访问权限的管理表单要快得多,因为我在添加新模型时,只需创建一个带有用户外键的新模型,继承AdminFilterByBusiness,或者直接

admin.site.register(NewModel,AdminFilterByBusiness)

如果不需要任何自定义的内容。这种方法有效且非常简洁。

不过,你也有可能无法利用其他已经发布的django应用。所以在你构建项目时,要仔细考虑这种技术。

下面是一个受启发于 http://code.djangoproject.co/wiki/NewformsHOWTO 的示例过滤管理类。

#AdminFilterByBusiness {{{2
class AdminFilterByBusiness(admin.ModelAdmin):
    """
    Used By News Items to show only objects a business user is related to
    """
    def has_change_permission(self,request,obj=None):
        self.request = request

        if request.user.is_superuser:
            return True

        if obj == None:
            return  super(AdminFilterByBusiness,self).has_change_permission(request,obj)

        if obj.business.user == request.user:
            return True
        return False

    def has_delete_permission(self,request,obj=None):

        self.request = request

        if request.user.is_superuser:
            return True

        if obj == None:
            return  super(AdminFilterByBusiness,self).has_delete_permission(request,obj)

        if obj.business.user == request.user:
            return True
        return False

    def has_add_permission(self, request):

        self.request = request
        return super(AdminFilterByBusiness,self).has_add_permission(request)

    def queryset(self, request):
        # get the default queryset, pre-filter
        qs = super(AdminFilterByBusiness, self).queryset(request)
        #
        if not (request.user.is_superuser):
            # filter only shows blogs mapped to currently logged-in user
            try:
                qs = qs.filter(business=request.user.business_set.all()[0])
            except:
                raise ValueError('Operator has not been created. Please Contact Admins')
        return qs

    def formfield_for_dbfield(self, db_field, **kwargs):

        """ Fix drop down lists to populate as per user request """
        #regular return for superuser
        if self.request.user.is_superuser:
            return  super(AdminFilterByBusiness, self).formfield_for_dbfield(
                    db_field, **kwargs)

        if db_field.name == "business":
            return forms.ModelChoiceField(
                queryset = self.request.user.business_set.all()
               )

        #default
        return  super(AdminFilterByBusiness, self).formfield_for_dbfield(db_field, **kwargs)
4

你可以随意做你想做的事情。如果你想自定义Django的管理后台,尽管去做,但一旦你偏离了常规的管理修改方式,可能就不太容易得到邮件列表和IRC的支持了。

虽然现在看起来自定义管理后台是个简单的解决办法,但实际上,一旦你真的开始调整功能,可能会发现这比自己重新创建所需的表单要麻烦得多。你可以看看通用的创建/编辑/删除通用的详情/列表视图——这些会很快提供你需要的基本功能,而且比管理后台更容易扩展。

我认为“管理后台不是你的应用”的观点,主要是因为使用其他机制会比修改管理后台更简单(而且,保持管理后台不变会让Django开发者在未来的兼容性上更轻松)。

撰写回答