简体   繁体   English

使用Django中类变量的基于类的视图的装饰器

[英]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 . 同时,这使我不必对getpost重复相同的方法。

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. 如果要避免在getpost重复代码,则可以将通用代码分解为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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM