在Django中为不同类型的用户配置文件解析URL到不同的视图

时间:2011-07-09 11:41:10

标签: django django-views django-urls extending

我正在向网站添加新类型的用户个人资料,而这种新用户(比如new_type)应该无法像现有用户那样访问相同的视图。

我的问题是:我如何使用相同的请求路径根据用户类型使用不同类型的视图,而不更改现有的视图代码,如添加

if user.profile_type == 'blah':
    do_this 
else: 
    do_that 

到每个视图?

详细说明:

我想对两种类型的用户使用“http://mysite.com/path/”,运行不同的逻辑并返回不同的显示而不会在现有视图中产生差异(因为有很多视图需要修改)

我正在考虑为新类型添加不同的视图组,然后覆盖网址逻辑以解析相关视图的请求路径,例如:

if user is of new_type 
    resolve path to related_view_for_new_type
else
    resolve as usual 

作为一个直截了当的例子:从同一个登录URL登录管理员和普通用户,如果用户是管理员,运行相关的管理员视图并返回django admin显示给她,如果是普通用户,则运行普通视图并返回正常的网站视图给她,而不重写或更改他们要求的网址。 (/ index /例如)

是否有可能以这种方式扩展Django中的URL,如果是这样,或者我应该放弃重载相同的请求路径并将“/ new_type /”添加到URL(http://mysite.com/new_type/path /)对于new_type用户?

由于

3 个答案:

答案 0 :(得分:2)

首先,拥有不同类型的用户意味着什么?一种非常简单的方法是在用户上存储属性。这样,给定user对象,您可以查看此额外属性以确定用户是否是特殊类型。 Django有一个标准的机制来存储这样的附加属性,你可以阅读here

一旦确定了用户类型,就可以创建一个装饰器,并将其应用于需要按照您描述的方式运行的任何视图。装饰器是将额外条件或行为应用于现有功能的好方法。装饰器中的逻辑在现有函数之前和/或之后开始工作,因此它可以非常轻松地完成类似于根据用户类型显示不同模板的操作。

装饰师的功能在您第一次遇到它们时看起来很奇怪,但仔细阅读它很快就会得到它。装饰器本身就是一个功能,你可以给它装饰你想要的功能。它为您提供了一个 new 函数,这是您使用额外逻辑包装的旧函数。

我在下面写了一些未经测试的示例代码。

def template_based_on_user_type(special_template, ordinary_template):
    def decorator(your_view_function):
        def inner_decorator(request, *args, **kwargs):
            # this is the logic that checks the user type before 
            # every invocation of this view:
            if request.user.type == 'special_type':
                template = special_template
            else:
                template = ordinary_template

            # this is the invocation of the view function, with
            # a custom template selected:
            return your_view_function(request, template)
        return inner_decorator
    return decorator

@template_based_on_user_type('my-special-template.html', 'ordinary-template.html')
def my_view_function(request, template='default.html'):
    # Do what you need to do here
    render_to_response(template, data, RequestContext(request)

应用装饰器的语法是“@”符号,后跟装饰器功能。装饰器使用指定的模板名称进行自定义。

答案 1 :(得分:0)

RTFM像往常一样:)

以下是可能解决方案的链接: method_splitter @ http://www.djangobook.com/en/2.0/chapter08/

new_type相关视图的名称将通过将new_type_添加到名称的开头来从原始文件中派生,例如index-> new_type_index

然后我将通过简单地检查request.user.is_new_type属性来确定要返回的视图。丑陋,但比修改广泛的观点要好。

答案 2 :(得分:0)

我在urls.py中使用装饰器解决了这个问题:

def dispatch_by_user(staff_view, external_user_view):
    def get_view(request, **kwargs):
        if (is_staff_user(request.user)):
            return staff_view(request, **kwargs)
        else:
            return external_user_view(request, **kwargs)
    return login_required(get_view)

def is_staff_user(user):
    return user.groups.filter(name="privileged-group").exists()

所以模式设置如下:

urlpatterns = [
    url(r'^$',
        dispatch_by_user(
                views.StaffHomeView.as_view(),  
                views.ExternalUserClientView.as_view()),
        name='index'),
     # ...
]