我正在Django(我很新)中编写一个应用程序,其中管理区域将暴露给客户'由于应用程序的性质以及Django使用如此少的代码在管理区域自动生成表单的方式,应用程序,而不仅仅是工作人员/超级用户...
因此,我需要健壮且易于管理的方式来维护身份验证和分离数据,因此该用户只能看到用户创建的数据。
目前,我只是使用默认的管理包并更改了“客户端用户”的权限。使用以下代码过滤他们可以看到的数据(我只希望他们看到他们创建的数据):
class MyModelAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(MyModelAdmin, self).get_queryset(request)
return qs.filter(user=request.user)
def save_model(self, request, obj, form, change):
# field not editable in admin area so handle it here...
obj.user = request.user
obj.save()
然而,随着应用程序的扩展,我可以看到确保此类数据过滤变得难以管理,例如,如果某些表上存在外键链(A->B
B->C
{{1} }),并过滤链末尾的表我需要做各种C->D
来获取与当前用户相关的行。
我正在考虑的一些解决方案是为每个用户创建一个单独的管理应用,但这感觉就像是矫枉过正,甚至更难以管理。
或者只是将用户列添加到每个需要用户进行数据过滤的模型中,以便于过滤。
对最佳方法的任何想法?
答案 0 :(得分:0)
首先,根据经验,您最好使用View
在实际的django应用中为用户提供编辑和创建功能。通用视图使这很容易。一旦您让用户加入管理员,他们就会习惯,并且很难让他们离开。
此外,您应该使用contrib.auth.Group和django-guardian来跟踪对象级权限,而不是自己实现。 从长远来看,这是值得的。
如果您想自己创造这种体验,那么您有多种明智的选择:
owner
关于ForeignKey
金字塔owner
要实现第一个选项,您应该在ForeignKey
链上的每个模型上实现两个方法:
def get_parent(self):
"""Should return the object that should be queried for ownership information"""
pass
def owned_by(self, user):
"""Should return a boolean indicating whether `user` owns the object, by querying `self.get_parent().owned_by(user)`"""
pass
但是,如您所述,如果您的架构足够复杂,则会导致许多JOINS
。
我建议你在每个模型中存储有关所有者的信息,其他一切都是我经验中的维护噩梦。
您应该使用继承,而不是手动将字段手动添加到每个模型。但是,django通过关系为继承提供了错误的内置支持:抽象基础模型无法定义models.ForeignKey
,因此您仍然坚持使用基于表的继承。
基于表的继承带来了另一个问题:考虑这些模型:
from django.db import models
from app.settings import AUTH_USER_MODEL
class Base(models.Model):
owner = models.ForeignKey(AUTH_USER_MODEL)
class ChildA(Base):
name = models.CharField(max_length=5)
class ChildB(Base):
location = models.CharField(max_length=5)
很容易找到owner
或ChildA
的给定实例的ChildB
:
>>> obj = ChildA.objects.create(owner=Peter, name="alex")
>>> obj.owner
彼得
然而,找到特定用户拥有的所有对象并非易事:
>>> Base.objects.filter(owner=Peter)
<Base-object at 0xffffff>
默认管理器返回一个Base对象,并且不包含有关它是ChildA
还是ChildB
实例的信息,这可能很麻烦。
为了避免这种情况,我建议使用django-polymorphic或django-model-utils的多态方法,它更轻量级。它们都提供了在查询中检索给定Base
模型的子类的方法。
有关django中多态性的更多信息,请参阅我的答案。
这些也会导致JOIN
,但至少复杂性是可控制的。