Предотвращение шаблонов Django base.py для разрешения всех возможных отношений внешнего ключа в строке - PullRequest
0 голосов
/ 24 июня 2019

Я пытаюсь создать Inline для существующего класса администратора Django, но обнаружил, что время отображения страницы слишком медленное. Я обнаружил, что проблема заключалась в функции django templates / base.py «resol» или в последующей функции рендеринга (Django 2.1). Казалось бы, все мои объекты «Track» загружаются для всех форм в строке во всех случаях.

Как я могу увеличить производительность этой функции, изменив мой код? Должен ли я реструктурировать запись -> Tracklist -> TracklistTrack -> Отслеживание отношений? Могу ли я как-то кэшировать объекты моей модели? Использование модели .thth inline неразумно?

Чтобы начать искать проблему, я начал использовать профилировщик. При запуске таймера для кода рассматриваемый профилировщик вызывает незначительное замедление.

Я вижу, что подавляющее большинство моих вызовов функций 22s выглядит следующим образом:

ncalls totaltime percall cumtime percall имя файла: lineno (функция)

  123    0.001    0.000   18.194    0.148 django/forms/widgets.py:232(_render)
  123    0.002    0.000   18.190    0.148 django/forms/renderers.py:29(render)

848104 1.037 0.000 3.867 0.000 django/template/base.py:668(resolve)

Я посмотрел на сообщения о переполнении стека, которые предлагали переопределить и "queryset", и "formfield_for_db". При печати контекста в функциях django я вижу, что все мои треки передаются через base.py, и, вероятно, это проблема.

Новая строка выглядит следующим образом:

    model = Tracklist.tracks.through

    readonly_fields = ('tracklist', 'recording')
    fields = ('track', 'timestamp', 'order')

    @silk_profile(name='Slow Inline')
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(TracklistInline, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name in ['track', 'tracklist', 'recording']:
            # dirty trick so queryset is evaluated and cached in .choices
            formfield.choices = formfield.choices
        return formfield

    def queryset(self, request):
        return super(MyAdmin, self).queryset(request).select_related(
            'track').select_related('tracklist').select_related('recording')```

Where Tracklist looks like this:

```class Tracklist(Timestamped, models.Model):
    """Tracklist is a collection of tracks, owned by a recording

              1                     0...1
    Recording   -------------------       Tracklist

              1                     0...*
    Tracklist   -------------------       Track"""
    tracks = models.ManyToManyField(
        Track, through="TracklistTrack", blank=True)
    recording = models.OneToOneField(
        Recording, related_name='tracklist', null=True, blank=True,
        on_delete=models.CASCADE)```

and tracklist_track, my customised join table, looks like this:

```class TracklistTrack(models.Model):
    """Stores ordering for a Tracklist/Track relationship"""
    class Meta:
        indexes = [
            models.Index(fields=['recording']),
        ]

    tracklist = models.ForeignKey(Tracklist, on_delete=models.CASCADE)
    recording = models.ForeignKey(
        Recording, related_name='tracklistsTrack',
        null=True, blank=True, on_delete=models.CASCADE)
    track = models.ForeignKey(Track, on_delete=models.CASCADE)
    timestamp = models.IntegerField(blank=True, null=True)
    order = models.IntegerField(blank=True, null=True)```

(A Track is a simple model with two charfields only, but a Recording is a bit of a monster)

1 Ответ

0 голосов
/ 26 июня 2019

Для любого переполнения стека я исправил это очень просто с помощью поля автозаполнения django 2.0:

class TracklistInline(admin.TabularInline):
    model = Tracklist.tracks.through

    list_display = ('recording', 'timestamp', 'order')
    autocomplete_fields = ('track',)
    exclude = ('tracklist',)
    extra = 0

@admin.register(Track)
class TrackAdmin(admin.ModelAdmin):
    form = TrackForm
    ordering = ['title']
    search_fields = ('artist', 'title')
    list_display = ('artist', 'title',)
    exclude = ('modified',)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...