2

我正在向站点添加一种新类型的用户配置文件,这种新类型的用户(比如 new_type)应该无法像现有用户一样访问相同的视图。

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

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

每个视图?

详细地:

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

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

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

举个简单的例子:从同一个登录 url 登录 admin 和普通用户,如果用户是 admin,则为 admin 运行相关视图并将 django admin 显示返回给她,如果是普通用户,则运行普通视图并返回 normal网站查看给她,无需重写或更改他们请求的 url。(例如/索引/)

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

谢谢

4

3 回答 3

2

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

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

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

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

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)

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

于 2011-07-09T12:08:49.303 回答
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 属性来确定要返回的视图。丑陋,但比修改无数的观点要好。

于 2011-07-09T13:08:38.960 回答
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'),
     # ...
]
于 2017-01-20T12:09:42.243 回答