向 django admin 添加每个对象的权限
背景
我正在为度假租赁网站开发 django 应用程序。它将有两种类型的用户:租户和物业经理。
我希望物业经理能够在 django admin 中管理他们的租赁物业。然而,他们应该只能管理自己的财产。
我意识到默认的 django admin 不支持这个。我想知道添加此功能会带来多少麻烦,如果可行的话,处理它的最佳方法是什么。
目标
理想情况下,我想象它的工作方式如下:
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
可能的解决方案 strong>
框架如何决定租赁(或其他)是否属于用户?我认为它会检查 vacation.Rental
类,看看它是否有 ForeignKey
到 auth.User
(可能有一些特定的名称,如“所有者”)。
创建新的
vacation.Rental
时,ForeignKey
字段的值将强制为当前用户的 ID。ForeignKey
字段不会显示在表单上。在列出租赁时,仅显示
ForeignKey
与当前用户匹配的租赁。更改租赁时,仅显示
ForeignKey
与当前用户匹配的租赁。ForeignKey
字段不会显示在表单上。
当然,这应该能够适用于任何具有适当 ForeignKey
字段的模型,而不仅仅是我们的 vacation.Rental
模型。
到目前为止这听起来可行吗,还是我应该朝不同的方向前进?
并发症
现在,这是棘手的部分;我不知道如何处理这个问题。假设Rental
可以有许多“RentalPhotos”。 RentalPhoto
有一个 ForeignKey
到 Rental
。用户应该能够将照片添加到自己的租赁中。但是,这些照片没有用户 ForeignKey
,因此无法直接找出谁拥有该照片。
可以通过框架中的一些技巧来解决这个问题吗?跟踪 ForeignKey
直到找到带有 ForeignKey
的对象给用户?或者我应该采取简单的方法,将 RentalPhoto
(以及“属于”Rental
的其他所有内容)提供给相应的ForeignKey
>auth.User?第二种方法会带来不必要的冗余,第一种方法可能会需要不必要的处理开销......
如果我完全误入歧途,请毫不犹豫地为我指出正确的方向。预先感谢您的任何帮助。
Background
I'm developing a django app for a vacation rental site. It will have two types of users, renters and property managers.
I'd like the property managers to be able to manage their rental properties in the django admin. However, they should only be able to manage their own properties.
I realize the default django admin doesn't support this. I'm wondering how much trouble it would be to add this functionality, and, if it's feasible, what the best way to handle it is.
Goal
Ideally, I picture it working something like this:
auth
already allows permissions like this:
vacation | rental | Can add rental vacation | rental | Can change rental vacation | rental | Can delete rental
I'd like to change this to something like:
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
Possible solution
How would the framework decide if the rental (or whatever) belongs to the user? I'm thinking it checks the vacation.Rental
class to see if it has a ForeignKey
to auth.User
(possibly having some particular name, like 'owner').
On creating a new
vacation.Rental
, the value of theForeignKey
field would be forced to the current user's id. TheForeignKey
field would not be displayed on the form.On listing rentals, only rentals with the
ForeignKey
matching the current user would be displayed.On changing rentals, only rentals with the
ForeignKey
matching the current user would be displayed. TheForeignKey
field would not be displayed on the form.
Of course, this should be able to work for any model having an appropriate ForeignKey
field, not just our vacation.Rental
model.
Does this sound feasible so far, or should I be going in a different direction?
Complications
Now, here's the tricky part; I'm not sure how to handle this. Let's say a Rental
can have many "RentalPhotos." RentalPhoto
has a ForeignKey
to Rental
. Users should be able to add photos to their own rentals. However, the photos don't have a user ForeignKey
, so there's no way to directly find out who owns the photo.
Can this be solved by some trickery in the framework, following ForeignKey
s until an object is found with a ForeignKey
to user? Or should I take the easy way out and give RentalPhoto
(and everything else 'belonging' to Rental
) its own ForeignKey
to the appropriateauth.User
? The second approach would invite unneeded redundancy, the first would probably require unnecessary processing overhead...
If I'm going entirely astray please don't hesitate to point me in the right direction. Thanks in advance for any help.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我只需向每个模型添加一个方法
is_owned_by(user)
,并由模型决定它是否由该用户拥有。在大多数情况下,is_owned_by
可以是基本模型类中的通用函数,您可以在特殊情况下对其进行调整。例如,这足够通用并且明确,您将完全控制事物的行为方式。
要添加新权限,您可以将其添加到您的模型中,例如
我认为您不应添加
any
和own
两个权限,而应该仅添加own
权限,因此每个对象都已经拥有can_edit
,您可以将其视为用户只能编辑他的对象,并且如果用户具有 can_edit_any 权限,则只允许他编辑所有对象使用此功能,我们可以通过添加自定义后端,例如,
这是一个非常快速的实现,实际上,您可以扩展权限对象来检查是否需要和对象,例如
permission.is_per_object
而不是进行粗略的字符串搜索,但这也应该可以工作,如果您有标准名称I would simply add a method to each model
is_owned_by(user)
, and it is upto the model to decide if it is owned by that user or not. In most caseis_owned_by
can be a generic function in a base model class and you can tweak it in special cases. e.g.This is generic enough and being explicit you will have full control how things behave.
To add new permission you can add that to your models e.g.
I think instead of adding two permission for
any
andown
, you should add onlyown
permission , so each object already hascan_edit
which you can treat as user can edit only his object, and if user has permission can_edit_any than only he is allowed to edit allUsing this we can extend auth by adding a custom backend e.g.
This is a very quick implemenation, in reality you can extend permission objects to check if it needs and object or not e.g.
permission.is_per_object
instead of doing crude string search but that should also work if you have standard names如果您不想实现自己的权限后端,我建议您使用 https://github.com /chrisglass/django-rulez 你会以更简单的方式做你想做的事。
If you don't want to implement your own Permission Backend, I recommend you to use https://github.com/chrisglass/django-rulez You will do what you want in a much easier way.
它位于 Django 文档。
基本上,您为模型创建自定义管理类,并定义方法
get_queryset
。在你的情况下,它可能类似于下面的内容。超级用户将看到所有出租,而所有者只能看到他的。这是另一个可能的线索: https://code.djangoproject.com/wiki/RowLevelPermissions
It's in Django docs.
Basically you create custom admin class for your model, and define the method
get_queryset
. In your case it could be something like below. Super user would see all rentals, while owner only his.Here's another possible lead: https://code.djangoproject.com/wiki/RowLevelPermissions
我看不出哪里有必要耍花招:
出租照片 ->出租->用户
因此,要获取特定 RentalPhoto 的用户,您可以在实例中调用类似以下内容:
一步中遵循多个关系可以被视为非欺骗。
I don't see where there is trickery necessairy:
RentalPhoto -> Rental -> User
So to get the User for a particular RentalPhoto you would call something like this in the instance:
Following multiple relations in one step can be considered as non-trickery.