Django 应用程序具有循环依赖关系,导致外键模型无法迁移

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

我有两个 Django 应用程序,它们之间有外键

一个 api 应用程序和另一个名为 blog

的应用程序

这是我的博客应用程序的 models.py

class Post(models.Model):

    uuid = models.UUIDField(default=uuid.uuid4, primary_key=False, unique=True)
    title = models.CharField(max_length=600)
    authors = models.ManyToManyField('Author', related_name='authors')
    tags = models.ManyToManyField('Tag', related_name='tags')
    date_published = models.DateField(auto_now_add=True)

    # store table of contents as JSON
    table_of_contents = models.TextField(default=dict)

    # s3 link to thumbnail
    thumbnail = models.URLField(max_length=300)

    # each post belongs to a blog
    blog = models.ForeignKey('api.Blog', on_delete=models.CASCADE, default=0)

    slug = models.SlugField(max_length=100, default='')

    # store markdown as text
    content = models.TextField(default='')

    # link to post
    url = models.URLField(default='')


    # for json serialization
    def as_dict(self):
        return {
            "title": self.title,
            "slug": self.slug,
            "authors": [ author.as_dict() for author in self.authors.all() ],
            "tags": [ tag.as_dict() for tag in self.tags.all() ],
            "date_published": "01/01/2001",  
            "table_of_contents": self.table_of_contents,
            "thumbnail": self.thumbnail,
            "id": str(self.uuid),
        }
    
    def __str___(self):
        return self.title


class Author(models.Model):
    name = models.CharField(max_length=100)
    blog = models.ForeignKey('api.Blog', on_delete=models.CASCADE, default=0)


    def as_dict(self):
        return {
            "name": self.name,
            "profile": self.name
        }

    def __str__(self):
        return self.name  

class Tag(models.Model):
    name = models.CharField(max_length=50)
    blog = models.ForeignKey('api.Blog', on_delete=models.CASCADE, default=0)

    def as_dict(self):
        return {
            "name": self.name
        }

    def __str__(self):
        return self.name    

还有我的“api”应用程序的 models.py

class Blog(models.Model):

    # Foreign key to the associated tenant in case we need to changve schema_name
    tenant = models.ForeignKey('Client', on_delete=models.CASCADE, related_name="tenant_blog", default=0)

    class Templates(models.TextChoices):
        SAAS = 'SAAS'
        CHANGELOG = 'CHANGELOG'
        HELP = 'HELP'
        DEFAULT = 'DEFAULT'
        PERSONAL = 'PERSONAL'

    class CTAS(models.TextChoices):
        DEFAULT = 'DEFAULT'
        NEWSLETTER = 'NEWSLETTER'
        
    uuid = models.UUIDField(default=uuid.uuid4, unique=True, primary_key=False)

    schema_name = models.CharField(default='', max_length=20)
    useCustomDomain = models.BooleanField(default=False)
    customDomain = models.CharField(max_length=100, default="")

    landing_header = models.CharField(max_length=100, default="")
    landing_subheader = models.CharField(max_length=100, default="")

    # choose template from the list
    template = models.CharField(max_length=18, choices=Templates.choices, default=Templates.DEFAULT)

    url = models.URLField(max_length=300, default='')
    name = models.CharField(max_length=100, default='')
    owner = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, related_name='blogs')

    posts = models.ManyToManyField('blog.Post', related_name='posts')
    featuredPosts = models.ManyToManyField('blog.Post', related_name='featured')
    authors = models.ManyToManyField('blog.Author', related_name="blog_authors")
    tags = models.ManyToManyField("blog.Tag", related_name="blog_tags")

    # call to action (newsletter or sign up)
    ctaType = models.CharField(max_length=50, choices=CTAS.choices, default=CTAS.DEFAULT)

    # display options
    defaultModeLight = models.BooleanField(default=True)
    showThemeToggle = models.BooleanField(default=True)
    showSpotlight = models.BooleanField(default=True)
    showFooter = models.BooleanField(default=True)
    showPoweredByBadge = models.BooleanField(default=True)
    showCTA = models.BooleanField(default=True)

    page_views_used = models.IntegerField(default=0)


    # Is the blog up/accesible to the public?
    isActive = models.BooleanField(default=True)

正如您所看到的,两个应用程序都有相互依赖的外键,这会导致循环依赖。

当我跑步

makemigrations
migrate
时,我得到
relation "blog_author" does not exist

我已经尝试过仅删除外键字段,进行迁移,将它们添加回来并重新进行迁移。但我得到了同样的

relation "blog_author" does not exist
错误...

如何让 Django 迁移而不会遇到此错误?

python django postgresql django-models
1个回答
0
投票

当您在对象上定义

ForeignKey
关系时,Django 将自动创建一种从其他模型访问这些关系的方法。由于您要在
ForeignKey
Post
Author
上定义
Tag
,因此无需从
ManyToMany
定义
Blog
关系。

如果您有

Blog
对象,您可以通过执行以下操作来访问与博客关联的帖子、作者和标签:
blog.[modelname]_set
。例如,要访问与博客文章关联的所有帖子,您可以执行
blog.author_set.filter...

如果要指定这些属性的名称,可以使用

related_name
字段作为
ForeignKey
字段。

class Author(models.Model):
    blog = models.ForeignKey('api.Blog', on_delete=models.CASCADE, default=0, related_name="authors")

这样,如果您有博客对象,您现在就可以执行

blog.authors.filter...
操作。

此外,与其为

ForeignKey
设置默认值 0,不如只允许该字段可为空:

blog = models.ForeignKey('api.Blog', on_delete=models.CASCADE, null=True, related_name="authors")

要么这样,要么删除

null
default
,这样当您尝试添加没有博客的作者/帖子/标签时会出现错误(如果每个作者/帖子/标签必须始终有一个关联到的博客)它)。

© www.soinside.com 2019 - 2024. All rights reserved.