Django - 避免在视图中重复代码的技巧 [英] Django - Tips to avoid repeating code in views

查看:17
本文介绍了Django - 避免在视图中重复代码的技巧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在通过 Python 从 PHP 背景转向 Django 开发,主要是为了解决我认为最有意义的 MVC(或 MVT),尽管在这种模式中我已经开始注意到很多在我的视图中重复代码.

I'm moving from a PHP background into Django development via python, mostly for the sake of tackling a MVC (or MVT) that I feel makes the most sense, although in this pattern I've started to notice a lot of repeated code in my views.

例如,当登录时,我有关于我希望出现在每个页面上的用户的信息,尽管在使用 render_to_response 并且在每个视图中这都是必需的时,我必须获取信息并将其传递给 render_to_response 函数.

For example, when logged in I have information regarding the user that I would like to appear on every page, although when using render_to_response and in every view this is required I have to grab the information and pass it to the render_to_response function.

我想知道减少重复代码的最有效方法是什么,而重复代码本质上是特定应用程序中所有视图所必需的.

I'm wondering what would be the most efficient way to cut down on the duplicate code which would in essence be required in all views in a particular app.

提前致谢.

推荐答案

就我个人而言,我是装饰器的忠实粉丝,装饰器是一个 Python 特性,不是 Django 特有的.装饰器是高阶函数之上的完美语法糖,它们对于减少视图中的样板文件特别有用——您可以快速定义一个通用的包装器函数,您可以在其中放置重复代码以便于重用和方便-停止重构.

Personally I am a huge fan of decorators, which are a python feature that isn't specific to Django. Decorators are the perfect syntactic sugar on top of higher-order functions, and they're especially useful for reducing boilerplate in views -- you can quickly define a generalized wrapper function, in which you can put the repetitive code for easy reuse and convenient one-stop refactoring.

向您展示可能比解释它们的工作原理更容易.这是一个简化的视图示例:

It's probably easier to show you than explain how they work. Here is a simplified view example:

def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

...然后说你想让这些页面要求用户登录.你可以像这样添加登录代码:

... but then say you wanted to make these pages require the user to log in. You might add login code like so:

def listpage(request):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.filter(visible=True).order_by("-modifydate")
        }))

def itemlist_tags(request, tags):
    if not request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponse(render_to_string("itemlist.html", {
            "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
        }))

...它开始变得明显更大和重复,即使是一个人为的例子.您可以使用装饰器使您的函数再次变瘦,如下所示:

... which is starting to get notably bigger and repetitive, even for a contrived example. You can make your functions slim again with decorators, like so:

从装饰器导入装饰器

@decorator
def loginrequired(f, request, *args, **kwargs):
    if request.user.is_authenticated():
        return f(request, *args, **kwargs)
    else:
        return HttpResponseRedirect("/")

@loginrequired
def listpage(request):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.filter(visible=True).order_by("-modifydate")
    }))

    @loginrequired
def itemlist_tags(request, tags):
    return HttpResponse(render_to_string("itemlist.html", {
        "items": Item.objects.tagged(name=tags).filter(visible=True).order_by("-modifydate"),
    }))

@loginrequired
def another_such_function(request):
    (...)

@loginrequired
def and_again(request):
    (...)

装饰器函数在函数定义时执行.我的示例中的f"是一个对象,表示装饰器所应用到的函数,您可以无休止地对其进行操作.

What happens is the decorator function is executed at the time of the function's definition. The 'f' in my example is an object representing the function that the decorator is applied to, which you can manipulate in unending ways.

这需要 decorator 库,它在 PyPI 上是免费的,还有很多好的 python 小食,你会找到.

This requires the decorator library, which is free on PyPI as are many good python morsels, you'll find.

你不需要这个库来编写装饰器函数,但它很有帮助,尤其是在开始的时候.他们可以做更多的事情——任何可调用的都可以是装饰器;可以修饰类方法,拦截self变量;装饰器可以像这样链接起来:

You don't need the this library to write decorator functions, but it's helpful, especially in the beginning. They can do a whole lot more -- any callable can be a decorator; you can decorate class methods and intercept the self variable; decorators can be chained up, like so:

@second
@first
def originalfunction(*args):
    (...)

如果这个概念激起了你的胃口,我将把你可以用这种简单的高阶函数操作做些什么的探索留给你.我还有更多示例,供您或任何其他好奇的新 Python 爱好者使用.祝你好运.

I'll leave the exploration of what you can do with such easy higher-order function manpipulation for you, should this notion whet your appetite. I have many more examples as well, for you or any other curious new python aficionados. Good luck.

这篇关于Django - 避免在视图中重复代码的技巧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆