Рубрики
Без рубрики

Почему упоминание Инонарки в Model’s __str__ Model __str__ – плохая идея

Запросы для резки базы данных, не ссылаясь на иностранные ключи. Или исправить плохое поведение. Фото… Теги с Python, Django.

фото Израиль Паласио на Бессмысленно

Таким образом, у вас есть модель с внешним ключом:

from django.db import models
from .models import Author

class Book(models.Model):
    name = models.CharField(...)
    author = models.ForeignKey(to=Author,...)

Теперь вы хотите увидеть Автор На вашей панели администратора. Легко, верно? Просто добавь:

def __str__(self):
    return f'{self.id} {self.author.name}'

Что это сделает, это ударить нашу базу данных для имени автора для каждой строки, присутствующей на странице. Представьте себе, что есть 100 рядов. Это 100 больше хитов. Эта проблема известна как N + 1 запрос Отказ

Решение довольно простое. Если это Иностранник , вам нужно использовать select_related на вашем запрос . Если это Manytomany поле или обратное FK тогда вам нужен Prefetch_related метод. И, кстати, это разница между этими двумя методами. Это обычный вопрос интервью.

Но в нашем случае это не простой запрос. Если вы действительно хотите исправить, что вам нужно будет глубже в том, как Django Admin работает и предоставляет пользовательские Queryset к мнению.

Когда я столкнулся с этой проблемой, решение, которое было принято, просто удалил ссылку на Викторина от __str__ Метод ¯ \ _ (ツ) _/¯ ¯

Немного Todo для себя: найдите способ решить это через select_related.

Некоторое время я не столкнулся с этой проблемой, но не так давно я сделал. Итак, как я уже сказал, решение этого довольно просто. Все, что нам нужно сделать, это переопределить get_queryset Метод на модели администратора. Например:

@admin.register(models.Book)
class BookAdmin(admin.ModelAdmin):
    def get_queryset(self, request):
        qs = self.model._default_manager.select_related(
            'author',
        )
        # This stuff is marked as TODO in Django 3.1
        # so it might change in the future
        ordering = self.get_ordering(request)
        if ordering:
            qs = qs.order_by(*ordering)

        return qs

Теперь будет только один запрос за запись, содержащую Присоединяйтесь к пункт, ударяя нашу базу данных.

Оптимизация ftw 😏.

Оригинал: “https://dev.to/c_v_ya/why-foreignkey-reference-in-django-model-s-str-method-is-a-bad-idea-41a7”