Django:在我的模型上调用 .only() 会导致无限循环?

问题描述 投票:0回答:1

我正在使用

.only
从我的模型中获取所需的字段,似乎我的
__init__
方法在在此模型上调用
only
时导致无限循环,这是我的模型:

class PodcastEpisode(models.Model):
    audio_metadata = models.JSONField(null=True)
    featured_artists = models.ManyToManyField(to=User, related_name='featured_artists')
    podcast_series = models.ForeignKey(to=PodcastSeries, on_delete=models.CASCADE, null=False)
    published = models.BooleanField(default=False)
    published_at = models.DateTimeField(blank=True, null=True)

    _original_audios = None # To store current data
    _published = None

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # self._original_audios = self.audio_metadata
        # self._published = self.published

当我评论这些行

self._original_audios = self.audio_metadata
self._published = self.published
时,它不会导致无限循环。即使我已将
audio_metadata
包含在我的
.only()
字段中,我也不确定这是如何发生的。这是我的询问

PodcastEpisode.objects\
            .filter(id__in=id_list).prefetch_related(*prefetches).only(*['id' 'audio_metadata'])

请建议我如何使用

.only()
以及我应该将这些
_original_audios
_published
变量放在哪里。

作为参考,这是整个堆栈跟踪:

 File "/Users/dev/Desktop/dev/Podsack_backend/mediacontent/models.py", line 152, in __init__
    self._original_audios = self.audio_metadata
                            ^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query_utils.py", line 182, in __get__
    instance.refresh_from_db(fields=[field_name])
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/base.py", line 707, in refresh_from_db
    ).filter(pk=self.pk)
      ^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/manager.py", line 85, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query.py", line 1420, in filter
    return self._filter_or_exclude(False, args, kwargs)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query.py", line 1438, in _filter_or_exclude
    clone._filter_or_exclude_inplace(negate, args, kwargs)
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query.py", line 1445, in _filter_or_exclude_inplace
    self._query.add_q(Q(*args, **kwargs))
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1532, in add_q
    clause, _ = self._add_q(q_object, self.used_aliases)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1562, in _add_q
    child_clause, needed_inner = self.build_filter(
                                 ^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1478, in build_filter
    condition = self.build_lookup(lookups, col, value)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/sql/query.py", line 1289, in build_lookup
    lookup_class = lhs.get_lookup(lookup_name)
                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/expressions.py", line 377, in get_lookup
    return self.output_field.get_lookup(lookup)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query_utils.py", line 216, in get_lookup
    found = self._get_lookup(lookup_name)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/dev/Library/Caches/pypoetry/virtualenvs/narratave-9vDc9ea1-py3.11/lib/python3.11/site-packages/django/db/models/query_utils.py", line 203, in _get_lookup
    return cls.get_lookups().get(lookup_name, None)
           ^^^^^^^^^^^^^^^^^
RecursionError: maximum recursion depth exceeded in comparison
python django django-models django-queryset
1个回答
0
投票

Django ORM(对象关系映射)利用延迟加载。当您尝试访问

self.audio_metadata
中的
self.published
__init__
时,Django 实际上尚未完成对象的初始化,并尝试从数据库中检索这些值。此检索再次触发
__init__
函数,导致无限循环。

您可以像这样重写 Django 的 save 方法,而不是在初始化时尝试保存这些值:

    def save(self, *args, **kwargs):
        # if self.pk is not None, then the instance is currently in the database
        if self.pk is not None:
            # retrieve the instance from the database
            old_values = PodcastEpisode.objects.get(pk=self.pk)
            self._original_audios = old_values.audio_metadata
            self._published = old_values.published
        super().save(*args, **kwargs)
© www.soinside.com 2019 - 2024. All rights reserved.