代码之家  ›  专栏  ›  技术社区  ›  nre

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

  •  2
  • nre  · 技术社区  · 16 年前

    我正在用Django编写一个应用程序,它使用 [year]/[month]/[title-text]

    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中是否有一种机制,允许我对给定的视图请求进行预处理 edit , show 和 save . 它可以解析参数,例如。 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'''
        ...
    

    而不是

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

    Django解决这个问题的方法是什么? 或者用一种更通用的方式,是否有一些机制来实现请求过滤器/预处理器,比如JavaEE和rubyonrails?

    3 回复  |  直到 16 年前
        2
  •  1
  •   Community Mohan Dere    9 年前

    首先,一个定制的装饰师。这个函数必须接受函数之外的其他参数,所以我们声明 另一个

    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
    

    这个装饰器除了要装饰的函数之外,还需要两个额外的参数。它们分别是要为其准备和注入实例的模型类和要用于准备实例的属性的名称。在本例中,decorator使用属性 get 数据库中的实例。

    现在,一个使用 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配置参数必须包含与属性相同的关键字。当然,您可以通过调整decorator来定制它。

    # urls.py
    ...
    url(r'^order/(?P<order_id>\d+)/$', 'show_order', {}, name = 'show_order'),
    url(r'^customer/(?P<id>\d+)/$', 'show_customer', {}, name = 'show_customer'),
    ... 
    

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

        3
  •  0
  •   Ofri Raviv    16 年前

    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...
    
    推荐文章