[英]Decorators for class-based views that use class variables in Django
I have a class-based view that is inherited by other views: 我有一个由其他视图继承的基于类的视图:
class EditProfileAttribute(View):
template_name = 'mytemplate.html'
ThisModel = models.Model
def get(request, model_id):
instance = self.ThisModel.objects.get(id=model_id)
if instance.user != request.user:
return HttpResponseForbidden("Forbidden.")
# add form here
return render(request, self.template_name, {'model_id':model_id})
def post(request, model_id):
instance = self.ThisModel.objects.get(id=model_id)
if instance.user != request.user:
return HttpResponseForbidden("Forbidden.")
# do some editing here, save forms, etc.
return HttpResponse("Edited")
class EditAddressView(EditProfileAttributeView):
ThisModel = Address
class EditLinkView(EditProfileAttributeView):
ThisModel = Link
Now in my models.py file: 现在在我的models.py文件中:
class Address(models.Model):
user = models.ForeignKey(User)
address = models.TextField(max_length=100)
class Link(models.Model):
from_user = models.ForeignKey(User, related_name='from_link')
to_user = models.ForeignKey(User, related_name='to_link')
The class EditAddressView
works because the User field is explicitly called user
, but the class EditLinkView
does not because it requires instance.from_user
instead of instance.user
. 之类的
EditAddressView
起作用,是因为User字段被显式地称为user
,但是EditLinkView
的类EditLinkView
是因为它需要instance.from_user
而不是instance.user
。 (Let's just say I can't rename from_user
). (让我们说我不能重命名
from_user
)。
What I'd like to do is to transform the instance.user != request.user
part into a decorator where the syntax user
is not required, but I can't figure out how to reference self.ThisModel
. 我想做的是将
instance.user != request.user
部分转换为不需要语法user
的装饰器,但我不知道如何引用self.ThisModel
。
At the same time, this allows me not to repeat the same method for both get
and post
. 同时,这使我不必对
get
和post
重复相同的方法。
Is what I want even possible? 我想要的甚至有可能吗?
You can use another class attribute to store the name of the user field, and then use get_attr
to fetch the value in the method. 您可以使用另一个类属性来存储用户字段的名称,然后使用
get_attr
来获取方法中的值。
If you want to avoid duplicating code in get
and post
, then factor the common code into a helper method, or override dispatch
instead. 如果要避免在
get
和post
重复代码,则可以将通用代码分解为helper方法,或者改写dispatch
。
class EditProfileAttribute(View):
ThisModel = models.Model
user_field_name = 'user'
def dispatch(self, request, *args, **kwargs):
self.instance = self.ThisModel.objects.get(id=kwargs['model_id'])
if getattr(self.instance, self.user_field_name) != request.user:
return HttpResponseForbidden("Forbidden.")
# calling super() will call get() or post() as appropriate
return super(EditProfileAttribute, self).dispatch(request, *args, **kwargs)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.