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

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

问题描述

通过python,我正在从一个PHP背景变成Django开发,主要是为了解决一个我认为最有意义的MVC(或MVT),尽管在这种模式下,我开始注意到很多



例如,当登录时,我有关于我想在每个页面上显示的用户的信息,虽然在使用render_to_response和每个查看这是必需的,我必须抓住信息并传递给render_to_response函数。



我想知道什么是最有效的方式来减少重复



提前感谢。

解决方案

个人我是装饰器的巨大粉丝,这是一个不是Django特有的python功能。装饰器是高级功能之上的完美语法糖,它们对于减少视图中的样板特别有用 - 您可以快速定义广义包装功能,您可以在其中放置重复的代码,方便复用-stop重构。



可能比您更容易地向您展示它们的工作原理。以下是一个简化的视图示例:

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

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

...但是后来说你想做这些页面要求用户登录,您可以添加如下所示的登录代码:

  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):
如果不t 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),
}))
/ pre>

...它开始显着更大和重复,即使是一个有创意的例子。您可以使用装饰器再次使您的功能变得苗条,如下所示:



从装饰器导入装饰器

 $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ $ * $ * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 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 (可见= True).order_by( - modifydate),
})

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

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

在功能定义时执行装饰器功能会发生什么。我的例子中的'f'是一个表示装饰器应用于的函数的对象,你可以通过不间断的方式进行操作。



这需要装饰器库,这是PyPI上免费的,很多很好的python morsel,你会发现。



你不需要这个库来编写装饰器函数,但是这很有用,特别是在开始的时候。他们可以做更多的事情 - 任何可以打电话的人都可以是装饰师;您可以装饰类方法并拦截 self 变量;装饰器可以链接起来,如下所示:

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

我会离开你可以做这样容易的高阶功能的manpipulation为你,这个概念,你的胃口。我还有更多的例子,对于你或任何其他好奇的新的python爱好者。祝你好运。


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.

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.

Thanks in advance.

解决方案

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:

from decorator import decorator

@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):
    (...)

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.

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

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):
    (...)

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天全站免登陆