Makemigration with django4.0.6 and python3.10.5 doesn't work

I’m currently coding a blog as a side project, whenever I make a considerable modification in my models, I cannot migrate.

This is my model

from ckeditor.fields import RichTextField
from django.contrib.auth.models import User
from django.db import models
from django.template.defaultfilters import slugify
from django.urls import reverse


class Tag(models.Model):
    name = models.CharField(max_length=255, default="Uncategorized")

    class Meta:
        ordering = ['name']

    def __str__(self):
        return self.name

    def get_absolute_url(self):
        return reverse('blog:home')


class Post(models.Model):
    ACTIVE = 'active'
    DRAFT = 'draft'

    CHOICE_STATUS = (
        (ACTIVE, 'Active'),
        (DRAFT, 'Draft')
    )

    title = models.CharField(max_length=255)
    title_color = models.CharField(max_length=50, default="white")
    header_image = models.ImageField(upload_to='images/headers', null=True, blank=True)
    author = models.ForeignKey(User, on_delete=models.CASCADE)
    table_content = RichTextField(default="CONTENTS", blank=True, null=True)
    body = RichTextField(blank=True, null=True)
    snippet = models.CharField(max_length=255, default="")
    date_published = models.DateTimeField(auto_now_add=True)
    status = models.CharField(max_length=10, choices=CHOICE_STATUS, default=DRAFT)
    slug = models.SlugField()
    tag = models.ManyToManyField(Tag)

    def __str__(self):
        return self.title + ' | ' + self.author.get_full_name()

    def get_absolute_url(self):
        return reverse('blog:article_details', args=(str(self.id), self.slug))

    @property
    def date(self):
        return self.date_published.date()

    def save(self, *args, **kwargs):
        if not self.slug:
            self.slug = slugify(self.title)
        return super().save(*args, **kwargs)


class PostPicture(models.Model):
    name = models.CharField(max_length=255, default="")
    files = models.FileField(upload_to="images/post")

    def __str__(self):
        return self.name

Now, in my model, I had the class named Category and decided I don’t need it anymore and just renamed it Tag.

When I make migrations, I have this error

LinuxTux@LinuxTux-MBP blog % python3 manage.py makemigrations
Traceback (most recent call last):
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
sqlite3.OperationalError: no such table: blog_tag

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/Users/LinuxTux/developer/PycharmProjects/blog_project/manage.py", line 22, in <module>
    main()
  File "/Users/LinuxTux/developer/PycharmProjects/blog_project/manage.py", line 18, in main
    execute_from_command_line(sys.argv)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/management/__init__.py", line 446, in execute_from_command_line
    utility.execute()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/management/__init__.py", line 440, in execute
    self.fetch_command(subcommand).run_from_argv(self.argv)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/management/base.py", line 414, in run_from_argv
    self.execute(*args, **cmd_options)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/management/base.py", line 455, in execute
    self.check()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/management/base.py", line 487, in check
    all_issues = checks.run_checks(
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/checks/registry.py", line 88, in run_checks
    new_errors = check(app_configs=app_configs, databases=databases)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/checks/urls.py", line 14, in check_url_config
    return check_resolver(resolver)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/core/checks/urls.py", line 24, in check_resolver
    return check_method()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/urls/resolvers.py", line 480, in check
    for pattern in self.url_patterns:
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/utils/functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/urls/resolvers.py", line 696, in url_patterns
    patterns = getattr(self.urlconf_module, "urlpatterns", self.urlconf_module)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/utils/functional.py", line 49, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/urls/resolvers.py", line 689, in urlconf_module
    return import_module(self.urlconf_name)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/importlib/__init__.py", line 126, in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
  File "<frozen importlib._bootstrap>", line 1050, in _gcd_import
  File "<frozen importlib._bootstrap>", line 1027, in _find_and_load
  File "<frozen importlib._bootstrap>", line 1006, in _find_and_load_unlocked
  File "<frozen importlib._bootstrap>", line 688, in _load_unlocked
  File "<frozen importlib._bootstrap_external>", line 883, in exec_module
  File "<frozen importlib._bootstrap>", line 241, in _call_with_frames_removed
  File "/Users/LinuxTux/developer/PycharmProjects/blog_project/blog_project/urls.py", line 21, in <module>
    import blog.views
  File "/Users/LinuxTux/developer/PycharmProjects/blog_project/blog/views.py", line 8, in <module>
    from .forms import UpdateForm, PostForm
  File "/Users/LinuxTux/developer/PycharmProjects/blog_project/blog/forms.py", line 7, in <module>
    for item in choices:
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/query.py", line 320, in __iter__
    self._fetch_all()
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/query.py", line 1507, in _fetch_all
    self._result_cache = list(self._iterable_class(self))
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/query.py", line 168, in __iter__
    return compiler.results_iter(
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1312, in results_iter
    results = self.execute_sql(
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1361, in execute_sql
    cursor.execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in execute
    return super().execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
  File "/Library/Frameworks/Python.framework/Versions/3.10/lib/python3.10/site-packages/django/db/backends/sqlite3/base.py", line 477, in execute
    return Database.Cursor.execute(self, query, params)
django.db.utils.OperationalError: no such table: blog_tag

I also tried

python3 manage.py makemigrations blog

or

python3 manage.py makemigrations --dry-run --verbosity 3

or

python3.10 manage.py makemigrations --dry-run --verbosity 3

I also have the same error output when I run:

python3 manage.py test

I tried removing the database (db.sqlite3) and all the migrations folder + pycache folder, re-run the same command above, same error.

Am I the only one having this error ?

This type of error is frequently encountered when you have some module-level code referencing the table.

Do you have any other code in any file in your project that is still referencing Category?

Yes, I used class-based view. When I commented out every bit of code that could reference Category and run makemigrations again, it works, thanks to your advice. Does that mean there’s something wrong with it and I need to change my class-based view to a function-based view?

You’d have to show me your view for me to determine what’s wrong. I would likely say that you’re not doing something right in your view.

This is my old view

from django.contrib.auth.decorators import login_required
from django.db.models import Q
from django.shortcuts import render
from django.urls import reverse_lazy
from django.utils.decorators import method_decorator
from django.views.generic import ListView, DetailView, CreateView, UpdateView, DeleteView

from .forms import UpdateForm, PostForm
from .models import Post, Category


class HomeView(ListView):
    model = Post
    template_name = 'blog/index.html'
    ordering = ['-date_published']

    def context_data_filtering(self, post):
        context = super(HomeView, self).get_context_data()
        cat_list = Category.objects.all()
        context["cat_list"] = cat_list
        if len(post) >= 5:
            last_post = post[0]
            first_row = post[1:4]
            the_rest = post[4:]
        elif 5 > len(post) > 1:
            last_post = post[0]
            first_row = post[1:4]
            the_rest = None
        elif len(post) == 1:
            last_post = post[0]
            first_row = None
            the_rest = None
        else:
            last_post = None
            first_row = None
            the_rest = None
        context["last_post"] = last_post
        context["row"] = first_row
        context["rest"] = the_rest
        return context

    def get_context_data(self, *, object_list=None, **kwargs):
        if self.request.user.is_authenticated:
            post_user_logged = Post.objects.all().order_by('-date_published')
            return self.context_data_filtering(post_user_logged)
        else:
            post = Post.objects.filter(status='active').order_by('-date_published')
            return self.context_data_filtering(post)


class ArticleDetailView(DetailView):
    model = Post
    pk_url_kwarg = "pk"
    slug_url_kwarg = "slug"
    template_name = 'blog/articles_details.html'


@method_decorator(login_required, name='dispatch')
class AddPostView(CreateView):
    model = Post
    form_class = PostForm
    template_name = 'blog/add_post.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)


@method_decorator(login_required, name='dispatch')
class UpdatePostView(UpdateView):
    model = Post
    form_class = UpdateForm
    template_name = 'blog/update_post.html'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)


@method_decorator(login_required, name='dispatch')
class DeletePostView(DeleteView):
    model = Post
    template_name = 'blog/delete_post.html'
    success_url = reverse_lazy('blog:home')

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)


@method_decorator(login_required, name='dispatch')
class AddCategoryView(CreateView):
    model = Category
    template_name = 'blog/add_category.html'
    fields = '__all__'

    @method_decorator(login_required)
    def dispatch(self, *args, **kwargs):
        return super().dispatch(*args, **kwargs)


def category_view(request, cats):
    category_post = Post.objects.filter(category=cats.replace('-', ' '))
    return render(request, 'blog/categories.html', {'cats': cats.title().replace('-', ' '), 'category': category_post})


def search(request):
    query = request.GET.get('query', '')
    posts = Post.objects.filter(status=Post.ACTIVE).filter(
        Q(title__icontains=query) | Q(snippet__icontains=query) | Q(body__icontains=query))
    return render(request, 'blog/search.html', {'query': query, 'posts': posts})

It was probably the import statement at the top, if the model Category no longer existed.

I’ve tried making migrations on the server with the new view file updated(with the right import) with the tag model, same problem, I had to comment every other file using the app logic, push to server, makemigrations on server, uncomment, push to server again to make it work.

I’m not entirely sure I know exactly what the implications are of this phrase, but since you have it working, it sounds like the issue is moot.

I meant admin.py urls.py test.py forms.py view.py…