如何在 Django 中编写请求过滤器/预处理器

发布于 2024-09-19 15:14:23 字数 1113 浏览 3 评论 0原文

我正在 Django 中编写一个应用程序,它在 url 中使用 [year]/[month]/[title-text] 来识别新闻项。为了管理这些项目,我定义了许多 URL,每个 URL 都以上述前缀开头。

urlpatterns = patterns('msite.views',
    (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/edit/$', 'edit'),
    (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/$', 'show'),
    (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/save$', 'save'),
)

我想知道 Django 中是否有一种机制,允许我预处理对视图 editshowsave 的给定请求。它可以解析参数,例如year=2010、month=11、slug='this-is-a-title'并从中提取模型对象。

这样做的好处是,我可以将我的视图定义为“

def show(news_item):
    '''does some stuff with the news item, doesn't have to care 
       about how to extract the item from request data'''
    ...

What

def show(year, month, slug): 
    '''extract the model instance manually inside this method'''
    ...

is the Django way to Solution this?” 或者以更通用的方式,是否有某种机制来实现请求过滤器/预处理器,例如在 JavaEE 和 Ruby on Rails 中?

I am writing an application in Django, which uses [year]/[month]/[title-text] in the url to identitfy news items. To manage the items I have defined a number of urls, each starting with the above prefix.

urlpatterns = patterns('msite.views',
    (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/edit/

I was wondering, if there is a mechanism in Django, which allows me to preprocess a given request to the views edit, show and save. It could parse the parameters e.g. year=2010, month=11, slug='this-is-a-title' and extract a model object out of them.

The benefit would be, that I could define my views as

def show(news_item):
    '''does some stuff with the news item, doesn't have to care 
       about how to extract the item from request data'''
    ...

instead of

def show(year, month, slug): 
    '''extract the model instance manually inside this method'''
    ...

What is the Django way of solving this?
Or in a more generic way, is there some mechanism to implement request filters / preprocessors such as in JavaEE and Ruby on Rails?

, 'edit'), (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/

I was wondering, if there is a mechanism in Django, which allows me to preprocess a given request to the views edit, show and save. It could parse the parameters e.g. year=2010, month=11, slug='this-is-a-title' and extract a model object out of them.

The benefit would be, that I could define my views as


instead of


What is the Django way of solving this?
Or in a more generic way, is there some mechanism to implement request filters / preprocessors such as in JavaEE and Ruby on Rails?

, 'show'), (r'^(?P<year>[\d]{4})/(?P<month>[\d]{1,2})/(?P<slug>[\w]+)/save

I was wondering, if there is a mechanism in Django, which allows me to preprocess a given request to the views edit, show and save. It could parse the parameters e.g. year=2010, month=11, slug='this-is-a-title' and extract a model object out of them.

The benefit would be, that I could define my views as


instead of


What is the Django way of solving this?
Or in a more generic way, is there some mechanism to implement request filters / preprocessors such as in JavaEE and Ruby on Rails?

, 'save'), )

I was wondering, if there is a mechanism in Django, which allows me to preprocess a given request to the views edit, show and save. It could parse the parameters e.g. year=2010, month=11, slug='this-is-a-title' and extract a model object out of them.

The benefit would be, that I could define my views as

instead of

What is the Django way of solving this?
Or in a more generic way, is there some mechanism to implement request filters / preprocessors such as in JavaEE and Ruby on Rails?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

温柔少女心 2024-09-26 15:14:24

做到这一点的一种方法是编写一个自定义装饰器。我在我的一个项目中对此进行了测试,并且它有效。

首先,自定义装饰器。除了函数之外,这个函数还必须接受其他参数,因此我们声明另一个装饰器来实现这一点。

decorator_with_arguments = lambda decorator: lambda * args, **kwargs: lambda func: decorator(func, *args, **kwargs)

现在是实际的装饰器:

@decorator_with_arguments
def parse_args_and_create_instance(function, klass, attr_names):
    def _function(request, *args, **kwargs):
        model_attributes_and_values = dict()
        for name in attr_names:
            value = kwargs.get(name, None)
            if value: model_attributes_and_values[name] = value

        model_instance = klass.objects.get(**model_attributes_and_values)
        return function(model_instance)
    return _function

除了它正在装饰的函数之外,该装饰器还需要两个附加参数。它们分别是要为其准备和注入实例的模型类以及要用于准备实例的属性的名称。在这种情况下,装饰器使用属性从数据库中获取实例。

现在,“通用”视图使用 show 函数。

def show(model_instance):
    return HttpResponse(model_instance.some_attribute)

show_order = parse_args_and_create_instance(Order, ['order_id'])(show)

另外:

show_customer = parse_args_and_create_instance(Customer, ['id'])(show)

为了使其正常工作,URL 配置参数必须包含与属性相同的关键字。当然,您可以通过调整装饰器来自定义它。

# urls.py
...
url(r'^order/(?P<order_id>\d+)/

正确更新

作为@rebus指出您还需要研究 Django 的通用视图。

, 'show_order', {}, name = 'show_order'), url(r'^customer/(?P<id>\d+)/

正确更新

作为@rebus指出您还需要研究 Django 的通用视图。

, 'show_customer', {}, name = 'show_customer'), ...

正确更新

作为@rebus指出您还需要研究 Django 的通用视图。

One way of doing this is to write a custom decorator. I tested this in one of my projects and it worked.

First, a custom decorator. This one will have to accept other arguments beside the function, so we declare another decorator to make it so.

decorator_with_arguments = lambda decorator: lambda * args, **kwargs: lambda func: decorator(func, *args, **kwargs)

Now the actual decorator:

@decorator_with_arguments
def parse_args_and_create_instance(function, klass, attr_names):
    def _function(request, *args, **kwargs):
        model_attributes_and_values = dict()
        for name in attr_names:
            value = kwargs.get(name, None)
            if value: model_attributes_and_values[name] = value

        model_instance = klass.objects.get(**model_attributes_and_values)
        return function(model_instance)
    return _function

This decorator expects two additional arguments besides the function it is decorating. These are respectively the model class for which the instance is to be prepared and injected and the names of the attributes to be used to prepare the instance. In this case the decorator uses the attributes to get the instance from the database.

And now, a "generic" view making use of a show function.

def show(model_instance):
    return HttpResponse(model_instance.some_attribute)

show_order = parse_args_and_create_instance(Order, ['order_id'])(show)

And another:

show_customer = parse_args_and_create_instance(Customer, ['id'])(show)

In order for this to work the URL configuration parameters must contain the same key words as the attributes. Of course you can customize this by tweaking the decorator.

# urls.py
...
url(r'^order/(?P<order_id>\d+)/

Update

As @rebus correctly pointed out you also need to investigate Django's generic views.

, 'show_order', {}, name = 'show_order'), url(r'^customer/(?P<id>\d+)/

Update

As @rebus correctly pointed out you also need to investigate Django's generic views.

, 'show_customer', {}, name = 'show_customer'), ...

Update

As @rebus correctly pointed out you also need to investigate Django's generic views.

篱下浅笙歌 2024-09-26 15:14:24

毕竟 Django 是 python,所以你可以轻松地做到这一点:

def get_item(*args, **kwargs):
    year = kwargs['year']
    month = kwargs['month']
    slug = kwargs['slug']
    # return item based on year, month, slug...

def show(request, *args, **kwargs):
    item = get_item(request, *args, **kwargs)
    # rest of your logic using item
    # return HttpResponse...

Django is python after all, so you can easily do this:

def get_item(*args, **kwargs):
    year = kwargs['year']
    month = kwargs['month']
    slug = kwargs['slug']
    # return item based on year, month, slug...

def show(request, *args, **kwargs):
    item = get_item(request, *args, **kwargs)
    # rest of your logic using item
    # return HttpResponse...
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文