我有这个模型:
class Country(models.Model):
name = models.CharField(max_length=250)
def __str__(self):
return str(self.name)
class City(models.Model):
name = models.CharField(max_length=250)
country = models.ForeignKey(Country, default=None, blank=True)
def __str__(self):
return str(self.name)
class Airport(models.Model):
name = models.CharField(max_length=250)
city = models.ForeignKey(City, default=None, blank=True)
def __str__(self):
return "{0} - {1} - {2}".format(self.city, self.city.country, self.name)
class Tour(models.Model):
title = models.CharField(max_length=200)
tour_from = models.ForeignKey(Airport)
tour_to = models.ForeignKey(Airport)
def __str__(self):
return str(self.title)
对于Airport
的字符串表示形式,Django向DB发送了许多请求:
302.06毫秒(591个查询,包括586个相似项和586个重复项)
在tour/create
页上,我有一个用于创建游览的ModelForm,而Django发送这些查询以显示表单。
forms.py:
class TourCreateForm(forms.ModelForm):
class Meta:
model = Tour
fields = ['title', 'tour_from', 'tour_to']
views.py:
class DashboardTourCreate(CreateView):
model = Tour
template_name = "dashboard/tour/create.html"
form_class = TourCreateForm
def get_context_data(self, **kwargs):
context = super(DashboardTourCreate, self).get_context_data(**kwargs)
context['page_name'] = ['tour', 'tour-index']
context['page_title'] = "Create Tour"
return context
如何减少查询数量?
答案 0 :(得分:2)
def __str__(self):
return "{0} - {1} - {2}".format(self.city, self.city.country, self.name)
在tour_to
小部件中将tour_from
和<option>
字段呈现为<select>
时,将调用Airport.__str__
方法。由于Airport.__str__
具有self.city.county
,并且两者都是ForeignKey
,因此Django ORM发出查询以获取机场城市和城市国家。
它对每个Airport
的每个<option>
都执行此操作,这意味着添加的Airport
越多,问题就会变得越来越严重。
利用select_related
[1]。 select_related
会告诉Django ORM每当抓住('city', 'county')
时就拉入相关字段Airport
。
class TourCreateForm(forms.ModelForm):
class Meta:
model = Tour
fields = ['title', 'tour_from', 'tour_to']
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['tour_from'].queryset = Airport.objects.select_related(
'city__country',
)
self.fields['tour_to'].queryset = Airport.objects.select_related(
'city__country',
)
[1] https://docs.djangoproject.com/en/2.1/ref/models/querysets/#select-related
答案 1 :(得分:0)
由于f字符串是在运行时link中计算的字符串文字表达式,因此它可能比其他字符串格式更快,但我不确定。我希望进行以下修改可以减少总时间。
class Airport(models.Model):
name = models.CharField(max_length=250)
city = models.ForeignKey(City, default=None, blank=True)
def __str__(self):
return f"{self.city} - {self.city.country} - {self.name}"
答案 2 :(得分:0)
我通过将Queryset
添加到forms.py
来解决此问题:
class TourCreateForm(BaseForm):
airports = Airport.objects.select_related('city', 'city__country').all()
tour_from = forms.ModelChoiceField(queryset=airports)
tour_to = forms.ModelChoiceField(queryset=airports)
但是我认为这是不正确的!