如何避免Django高频访问视图中的重复数据库查询?
嘿,针对你遇到的Django视图重复执行查询的问题,这里有几个实用的解决方案,结合你给出的代码场景来拆解:
1. 利用Django内置缓存框架(最适合你的场景)
你的related_negos和all_jobs更新频率很低(一个每2个月、一个每周),完全适合用缓存把查询结果存起来,避免每次请求都跑数据库。Django的低级别缓存API可以精准控制要缓存的内容:
from django.core.cache import cache @access_to(['is_admin','is_job_seeker']) def negotiationView(request,slug,id,code): obj = get_object_or_404(Group,slug=slug) nego = get_object_or_404(Negotiation,id=id,code=code) # 缓存related_negos,按tag ID生成唯一缓存键,有效期60天 cache_key_related = f"related_negos_{nego.tag.id}" related_negos = cache.get(cache_key_related) if not related_negos: # 查询后转成列表(QuerySet不能直接序列化缓存) related_negos = list(Negotiation.objects.filter(tag=nego.tag)) cache.set(cache_key_related, related_negos, timeout=60*60*24*60) # 缓存all_jobs,按Group ID生成唯一缓存键,有效期7天 cache_key_jobs = f"group_published_jobs_{obj.id}" all_jobs = cache.get(cache_key_jobs) if not all_jobs: all_jobs = list(obj.job_offers.filter(published=True)) cache.set(cache_key_jobs, all_jobs, timeout=60*60*24*7) # 后续业务逻辑...
注意:当你创建新tag或发布新job时,记得手动清除对应缓存(比如调用cache.delete(cache_key_related)),这样用户就能看到最新数据了。
2. 单次请求内避免重复查询(辅助优化)
如果你的视图里多次用到同一个查询结果,还可以把它存在request对象里,避免同一次请求内重复执行:
# 比如视图里多次需要related_negos的话 if not hasattr(request, '_cached_related_negos'): request._cached_related_negos = list(Negotiation.objects.filter(tag=nego.tag)) related_negos = request._cached_related_negos
这个方法只解决单次请求内的重复,跨请求还是得靠缓存框架。
3. 模板层面缓存渲染片段
如果这些查询结果是直接在模板里渲染的,还可以用Django的模板缓存标签,直接缓存渲染后的HTML片段,既省查询又省渲染时间:
{% load cache %} {# 缓存related_negos的渲染结果,有效期60天 #} {% cache 5184000 related_negos_block nego.tag.id %} {% for nego_item in related_negos %} <div>{{ nego_item.title }}</div> {% endfor %} {% endcache %} {# 缓存all_jobs的渲染结果,有效期7天 #} {% cache 604800 group_jobs_block obj.id %} {% for job in all_jobs %} <div>{{ job.title }}</div> {% endfor %} {% endcache %}
4. 数据库索引优化
即使最终还是要执行查询,给查询字段加索引也能大幅提升速度。比如在你的模型里给常用过滤字段加索引:
class Negotiation(models.Model): tag = models.ForeignKey(Tag, on_delete=models.CASCADE, db_index=True) # 其他字段... class JobOffer(models.Model): published = models.BooleanField(default=False, db_index=True) group = models.ForeignKey(Group, on_delete=models.CASCADE) # 其他字段...
这样数据库会更快找到符合条件的数据,减少查询耗时。
内容的提问来源于stack exchange,提问作者user9865749
相关产品推荐
相关产品推荐

