我很难理解Django ORM中的prefetch_related
和select_related
。我有以下型号:
class City(models.Model):
name = models.CharField(max_length=35)
state = models.ForeignKey('states.State', on_delete=models.CASCADE)
class Street(models.Model):
name = models.CharField(max_length=35)
building = models.ForeignKey('buildings.Building', on_delete=models.CASCADE)
city = models.ForeignKey('cities.City', on_delete=models.CASCADE)
现在我的views.py:
cities = City.objects.all()
streets = Street.objects.all()
for city in cities:
has_bank = streets.filter(building_id=1, city=city)
if has_bank:
city.has_bank = 1
has_cinema = streets.filter(building_id=2, city=city)
if has_cinema:
city.has_cinema = 1
has_church = streets.filter(building_id=3, city=city)
if has_church:
city.has_church = 1
但是现在,每次for循环迭代时,它都会访问数据库3次。我试图提高时间复杂度——现在是3N 2,N是城市的数量,但是我不能理解select_related和prefetch_related。
你能给我一个例子,我该如何改进它,使它不会在for循环中命中数据库3次吗?
选择相关。让我解释一下。我添加了虚拟数据来解释。
class City(models.Model):
name = models.CharField(max_length=35)
state = models.ForeignKey('states.State', on_delete=models.CASCADE)
class Street(models.Model):
name = models.CharField(max_length=35)
building = models.ForeignKey('buildings.Building', on_delete=models.CASCADE)
city = models.ForeignKey('cities.City', on_delete=models.CASCADE)
您的城市表应该是。
id name state
1 Cityname1 state1
2 Cityname2 2
你的街头桌子应该是。
id name city ..
1 st 1 1
2 stno.2 1
3 st no3 2
如果你的orm查询将是这个。
street = Street.objects.select_related('city')
此查询将两个表合并为一个表。这意味着所有的城市id外键将连接到每个街道id以创建如下新表。它将返回3条记录,因为我们使用的是选择相关的城市,主表在这种情况下是街道,所以它将返回3条记录。主表在所有情况下将首先返回dajngo。
id name city .. city.id city.name city.state
1 st 1 1 1 Cityname1 state1
2 stno.2 1 1 Cityname1 state1
3 st no3 2 2 Cityname2 2
在您的具体情况下,我认为最好使用注释而不是预取:
from django.db.models import Count, Q
cities = City.objects
.annotate(bank_count=Count("street", filter=Q(street__building_id=1)))
.annotate(cinema_count=Count("street", filter=Q(street__building_id=2)))
.annotate(church_count=Count("street", filter=Q(street__building_id=3)))
现在您可以直接使用bank\u count
、cinema\u count
和church\u count
属性:
for city in cities:
print(city.bank_count)
print(city.cinema_count)
print(city.church_count)
如果要使用prefetch\u related
,则需要使用prefetch
对象。这允许您过滤预取的对象:
City.objects.prefect_related(
Prefetch("street_set", queryset=Street.objects.filter(building_id=1), to_attr='has_bank'),
Prefetch("street_set", queryset=Street.objects.filter(building_id=2), to_attr='has_cinema'),
Prefetch("street_set", queryset=Street.objects.filter(building_id=3), to_attr='has_church')
)
注意to_attr
参数这有助于使用不同的过滤器将同一模型的对象预取到不同的属性。所以你现在可以做:
for city in cities:
print(city.has_bank)
print(city.has_cinema)
print(city.has_church)
问题内容: django-smart-selects是一个优雅的解决方案,它使Django开发人员能够在其表单中链接选择输入。但是,正如开发人员在其问题清单中所报告的那样,在表单集中使用它时效果不佳。 它呈现的JavaScript与模型定义中“已链接字段”的ID绑定在一起。 当您在表单集中使用它时,您如何看待它如何工作?我认为小部件的渲染方法(请参阅django-smart- selects代码)
我正在开发一个巴士预订应用程序。我使用Recyclerview和GridLayoutManager创建了座位预订布局。布局已正确创建。我1排有4个座位,最后一排有5个座位。所以我在GridLayoutManager中使用了5个列。中间立柱空出两个座位之间的空间供步行。现在的问题是,如果我点击第1个座位,将选择第1个座位,但图像变化的第5个座位。并且我还在textview中设置了座位号,所以有时显示
这里,我们将介绍一下拾取和选择的区别和使用方法。 拾取 通过平台提供的属性和接口,我们可以获取鼠标拾取到(Pick)的物体,将下面的代码输入到项目文件中,即可打印当前拾取和之前拾取的物体。 // 每一帧判断拾取的物体是否发生变化 app.on('update', function () { if (app.picker.isChanged()) { console.clear(); //
问题内容: 我是Django的新手,如果您能向我提供一些指导,我将不胜感激。我正在尝试创建一种允许用户在一个或多个选项上打勾的表格。我知道我必须将MultiChoiceField字段与CheckboxSelectMultiple小部件一起使用,但是Django文档没有提供有关此主题的示例。如果您能给我一个例子并解释如何处理结果,将不胜感激。例如,如果我有一个带有选项abcd的表单,并且用户在c和d
问题内容: 我需要具有2个字段的django modelform,其中第二个字段选择列表取决于在第一个字段中选择的内容。我的模特: 如果vehicle_type设置为 personal, 如何将 make 字段的选择设置为 PERSONAL_MAKES ?我怎样才能做到这一点?在模型级别上可以吗? __ 问题答案: 您可能不能,因为这取决于用户与表单的交互:您的服务器无法预先知道用户将表单发送到浏
问题内容: models.py: views.py: 在模板上,当我调用时,我得到而不是。 如何显示值(或)而不是代码()? 问题答案: 看来你走在正确的轨道上- 无疑是你想要的: 在模板中,你不包括方法名称。请执行下列操作: