我有一个模型表单可以在基于函数的 View 中创建模型实例。 当创建 View 呈现表单模板时,它运行 6 个我想减少的查询。 有什么方法可以减少 qs 或提高模型创建 View 的性能吗?
models.py
class Teacher(models.Model):
name = models.CharField(max_length=150)
photo = models.ImageField(upload_to='teachers',
default='teacheravatar.jpg')
date_of_birth = models.DateField(blank=True, null=True)
designation = models.ForeignKey(Designation, on_delete=models.CASCADE)
expertise = models.ManyToManyField(
to=Topic, blank=True, related_name='expert_in')
mobile = models.CharField(max_length=11, blank=True, null=True)
email = models.CharField(max_length=255, blank=True, null=True)
joining_date = models.DateField(auto_now=True)
class Meta:
ordering = ['joining_date', 'name']
* forms.py *
class TeacherForm(ModelForm):
class Meta:
model = Teacher
fields = ['name', 'photo', 'date_of_birth',
'designation', 'expertise',
'mobile', 'email', ]
*views.py*
# THIS VIEW DUPLICATES QUEREIS
# AND RUNS 6 QUERIES
@login_required
def add_teacher_view(request):
"""
:param request:
:return: teacher add form
"""
if request.method == 'POST':
form = TeacherForm(request.POST)
if form.is_valid():
form.save()
pk = form.instance.pk
return redirect('teachers:teacher_details', pk=pk)
form = TeacherForm()
context = {'form': form}
return render(request, 'teachers/add_teacher.html', context)
最佳答案
您应该在关系字段上定义.choices。当 modelform 中有关系字段时,django modelform 字段会在 request.get 方法中运行重复查询。事实上,我们通过手动提供数据来防止字段运行重复查询。
models.py
class TeacherForm(ModelForm):
class Meta:
model = Teacher
fields = ['name', 'photo', 'date_of_birth',
'designation', 'expertise',
'mobile', 'email', ]
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
designation_choices = [(designation.id, designation.__str__()) for designation in Designation.objects.all()]
expertise_choices = [(topic.id, topic.__str__()) for topic in Topic.objects.all()]
self.fields['designation'].choices = designation_choices
self.fields['expertise'].choices = expertise_choices
我建议您在所有模型中定义str,例如假设您在所有模型的str中返回self.name,您可以像这样定义designation_choices和experience_choices :
designation_choices = Designation.objects.values_list('id', 'name')
expertise_choices = Topic.objects.values_list('id', 'name')
这非常快,因为查询 Designation 或 Topic 的所有字段时只查询其中的两个字段。
更深入
(通过引用 django 类(class)代码来回答,仅供阅读):
django modelform 创建表单字段 ModelChoiceField、ForeignKey 的 ModelMultipleChoiceField、ManyToManyField 字段。这两个字段都使用方法 _get_choices 来创建这些重复的查询。
由 self.iterator(self) 运行的重复查询这里的关键是当提供 _choices 时,默认查询(重复查询)将停止。这里的属性选择将填充变量 _choices 并删除重复的查询。
django.forms.models.py
def _get_choices(self):
# If self._choices is set, then somebody must have manually set
# the property self.choices. In this case, just return self._choices.
if hasattr(self, '_choices'):
return self._choices
# Otherwise, execute the QuerySet in self.queryset to determine the
# choices dynamically. Return a fresh ModelChoiceIterator that has not been
# consumed. Note that we're instantiating a new ModelChoiceIterator *each*
# time _get_choices() is called (and, thus, each time self.choices is
# accessed) so that we can ensure the QuerySet has not been consumed. This
# construct might look complicated but it allows for lazy evaluation of
# the queryset.
return self.iterator(self)
choices = property(_get_choices, ChoiceField._set_choices)
关于python - 减少 django modelform 中的重复查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59116235/