Django: A more DRY way to prevent edit/delete of objects?

瘦欲@ 提交于 2019-12-10 16:25:39

问题


After reading the permission Django documentation, I'm still confused. I'd like to prevent access for user to edit or delete objects they didn't own. I dit it this way and it works:

In views.py:

def deleteReward(request, reward_id):
    reward = get_object_or_404(Reward, pk=reward_id)
    if reward.owner.user != request.user: # if the user linked to the reward is not the current one
        raise Exception("This reward is not yours, you can't delete it !")
    #...

But I think this isn't clean and DRY for two reasons:

  1. In each editStuff and deleteStuff views, I'll have to write the same portion of code.

  2. I'm currently writing an API with Tastypie, and if the permission logic is in a view, I won't be able to re-use it. The best way to deals with seems to be to map the API permission with the Django permissions (but the code I wrote in my view has nothing to do with permissions).

Could you help me to find the right way to do? Thanks a lot.


回答1:


Here is my working example.

1) QuerySet

class PermissionQuerySet(models.query.QuerySet):
    def editable_by(self, user):
        return self.filter(user=user)

    def viewable_by(self, user):
        return self.filter(user=user)

2) Managers

class PermissionManager(models.Manager):
    def get_query_set(self):
        return PermissionQuerySet(self.model)

    def editable_by(self, user, *args):
        return self.get_query_set().editable_by(user, *args)

    def viewable_by(self, user, *args):
        return self.get_query_set().viewable_by(user, *args)

3) Models

class MyModel(models.Model):
    ...
    objects = PermissionManager()

This approach works perfectly with class based views. I see you using TastyPie. I never used it before but it seems it's uses class based views too.

This is working sample:

class MyUpdateView(UpdateView):
    def post(self, request, *args, **kwargs):
        self.request = request
        super(MyUpdateView, self).post(request, *args, **kwargs)

    def get_query_set(self):
        queryset = super(MyUpdateView, self).get_query_set()
        queryset = queryset.editable_by(self.request.user)
        if not queryset.exists():
            raise Exception("This reward is not yours, you can't delete it !")
        return queryset

I think you can imagine how to use this approach in CreateView, DeleteView. And i think it is easy to implement this in TastyPie.




回答2:


Pass an additional parameter to get_object_or_404:

reward = get_object_or_404(Reward, pk=reward_id, owner=request.user)


来源:https://stackoverflow.com/questions/22178928/django-a-more-dry-way-to-prevent-edit-delete-of-objects

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!