我正在使用
.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
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)