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)?
精彩评论