python-Django反向m2m查询
内容导读
互联网集市收集整理的这篇技术教程文章主要介绍了python-Django反向m2m查询,小编现在分享给大家,供广大互联网技能从业者学习和参考。文章包含2816字,纯文字阅读大概需要5分钟。
内容图文
![python-Django反向m2m查询](/upload/InfoBanner/zyjiaocheng/669/6e626f79ce254fc4a933ea6a307ff9a4.jpg)
使用https://docs.djangoproject.com/en/dev/topics/db/queries/#making-queries之后的模型进行少量修改:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
class Author(models.Model):
name = models.CharField(max_length=200)
joined = models.DateField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
authors = models.ManyToManyField(Author)
rating = models.IntegerField()
我想创建一个从Author到Entries的词典,作者今年加入了该词典,并且Entry的评分为4或更高.结果字典的结构应如下所示:
author_entries = {author1: [set of entries], author2: [set of entries], etc.}
而访问数据库的时间少于3’ish次(或至少与作者或条目的数量不成比例).
我的第一次尝试(db hits ==作者数量,100作者100 db-hits):
res = {}
authors = Author.objects.filter(joined__year=date.today().year)
for author in authors:
res[author] = set(author.entry_set.filter(rating__gte=4))
第二次尝试,尝试一次读取条目:
res = {}
authors = Author.objects.filter(joined__year=date.today().year)
entries = Entry.objects.select_related().filter(rating__gte=4, authors__in=authors)
for author in authors:
res[author] = {e for e in entries if e.authors.filter(pk=author.pk)}
这甚至更糟,有100位作者,198次db-hits(最初的第二次尝试使用的是{如果e.authors中为author,则在条目中为e}),但是Django却没有.
我发现的唯一方法涉及原始SQL(4个db-hits):
res = {}
_authors = Author.objects.filter(joined__year=date.today().year)
_entries = Entry.objects.select_related().filter(rating__gte=4, authors__in=_authors)
authors = {a.id: a for a in _authors}
entries = {e.id: e for e in _entries}
c = connection.cursor()
c.execute("""
select entry_id, author_id
from sampleapp_entry_authors
where author_id in (%s)
""" % ','.join(str(v) for v in authors.keys()))
res = {a: set() for a in _authors}
for eid, aid in c.fetchall():
if eid in entries:
res[authors[aid]].add(entries[eid])
(在c.execute(..)调用中使用字符串替换的道歉-我找不到在调用中的where所需的sqlite语法).
还有更多的Djangoesque方式可以做到这一点吗?
我用我正在使用的代码(https://github.com/thebjorn/revm2m)创建了一个git repo,测试在https://github.com/thebjorn/revm2m/blob/master/revm2m/sampleapp/tests.py中进行
解决方法:
您可以为此使用Prefetch-object [Django-doc]:
from django.db.models import Prefetch
good_ratings = Prefetch(
'entry_set',
queryset=Entry.objects.filter(rating__gte=4),
to_attr='good_ratings'
)
authors = Author.objects.filter(
joined__year=date.today().year
).prefetch_related(
good_ratings
)
现在,authors中的Author对象将具有一个额外的属性good_ratings(Prefetch对象的to_attr的值),该属性是预加载的QuerySet,其中包含条目的评分大于或等于4.
因此,您可以像这样对它们进行后处理:
res = {
author: set(author.good_ratings)
for author in authors
}
尽管由于Author对象(通常不是从此QuerySet获得)已经带有属性,所以无论如何可能没有太多用途.
内容总结
以上是互联网集市为您收集整理的python-Django反向m2m查询全部内容,希望文章能够帮你解决python-Django反向m2m查询所遇到的程序开发问题。 如果觉得互联网集市技术教程内容还不错,欢迎将互联网集市网站推荐给程序员好友。
内容备注
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 gblab@vip.qq.com 举报,一经查实,本站将立刻删除。
内容手机端
扫描二维码推送至手机访问。