【问题标题】:How to restrict access to pages based on user type in Django如何根据 Django 中的用户类型限制对页面的访问
【发布时间】:2012-09-17 20:25:14
【问题描述】:

我有一个对新 Django 开发人员有用的基本问题。

我在 Django 中创建了自己的 UserProfile。此用户配置文件有一个名为“类型”的特定字段。该字段可以有两个值(直到现在可能会更多):男 - M / 女 - F:

from django.contrib.auth.models import User

GENDER = (
    (M, 'Male'),
    (F, 'Female'),
)

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    type = models.CharField( max_length=2,
                             choices=GENDER,
                             default='F')

基本上,我想允许访问以限制访问或根据用户类型调整页面内容。到目前为止,我使用了一种非常基本的初学者方法,即在视图中测试用户类型,然后处理页面:

def OnePage(request):
    if request.user.type == 'M':
        ....
    else if request.user.type =='F':
        ....

然后我还需要根据用户类型调整呈现的模板:男性用户不会拥有与女性用户相同的个人资料页面。

我确信有更好的方法可以做到这一点,但作为一个 Django 初学者,我对所有 Django 的可能性感到迷茫。因此,如果您有任何最佳实践来实现这一点,请告诉我(显然我想要一个可以在每个视图上使用的 DRY 代码!)

感谢您的帮助。

【问题讨论】:

    标签: django django-templates django-views


    【解决方案1】:

    根据你想做什么,如果你需要为不同的性别使用非常不同的html,你可以试试这个方法:

    def gender_filter(func):
        def _view(request,*args,**kwargs):
            res=func(request,*args,**kwargs)
            if request.user.get_profile().type=='F':
                res.template_name='template_f.html'
                res.context_data['gender']='female'
            elif request.user.get_profile().type=='M':
                res.template_name='template_m.html'
                res.context_data['gender']='male'
            return res.render()
        return _view
    
    @gender_filter
    def my_view(request):
        t=TemplateResponse(request,'template_f.html',{...})
        return t
    

    因此,您可以让它们返回 TemplateResponse 对象,并使用装饰器更改模板,添加一般上下文,然后将它们转换为 HttpResponse,而不是在视图中返回 Http 响应。

    或者类似的权限检查:

    def gender_only(gender):
        def _dec(func):
            def _view(request,*args,**kwargs):
                if request.user.get_profile().type==gender
                    return func.render(request,*args,**kwargs)
                else:
                    raise Exception("You do not have the right gender")
            return _view
        return _dec
    
    @gender_only('F')
    def my_view(request):
        ...
        return render_to_response('template.html',{...},context_instance=RequestContext(request))
    

    【讨论】:

      【解决方案2】:

      要限制访问,请使用user passes test 装饰器:

      from django.contrib.auth.decorators import user_passes_test
      
      male_only = lamda u: u.type == 'M'
      female_only = lamda u: u.type == 'F'
      
      
      @user_passes_test(male_only)
      def myfunc(request):
         pass
      
      @user_passes_test(female_only)
      def myotherfunc(request):
         pass
      

      【讨论】:

        【解决方案3】:

        一种解决方案可能是根据用户类型更改基本模板名称:

        @render_to('some_template.html')
        def some_view(request):
            base_template = 'base_%s.html' % request.user.profile.type
            # …
            return {
                'base_template': base_template,
            }
        

        在你的模板中:

        {% extends base_template %}
        {% block some-block %}
        …
        {% endblock %}
        

        如果您需要在每个视图上执行此操作,您可以使用中间件来设置此值。

        【讨论】:

        【解决方案4】:

        要向用户添加额外数据,请参阅

        Storing additional information about users

        然后将配置文件添加到您的上下文中,您可以在模板中使用 {{profile}} 变量

        {% if profile.type == "F" %}
            blah, blah
        {% else %}
            blah, blah
        {% endif %}
        

        【讨论】:

        • 是的,这就是我到目前为止所做的。但是有没有办法不在我需要执行此过程的每个页面上重复自己?像装饰师还是别的什么?
        猜你喜欢
        • 2016-10-18
        • 2018-06-06
        • 1970-01-01
        • 1970-01-01
        • 2018-08-11
        • 1970-01-01
        • 2014-08-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多