Django预取与中间表没有重复
发布时间:2020-12-16 21:30:40 所属栏目:Python 来源:网络整理
导读:我有一个问题,我现在想解决一天. 随着模型 class Quote(models.Model): text = models.TextField() source = models.ForeignKey(Source) tags = models.ManyToManyField(Tag) ...class Source(models.Model): title = models.CharField(max_length=100) ...c
我有一个问题,我现在想解决一天.
随着模型 class Quote(models.Model): text = models.TextField() source = models.ForeignKey(Source) tags = models.ManyToManyField(Tag) ... class Source(models.Model): title = models.CharField(max_length=100) ... class Tag(models.Model): name = models.CharField(max_length=30,unique=True) slug = models.SlugField(max_length=40,unique=True) ... 我试图模拟引号的世界.与关系:一个源有很多报价,一个报价有很多标签. >如何获取源中包含的所有标记(通过包含的引号)? 我用模型方法尝试了没有预取相关的天真的 def source_tags(self): tags = Tag.objects.filter(quote__source__id=self.id).distinct().annotate(usage_count=Count('quote')) return sorted(tags,key=lambda tag:-tag.usage_count) 在模板中: {% for tag in source.source_tags|slice:":5" %} source.quote {% endfor %} 我现在有 sources = Source.objects.all().prefetch_related('quote_set__tags') 在模板中我不知道如何正确迭代以获取一个源的标签,以及我如何计算它们而不是列出重复标签. 解决方法
这将在单个SQL查询中获得结果:
# views.py from django.db.models import Count from .models import Source def get_tag_count(): """ Returns the count of tags associated with each source """ sources = Source.objects.annotate(tag_count=Count('quote__tags')) .values('title','quote__tags__name','tag_count') .order_by('title') # Groupe the results as # {source: {tag: count}} grouped = {} for source in sources: title = source['title'] tag = source['quote__tags__name'] count = source['tag_count'] if not title in grouped: grouped[title] = {} grouped[title][tag] = count return grouped # in template.html {% for source,tags in sources.items %} <h3>{{ source }}</h3> {% for tag,count in tags.items %} {% if tag %} <p>{{ tag }} : {{ count }}</p> {% endif %} {% endfor %} {% endfor %} 补充测试:) # tests.py from django.test import TestCase from .models import Source,Tag,Quote from .views import get_tag_count class SourceTags(TestCase): def setUp(self): abc = Source.objects.create(title='ABC') xyz = Source.objects.create(title='XYZ') inspire = Tag.objects.create(name='Inspire',slug='inspire') lol = Tag.objects.create(name='lol',slug='lol') q1 = Quote.objects.create(text='I am inspired foo',source=abc) q2 = Quote.objects.create(text='I am inspired bar',source=abc) q3 = Quote.objects.create(text='I am lol bar',source=abc) q1.tags = [inspire] q2.tags = [inspire] q3.tags = [inspire,lol] q1.save(),q2.save(),q3.save() def test_count(self): # Ensure that only 1 SQL query is done with self.assertNumQueries(1): sources = get_tag_count() self.assertEqual(sources['ABC']['Inspire'],3) self.assertEqual(sources['ABC']['lol'],1) 我基本上使用了ORM的 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |