开发者

DRY: Only show records owned by user. Possible with models.Manager?

I need to show a user only the objects that he owns. Since I need to do this on more then 80% of my views, hardcoding this kills DRY. More so, it is absolutely imperative that a user never sees records owned by others. And doing it by hand (in all the views) also seems error prone.

I've been looking at decorators (like login_required) but that seems to early in the request handling process. Is it possible to get the request.user value into a custom written manager and do something like this:

class CustomerManager(models.Manager):
    def get_query_set(self):
        return super(CustomerManager, self).get_query_set().filter(created_by=request.user)

Or is the manager object just as 'no go!' as the model definition as far as request info is concerned?

Thanx a lot.


This is the saving objects part, but purely here as elaboration and not a necessary read.

The saving part is relatively secure. I changed the object.save() function on the model so it takes the userid as a parm.

def save(self, userid):  
    self.created_by = userid    
    super(Customer, self).save(userid)

In the view:

if form.is_valid():
    customer = form.save(commit=False)
    customer.save(request.user)

This way I dont need to have the line below in my view before customer.开发者_如何学编程save...

    customer.created_by = request.user

And thus making it less error prone.


Why not define a method that fetches records for the user in the CustomerManager:

class CustomerManager(models.Manager):
    def get_user_records(self, user):
        return self.filter(created_by=user)

I would leave the get_query_set unoverridden as I see no benefits to override it in your case.


I think the best place for this may be in your views - though I could be wrong. Adding the self.created_by = userid in the save() method doesn't do anything to protect people from viewing the information. Just from saving it.

If you use a custom manager for a default queryset, then the 20% of your views will be out of luck.

I think you need a view - why not create your own generic view once and then reuse it ?

def object_detail_user_only(request. queryset, **kwargs):
    queryset = queryset.filter(created_by=request.user)

    return list_detail.object_detail(request,queryset,**kwargs)

Something like that (untested)?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜