Django дублирует поиск в базе данных с помощью inlineformset - PullRequest
0 голосов
/ 20 января 2019

Мне нужна помощь в решении проблемы, связанной с дублированием запросов к базе данных для каждой формы в inlineformset.У меня есть страница, на которой пользователи могут добавлять и редактировать книги, принадлежащие автору.

models.py

from django.db import models
class Author(models.Model):
    id = models.AutoField(primary_key=True)
    name = models.CharField(max_length=100)

class Book(models.Model):
    id = models.AutoField(primary_key=True)
    author = models.ForeignKey(Author, on_delete=models.CASCADE)
    title = models.CharField(max_length=100)
    category_idcategory = models.ForeignKey(Category, models.DO_NOTHING)

class Category(models.Model):
    name = models.CharField(max_length=100)

forms.py

from django import forms
class BookForm(forms.ModelForm):
    class Meta:
        model = Book
        fields = '__all__'

views.py

instance = get_object_or_404(Author, id=id)
form = inlineformset_factory(Author, Book, form=BookForm, can_delete=True, extra=5)
formset = form(request.POST or None, instance=instance)

if request.method == "POST":
    if formset.is_valid():
        instanceForm = formset.save(commit=False)
        for obj in instanceForm:
            obj.save()
        for obj in formset.deleted_objects:
            obj.delete()
        return HttpResponseRedirect(URL)

Когда я запускаю шаблон, он выполняет запрос базы данных к модели категории для каждой формы в наборе форм.Как я могу предотвратить эти дубликаты?Я не знаю, куда поместить select_related или prefetch_related.Если количество экземпляров модели Book увеличивается до большого количества, время загрузки страницы становится очень медленным.

template.html

<table class="table table-sm">
{{ formset.management_form }}
    <thead>
        <td>Title</td>
        <td>Category</td>
        <td>delete</td>
    </thead>
    <tbody>
    {% for obj in formset %}
    {{ obj.id }}
        <tr>
            <td>{{ obj.title }}</td>
            <td>{{ obj.category_idcategory }}</td>
            <td>{{ obj.DELETE }}</td>
       </tr>
    {% endfor %}
    </tbody>
</table>

1 Ответ

0 голосов
/ 21 января 2019

Вы можете изменить набор запросов набора форм следующим образом:

class InlineBookFormSet(BaseInlineFormSet):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Here is where to put the select_related.
        self.queryset = Book.objects.select_related('category_idcategory').all()

тогда в вашем фабричном вызове метода:

# Use your custom InlineBookFormSet
form = inlineformset_factory(Author, Book, form=BookForm, can_delete=True, extra=5, formset=InlineBookFormSet)
...