在使用OneToOne字段扩展site对象后,在site-packages.django.contrib.sites而不



我借用了这个答案中的想法,扩展了在Django sites框架的初始迁移过程中创建的默认Site对象。新模型SiteSettings与Site模型建立了OneToOne关系,以添加其他字段。然后我使用信号创建SiteSettings对象。

当我为SiteSettings模型进行第一次迁移时,一切似乎都很好。创建了一个SiteSettings对象,该对象与默认Site对象具有OneToOne关系。

然而,我没有注意到的是,在我的本地应用程序下没有为此创建迁移文件。我能够很好地进行迁移,所以我不确定迁移到了哪里。它没有列在我的迁移表中。

不管怎样,既然它起作用了,我就没注意到。一两天后,我开始向SiteSettings添加额外的字段,并注意到当我进行这些迁移时,它们是为了创建SiteSettings模型,而不是更新其字段。就在那时,我注意到第一次迁移并没有在正确的位置创建。创建了第二个迁移,但它是在site-packages/django/contrib/sites/migrations/中创建的。它看起来像这样:

class Migration(migrations.Migration):
dependencies = [
("sites", "0002_alter_domain_unique"), # the initial auto migration
]
operations = [
migrations.CreateModel(
name="SiteSettings",
fields=[
(
"site",
models.OneToOneField(
on_delete=django.db.models.deletion.CASCADE,
primary_key=True,
related_name="settings",
serialize=False,
to="sites.site",
verbose_name="site",
),
),
# A bunch of other CharFields that aren't important
],
options={
"verbose_name_plural": "settings",
},
),
]

我的模特.py看起来是这样的。我认为问题可能是app_labeldjango.contrib.sites的名称匹配,但我不确定。我命名这个标签的原因是,它显示在管理员的网站下。

class SiteSettings(models.Model):
"""
Extension of the Sites model that holds more info about the site.
"""
site = models.OneToOneField(
Site,
on_delete=models.CASCADE,
primary_key=True,
related_name="settings",
verbose_name="site",
)
# A bunch of other fields that aren't important
def __str__(self):
return self.site.name
class Meta:
app_label = "sites"
verbose_name_plural = "settings"

以下是apps.py的样子:

from django.apps import AppConfig
from django.conf import settings
from django.db.models.signals import post_migrate, post_save

def create_default_site_settings(sender, **kwargs):
"""Creates default site settings after migration"""
# App config must be ready for import to work
from django.contrib.sites.models import Site
from .models import SiteSettings
site = Site.objects.get(id=getattr(settings, "SITE_ID", 1))
if not SiteSettings.objects.exists():
SiteSettings.objects.create(site=site)

class CoreConfig(AppConfig):
name = "apps.core"
label = "core"
default_auto_field = "django.db.models.BigAutoField"
def ready(self):
# App config must be ready for import to work
from django.contrib.sites.models import Site
post_migrate.connect(create_default_site_settings, sender=self)
from .signals import create_site_settings
post_save.connect(create_site_settings, sender=Site)

最后,signals.py.

from django.contrib.sites.models import Site
from django.db.models.signals import post_save
from django.dispatch import receiver
from .models import SiteSettings

@receiver(post_save, sender=Site)
def create_site_settings(sender, instance, **kwargs):
"""
Creates/updates a SiteSettings object after a Site object.
"""
site_settings, created = SiteSettings.objects.update_or_create(site=instance)
if not created:
site_settings.save()

这只是app_label相同的问题吗?我想弄清楚为什么会这样。

我发现了这个问题。由于我在Docker容器中运行我的应用程序,并且我的新模型中的app_label设置为与django.contrib.sites相同的app_label,所以迁移是在Docker集装箱中的path/to/site-packages/django/contrib/sites/migrations/中创建的。不是在复制到容器的应用程序中,而是在容器中实际安装的Django。

因此,最初的迁移是在容器中创建的,而不是我一开始没有注意到的本地迁移。一旦我的容器在某个时候被重建,迁移文件就被删除了,因为它刚刚将所有Python包重新安装到新映像上。当我进行第二次迁移时,尽管数据库中存在表,但模型似乎从未创建过。

为了修复它,我将新模型的app_label恢复为默认值。然后我不得不重建容器,删除旧的表site_sitesettings,并删除";丢失";django_migrations表中的迁移记录。在下一轮迁移过程中,为core_sitesettings创建了一个新表,我可以按预期访问我的OneToOne关系。

相关内容

最新更新