用于重定向的 Django 自定义装饰器

Posted

技术标签:

【中文标题】用于重定向的 Django 自定义装饰器【英文标题】:Django custom decorator for redirections 【发布时间】:2021-11-25 17:05:18 【问题描述】:

我正在 Django 中部署一个多域平台,其中包含一些用于在网站之间执行重定向的模型逻辑。

由于重定向映射会变得有点庞大,我宁愿装饰每个视图,而不是在每个视图中复制用于重定向的代码(对于这个项目,我坚持使用基于函数的视图)。由于逻辑也可能会更改,因此我需要将所有内容集中在一个地方,并且我真的很想为此使用自定义装饰器。

我一直在尝试不同的语法来定义装饰器,但遇到了各种各样的问题。 https://pythonbasics.org/decorators/ 我正在使用我在这里看到的语法,但一开始我无法将它应用于 Django 视图。我正在使用 Django 3.2。这是与我的情况最相似的线程,它帮助我更接近我想要的结果Django custom decorator redirect problem 但是我的装饰器视图仍然返回 None 而不是 HttpResponse 对象,我不明白。

装饰器 1

    def inner(request, *args, **kwargs):
        print("DEBUGGING")
        if settings.DEBUG == False or request.user.is_superuser == False:
            return render(request, 'myapp/manutenzione.html')
        func(request, *args, **kwargs)
    return inner

装饰器 2 用于我的重定向

def reindirizzamenti_necessari(func):
    def inner(request, *args, **kwargs):
        print("REINDIRIZZAMENTI")


        sito = get_current_site(request)
        dominio = sito.domain
        if dominio[0:4] == "www.":
            dominio = dominio.split("www.")[1]
        try:

            dominio = Dominio.objects.get(dominio = dominio)
            sito_generale = False

            # Redirect to the main domain
            if not dominio.principale:
                redirect_necessario = True
                url = '/redirect/' + dominio.città.nome.lower()
                return redirect(url)
            context['luogo'] = dominio.città

        except:

            print("DOMINIO GENERALE")

            if dominio.endswith(".it"):
                return redirect("https://www.mymaindomainname.com") #not using this now, just moving forward to func()

            func(request, *args, **kwargs) # <---- I THINK THIS IS WHAT IS NOT WORKING (from checking the prints, I get this last one)
    return inner

我的装饰视图

@debugging
@reindirizzamenti_necessari
def homepage(request):

    context = 

    return render(request, 'myapp/index.html', context)

我当前的重定向视图

def redirect_domain(request, city):

    città_url = City.objects.get(nome = city)
    dominio_principale_città = Dominio.objects.get(città = città_url, principale = True)
    url_finale = "https://" + dominio_principale_città.dominio

    return redirect(url_finale)

当我现在调用“主页”视图时,我得到了

ValueError at /my-path

The view myapp.views.inner didn't return an HttpResponse object. It returned None instead.

【问题讨论】:

您需要从装饰器中的inner 函数返回响应,返回视图在基本情况下返回的内容,否则您只是调用视图而不对响应执行任何操作:@ 987654329@ 谢谢你,看来这是我错过的最后一点! 【参考方案1】:

在我看来,你应该使用中间件而不是装饰器。

https://docs.djangoproject.com/en/3.2/topics/http/middleware/#process-view

【讨论】:

我考虑过这个选项,但我需要基于每个视图应用重定向,所以我认为装饰器方法确实是正确的

以上是关于用于重定向的 Django 自定义装饰器的主要内容,如果未能解决你的问题,请参考以下文章

Django 自定义视图装饰器

带有自定义错误消息的 Django 重定向

如何使用自定义 django 404 错误视图重定向?

登录django后如何转到另一个页面

如何将 is_staff 用户重定向到 Django 中的自定义模板?

用于覆盖 post 方法的 Django REST 框架自定义装饰器