Сокращение дБ запросов в Django - PullRequest
6 голосов
/ 29 июня 2011

У меня есть представление, которое ищет в базе данных титры фильмов, а также конвертирует и возвращает результаты, как это так -

# From the following results:
Avatar - James Cameron - director
Avatar - James Cameron - writer
Avatar - James Cameron - editor
Avatar - Julie Jones - writer
Crash - John Smith - director

# ...display in the template as:
Avatar - James Cameron (director, writer, editor)
Avatar - Julie Jones (writer)
Crash - John Smith (director)

Однако, когда я делаю это преобразование и print connection.queries, я попадаю в базу данных около 100 раз. Вот что у меня сейчас есть -

# in models
class VideoCredit(models.Model):
    video = models.ForeignKey(VideoInfo)

    # if the credit is a current user, FK to his profile,
    profile = models.ForeignKey('UserProfile', blank=True, null=True)
    # else, just add his name
    name = models.CharField(max_length=100, blank=True)
    # normalize name for easier searching / pulling of name
    normalized_name = models.CharField(max_length=100)

    position = models.ForeignKey(Position)
    timestamp = models.DateTimeField(auto_now_add=True)
    actor_role = models.CharField(max_length=50, blank=True)    

class VideoInfo(models.Model):
    title = models.CharField(max_length=256, blank=True)
    uploaded_by = models.ForeignKey('UserProfile')
    ...

Положение класса (модели. Модель): position = models.CharField (max_length = 100) ordering = models.IntegerField (max_length = 3)

class UserProfile(models.Model):
    user = models.ForeignKey(User, unique=True)
        ...

На мой взгляд, я строю список из трех кортежей в форме (name, video, [list_of_positions]) для отображения кредитов -

    credit_set = VideoCredit.objects.filter(***depends on a previous function***)
    list_of_credit_tuples = []
    checklist = [] # I am creating a 'checklist' to see whether to append the positions
                   # list of create a new tuple entry
    for credit in credit_set:
        if credit.profile:  # check to see if the credit has an associated profile
            name = credit.profile    
        else:
            name = credit.normalized_name
        if (credit.normalized_name, credit.video) in checklist:
            list_of_keys = [(name, video) for name, video, positions in list_of_credit_tuples]
            index = list_of_keys.index((name, credit.video))
            list_of_credit_tuples[index][2].append(credit.position)
        else:
            list_of_credit_tuples.append((name, credit.video, [credit.position]))
            checklist.append((credit.normalized_name, credit.video))
    ...

И, наконец, в моем шаблоне для отображения кредитов (примечание: если у кредита есть профиль, укажите ссылку на профиль пользователя) -

{% for name, video, positions in list_of_credit_tuples %}
<p>{% if name.full_name %}
    <a href="{% url profile_main user_id=name.id %}">{{name.full_name}}</a>
    {% else %}
    {{name}}
    {% endif %}
    <a href="{% url videoplayer video_id=video.id %}">{{video}}</a>
    ({% for position in positions %}{% ifchanged %}{{position}}{% endifchanged %}{% if not forloop.last %}, {% endif %}{% endfor %})
{% endfor %}

Почему и где это представление создает так много запросов к БД? Как и каким образом я могу сделать эту функцию более эффективной / лучшей? Спасибо.

Ответы [ 2 ]

15 голосов
/ 29 июня 2011

Вы захотите взглянуть на select_related () (https://docs.djangoproject.com/en/1.3/ref/models/querysets/#select-related), чтобы решить проблему утечки вашего запроса. Если вы заранее знаете, что будете искать данные по моделям, связанным с чужим ключом, выхочу добавить select_related. Еще лучше, если вы знаете, что это будет всего пара иностранных ключей, вы можете добавить только те, которые вам нужны.

Каждый раз, когда вы видите, что django запускает огромное количество запросов больше, чем вы ожидали, select_relatedпочти всегда правильный ответ

4 голосов
/ 07 июля 2011

Попробуйте добавить этот фрагмент Django, который возвращает количество запросов, а также сами запросы в ваш шаблон:

http://djangosnippets.org/snippets/159/

Это должно легко сказать вам, откуда произошла ваша утечка.

...