Python 向django admin添加每个对象的权限
背景 我正在为一个度假租赁网站开发django应用程序。它将有两种类型的用户,租客和物业经理 我希望物业经理能够在django admin中管理他们的租赁物业。但是,他们应该只能管理自己的财产 我意识到默认的django管理员不支持这一点。我想知道添加这个功能会有多麻烦,如果可行的话,最好的处理方法是什么Python 向django admin添加每个对象的权限,python,django,django-admin,Python,Django,Django Admin,背景 我正在为一个度假租赁网站开发django应用程序。它将有两种类型的用户,租客和物业经理 我希望物业经理能够在django admin中管理他们的租赁物业。但是,他们应该只能管理自己的财产 我意识到默认的django管理员不支持这一点。我想知道添加这个功能会有多麻烦,如果可行的话,最好的处理方法是什么 目标 理想情况下,我想象它是这样工作的: vacation | rental | Can add rental vacation | rental | Can change rental v
目标 理想情况下,我想象它是这样工作的: vacation | rental | Can add rental vacation | rental | Can change rental vacation | rental | Can delete rental
auth
已经允许这样的权限:
vacation | rental | Can add rental
vacation | rental | Can change rental
vacation | rental | Can delete rental
假期|租金|可以增加租金
假期|租金|可以更改租金
假期|租金|可以删除租金
我想将此更改为:
vacation | rental | Can add any rental
vacation | rental | Can change any rental
vacation | rental | Can delete any rental
vacation | rental | Can add own rental
vacation | rental | Can change own rental
vacation | rental | Can delete own rental
假期|租金|可以添加任何租金
假期|租金|可以更改任何租金
假期|租赁|可以删除任何租赁
度假|租赁|可以添加自己的租赁
度假|租赁|可以更改自己的租赁
假期|租赁|可以删除自己的租赁
可能的解决方案 框架如何决定租金(或任何东西)是否属于用户?我想它会检查
vacation.Rental
类,看看它是否有一个ForeignKey
到auth.User
(可能有一些特定的名字,比如“owner”)
- 在创建新的
休假.租赁时,
字段的值将强制为当前用户的id。ForeignKey
字段将不会显示在表单上ForeignKey
- 在列出rentals时,仅显示与当前用户匹配的
的rentalsForeignKey
- 在更改租金时,仅显示与当前用户匹配的
租金。外键
字段将不会显示在表单上ForeignKey
ForeignKey
字段的模型,而不仅仅是我们的vacation.rent
模型
到目前为止,这听起来是可行的,还是我应该走另一个方向
并发症 现在,这里是棘手的部分;我不知道该怎么办。假设一个
Rental
可以有很多“RentalPhoto”。RentalPhoto
有一个ForeignKey
到Rental
。用户应该能够将照片添加到自己的租赁中。但是,这些照片没有用户ForeignKey
,因此无法直接找出照片的所有者
这可以通过框架中的一些诡计来解决吗,在ForeignKey
s之后,直到找到一个对象,并向用户提供ForeignKey
?或者我应该采取简单的方法,将RentalPhoto
(以及属于rent
的所有其他内容)自己的ForeignKey
交给相应的auth.User
?第二种方法将导致不必要的冗余,第一种方法可能需要不必要的处理开销
如果我完全误入歧途,请毫不犹豫地为我指出正确的方向。提前感谢您的帮助
这个问题可以通过一些诡计来解决吗
框架,遵循外键
直到找到具有
用户的外键
我看不出哪里有必要耍花招:
RentalPhoto->租赁->用户
因此,要获取特定RentalPhoto的用户,您可以在实例中调用类似的内容:
photo.rental.user
在一个步骤中遵循多个关系可以被视为非欺骗。我只需在每个模型中添加一个方法
由(用户)
拥有,由模型决定它是否由该用户拥有。在大多数情况下,是由
拥有的,可以是基本模型类中的通用函数,在特殊情况下可以对其进行调整。e、 g
class RentalPhoto(BaseModel):
def is_owned_by(self, user):
return self.rental.is_owned_by(user)
这是足够通用的,并且是明确的,你将完全控制事物的行为
要添加新权限,您可以将其添加到您的模型中,例如
class Rental(models.Model):
# ...
class Meta:
permissions = (
("can_edit_any", "Can edit any rentals"),
)
我认为不应该为any
和own
添加两个权限,而应该只添加own
权限,这样每个对象都已经有can\u edit
,您可以将其视为用户只能编辑其对象,并且如果用户有权限只能编辑任何对象,那么他就可以编辑所有对象
使用这个,我们可以通过添加一个自定义后端来扩展auth
class PerObjectBackend(ModelBackend):
def has_perm(self, user_obj, perm, obj=None):
allowed = ModelBackend.has_perm(self, user_obj, perm)
if perm.find('any') >=0 :
return allowed
if perm.find('edit') >=0 or perm.find('delete') >=0:
if obj is None:
raise Exception("Perm '%s' needs an object"%perm)
if not obj.is_owned_by(user_obj):
return False
return allowed
这是一个非常快速的实现,实际上,您可以扩展权限对象来检查它是否需要和对象,例如
权限。is_per_对象
,而不是执行粗略的字符串搜索,但是如果您有标准名称,如果您不想实现自己的权限后端,这也应该起作用,我建议你使用“你将以一种更简单的方式做你想做的事情”。这是一种很好的方法
基本上,您可以为模型创建自定义管理类,并定义方法get\u queryset
。在您的情况下,它可能是如下所示。超级用户将看到所有的租金,而所有者只有他的
class RentalAdmin(admin.ModelAdmin):
def get_queryset(self, request):
qs = super(RentalAdmin, self).get_queryset(request)
if request.user.is_superuser:
return qs
return qs.filter(owner=request.user)
这是另一个可能的线索:这将适用于这种特殊情况,但我想以一种通用的方式来做--“当然,这应该能够适用于任何具有适当的
ForeignKey
字段的模型,而不仅仅是我们的休假.rent
[和相关的]模型。”有很多种可能的方法更通用。例如,拥有一个model.Ownable,它定义了字段所有者,并在Ownable模型中对其进行了扩展。这个答案没有多大帮助。这使得大部分问题没有答案。也许我在解释这个问题上做得不好?如果你能告诉我为什么使用模型继承对你的案例没有帮助,我会更好地理解你的问题所在。谢谢你,Anurag;它不像我想的那样通用,但我会考虑的。如何将其绑定到auth
中,以便显示我的新权限