【问题标题】:How to avoid calling get_absolute_url each time on page (django)?如何避免每次在页面(django)上调用 get_absolute_url?
【发布时间】:2016-07-20 19:11:10
【问题描述】:

每个人都说在模板中使用 get_absolute_url 是非常好的做法。但在我的情况下,它会在单个页面上对数据库产生许多相同的查询。 这是我必须开发的 url 结构(我无法更改它,因为客户已经在使用网站,如果我更改 url,Google 不会喜欢它) - mysite/category/subcategory/product_slug.html 这是url模式的代码:

from django.conf.urls import url

从 .导入视图

urlpatterns = [
    url(r'^(?P<parent_category_slug>[\w-]+)/(?P<category_slug>[\w-]+)/(?P<slug>[\w-]+)\.html$', views.ProductDetailView.as_view(), name='product_detail'),
    url(r'^(?P<parent_slug>[\w-]+)/(?P<slug>[\w-]+)$', views.ProductListView.as_view(), name='products_of_category'),
    url(r'^(?P<slug>\w+)$', views.SubCategoryListView.as_view(), name='sub_category'),
    url(r'^$', views.CatalogIndexListView.as_view(), name='index'),
]

这是产品模型中get_absolute_url的代码:

def get_absolute_url(self):
    return reverse('product_detail', kwargs={'slug':self.slug, 'parent_category_slug':self.product_category.category_parent.slug,
                                             'category_slug':self.product_category.slug})

因此,当我访问 mysite/category/subcategory 时,我看到所有产品都属于该子类别。这是一个列表(实际上是表格,带有图像、标题等)。 所有图片和标题都必须是产品的网址。 这是模板中的一段代码

e {% for product in products %}

                    <tr>
                        <td class="product_name_list">
                            <a href="{{ product.get_absolute_url }}">{{ product.product_name }}</a>
                        </td>
                        <td class="product_article_list">{{ product.product_article }}</td>
                        {% if product.product_main_image  %}
                            <td class="product_image_list"><a href="{{ product.get_absolute_url }}" ><img src='{{ product.product_main_image.url}}' alt=""></a></td>
                        {% else %}
                            <td class="product_image_list"><a href="{{ product.get_absolute_url }}" ><img src='{% static "images/empty.gif" %}' alt=""></a></td>
                        {% endif %}

                        <td class="product_request_list"><a href="#">Запросить</a></td>
                    </tr>

             {% endfor %}

所以,结果,我确实有很多对数据库的查询,因为 get_absolute_url 被重复调用。

请帮助我避免这种情况。我尝试使用“get_related()”设置默认的 Manager 类,但这很愚蠢,显然它没有帮助,因为每个实例都一次又一次地调用方法 get_absolute_url。

提前致谢!

【问题讨论】:

    标签: django django-models django-templates django-views


    【解决方案1】:

    你可以使用django的cached_property装饰器来解决这个问题

    from django.utils.functional import cached_property
    
    # You can either use it convert `get_abolute_url` method to property
    @cached_property
    def get_absolute_url(self):
        return reverse(
            'product_detail', kwargs={
                'slug':self.slug,
                'parent_category_slug':self.product_category.category_parent.slug,
                'category_slug':self.product_category.slug})
    
    # or decorate the method with different name so that you can use both
    
    cached_absolute_url = cached_property(get_absolute_url)
    

    这样你就可以同时使用了,

    object.get_absolute_url()
    
    object.cached_absolute_url
    

    cached_property缓存了方法的值,这样当你再次调用它时,它不会运行整个方法,而是直接返回缓存的值。

    【讨论】:

    • 我无法在您的答案中添加“+”。您的回答并不是我真正需要的,但仍然非常有用。我明白了,我应该在我的视图中在查询集中使用 {% url %} 和 'select_related'、'prefetch_related'。
    • 使用 url 标签与使用get_absolute_url 相同。事实上,通常建议使用get_absolute_url 而不是url 标记来生成模型对象的DRY 链接。
    • get_absolute_url 上使用@cached_property 装饰器有什么缺点?我很惊讶默认情况下不推荐在文档中?我不明白用例有单独的cached_absolute_url
    • 一个可能的缺点是,如果 get_absolute_url 的值由于模型实例中的某些更改而发生更改,则缓存的 url 仍将指向过期的 url。 cached_absolute_url 只是将获取 url 的真实方式和缓存方式分开的示例。
    猜你喜欢
    • 1970-01-01
    • 2023-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-01-22
    • 2010-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多