Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FAQ/Documentation on Migration Pitfalls Should Be Added #849

Open
FinalPrayer opened this issue Apr 13, 2023 · 3 comments
Open

FAQ/Documentation on Migration Pitfalls Should Be Added #849

FinalPrayer opened this issue Apr 13, 2023 · 3 comments
Labels

Comments

@FinalPrayer
Copy link

FinalPrayer commented Apr 13, 2023

Hi there,

If the problem has been answered please also let me know, since I am not sure the correct keyword for this question.

django-taggit version:3.1.0
Django version: 4.1.5

Assuming I have a Django app named news, the models.py file of this app contains code below:

from django.db import models
from django.utils.text import slugify
from django.utils.translation import gettext_lazy as _
from taggit.managers import TaggableManager
from taggit.models import TagBase, GenericTaggedItemBase

class NewsTag(TagBase):
    slug = models.SlugField(verbose_name=_("slug"), unique=True, max_length=100, allow_unicode=True)

    def slugify(self, tag, i=None):
        slug = slugify(tag, allow_unicode=True)
        if i is not None:
            slug += "_%d" % i
        return slug

    class Meta:
        verbose_name = _("news_tag")
        verbose_name_plural = _("news_tags")
        app_label = "taggit"


class TaggedNews(GenericTaggedItemBase):
    tag = models.ForeignKey(
        NewsTag,
        on_delete=models.CASCADE,
        related_name="%(app_label)s_%(class)s_items",
    )

class News(models.Model):
    title = models.CharField(max_length=100)
    intro = models.CharField(max_length=150)
    details = models.TextField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)
    tags = TaggableManager(through=TaggedNews, blank=True)

When I execute the command python manage.py makemigrations, it generates 2 migrations:

Migrations for 'taggit':
  venv/lib/python3.11/site-packages/taggit/migrations/0006_newstag.py
    - Create model NewsTag
Migrations for 'news':
  news/migrations/0001_initial.py
    - Create model TaggedNews
    - Create model News

The model generated within taggit is located within the Python environment, which is not included within the Git directory of my project. The migration file generated for the news app relies on the tag:

    dependencies = [
        ('taggit', '0006_newstag'),
        ('contenttypes', '0002_remove_content_type_name'),
    ]

The problem comes when I deploy the code using git and Docker, when running python manage.py migrate within a freshly created container, it shows the error:
django.db.migrations.exceptions.NodeNotFoundError: Migration news.0001_initial dependencies reference nonexistent parent node ('taggit', '0006_newstag')

Is there any solutions that I can solve the problem? My current solution is to create the base migration at the beginning, leave the tag not created at the first place, and let the container run python manage.py makemigrations and python manage.py migrate when starts up. Yet this causes wider problem about migration inconsistency.

@rtpg
Copy link
Contributor

rtpg commented Apr 15, 2023

When you're generating mgirations, a migration ends up being put inside the taggit package.

This is because in your meta you have:

    class Meta:
        verbose_name = _("news_tag")
        verbose_name_plural = _("news_tags")
        app_label = "taggit"

the app_label = "taggit" is the culprit. I do not believe you want to set this app_label! That is mainly a thing that exists for code refactoring, but here you really just should not be specifying the app label. That way the migration will properly end up in news.

I cannot insist enough that a migration getting generated into the site packages is a sign of a serious issue, either in django-taggit or your code. An issue so large that you should probably not deploy anything that is doing that.

In your case, I believe removing app_label will "fix" the problem. But to be honest if you have run this in prod already and have generated the tables, you will need to probably do some stuff to work around stuff that has been created in your DB, doing some "fixup" and some manual work. I cannot really help you deeply on this as it depends on your environment

@FinalPrayer
Copy link
Author

Thanks for the reply.

The solution about removing app_label = "taggit" makes the migration for the tag into the news app, which is what I wish for.

Since the problem has been discovered during local mock testing, I can still squish those migrations prior to any production/testing environment deployment.

Thanks for the help <3

@rtpg rtpg added the docs label Apr 24, 2023
@rtpg rtpg changed the title automatically generated in-package migrations causes NodeNotFoundError on deployment FAQ/Documentation on Migration Pitfalls Should Be Added Apr 24, 2023
@rtpg
Copy link
Contributor

rtpg commented Apr 24, 2023

Alright, we should add something to the FAQ about this (and for other things). subclassing models can easily mess things up if you're not careful

@rtpg rtpg reopened this Apr 24, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants