Deploying with Postgres - ProgrammingError - LINE 1: SELECT COUNT(*) AS "__count" FROM "landings_pagecontent"

There is something wrong with my PostgreSQL configuration with my Django CMS.

Locally when testing with placeholder content using db.sqlite3 everything runs as expected. But now I am trying to deploy to Heroku. I’ve successfully exported remote Postgres db’s locally in the past. After exporting, I run all the standard makemigrations and migrate commands which all return OK. But now when I open the Admin Dashboard and go to enter content into one of my apps, Django throws the error copied below.

I tried backing up my migrations files and creating new migrations from scratch. That didn’t help.

What is the error below trying to say? What other information could I provide to help troubleshoot this and provide further clarity?

Here is my traceback:

[12/Mar/2023 16:55:21] "GET /admin/ HTTP/1.1" 200 7830
Internal Server Error: /admin/landings/pagecontent/
Traceback (most recent call last):
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
psycopg2.errors.UndefinedTable: relation "landings_pagecontent" does not exist
LINE 1: SELECT COUNT(*) AS "__count" FROM "landings_pagecontent"
                                          ^


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

Traceback (most recent call last):
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/core/handlers/exception.py", line 55, in inner
    response = get_response(request)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/core/handlers/base.py", line 197, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/options.py", line 686, in wrapper
    return self.admin_site.admin_view(view)(*args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 133, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/views/decorators/cache.py", line 62, in _wrapped_view_func
    response = view_func(request, *args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/sites.py", line 242, in inner
    return view(request, *args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 46, in _wrapper
    return bound_method(*args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/utils/decorators.py", line 133, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/options.py", line 1931, in changelist_view
    cl = self.get_changelist_instance(request)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/options.py", line 834, in get_changelist_instance
    return ChangeList(
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/views/main.py", line 123, in __init__
    self.get_results(request)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/contrib/admin/views/main.py", line 279, in get_results
    result_count = paginator.count
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/utils/functional.py", line 57, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/core/paginator.py", line 96, in count
    return c()
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/models/query.py", line 621, in count
    return self.query.get_count(using=self.db)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 559, in get_count
    return obj.get_aggregation(using, ["__count"])["__count"]
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/models/sql/query.py", line 544, in get_aggregation
    result = compiler.execute_sql(SINGLE)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/models/sql/compiler.py", line 1398, in execute_sql
    cursor.execute(sql, params)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 103, in execute
    return super().execute(sql, params)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 67, in execute
    return self._execute_with_wrappers(
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 80, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 84, in _execute
    with self.db.wrap_database_errors:
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/utils.py", line 91, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/home/<user>/dev/projects/python/2018-and-2020/<project-dir>/venv/lib/python3.10/site-packages/django/db/backends/utils.py", line 89, in _execute
    return self.cursor.execute(sql, params)
django.db.utils.ProgrammingError: relation "landings_pagecontent" does not exist
LINE 1: SELECT COUNT(*) AS "__count" FROM "landings_pagecontent"

Also notable is:

The above exception (relation "landings_pagecontent" does not exist LINE 1: SELECT COUNT(*) AS "__count" FROM "landings_pagecontent" ^ ) was the direct cause of the following exception:
/home/<user>/dev/projects/python/2018-and-2020/<project>/venv/lib/python3.10/site-packages/django/core/handlers/exception.py, line 55, in inner
               response = get_response(request)

Here is my models.py for this landings app:

from django.db import models
from ckeditor.fields import RichTextField
# from django.template.defaultfilters import slugify

class PageContent(models.Model):
   # title = models.CharField(max_length=200)
   slug = models.SlugField(null=False, unique=True, blank=True)
   page_type = models.CharField(max_length=20)
   body = RichTextField(config_name='default',max_length=300000,blank=True, null=True)
   pure_html_body = models.TextField(blank=True)


   def __str__(self):
       return f'{self.page_type}'

Here is my app’s CBV:

from django.views.generic import DetailView
from .models import PageContent

class PageView(DetailView):
   model = PageContent
   template_name = "landings/page_detail.html"
   context_object_name = 'contents' 

Here is my app’s urls.py:

from django.urls import path, include
from .views import PageView

app_name= 'landings'

urlpatterns = [
   path('', PageView.as_view(),name='the_gate'),
   path('<str:slug>/', PageView.as_view(),name='home'),
]

This error is common if the migrations haven’t been applied on the database.

The first thing I’d do is independently verify the database to ensure that the database and the tables exist.

You may also want to double-check your DATABASES settings to ensure that you’re trying to use the database you’re supposed to be using.

Hi Ken!

Thanks for your reply.

When I run $ echo $DATABASE_URL, the output shows:

postgres://USER:PASSWORD@HOST:PORT/NAME

The five variables in all caps above are just placeholders. What I see in my terminal are basically hashes for each variable. It’s all auto generated by Heroku at random. Anyways, the output that I see in my terminal confirms my locally exported database is accurate. What this means next is that my settings.py could be misconfigured. My entire settings.py is included at the bottom of this post. However the relevant lines where I think the problem lies could be these:

import dj_database_url
...
DATABASES = { 'default' : dj_database_url.config()}
...
django_heroku.settings(locals())

As you can see with the DATABASES file above, I’m trying to make my Django project “platform agnostic” with environmental variables dynamic so that it works remotely and locally without hard coding credentials or handling all the unique database variables. For example, the official Django docs expect this formatting as convention for postgresql:

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql',
        'NAME': 'mydatabase',
        'USER': 'mydatabaseuser',
        'PASSWORD': 'mypassword',
        'HOST': '127.0.0.1',
        'PORT': '5432',
    }
}

But in my case - - and the beauty of Django and Heroku in general - - is that it’s possible to decouple and automate all of this. I’ve tried to achieve that by configuring my settings.py a certain way. I’ve successfully done this with my many other Django projects deployed to Heroku and I don’t know why it isn’t working this time. I’ve cross-referenced my configurations for this new project and experimented with using my other project configuration files unsuccessfully.

It’s also worth mentioning that this Postgres instance I am using on Heroku is shared with my other Django projects. And when I run the server for this new project, I am able to successfully login to the Django Admin Dashboard using a super user from one of those other projects. I can see the other prior staff Admin users already created. So it’s working. The problem shows only when I go to add content using an app for this new CMS project that I am encountering the error quoted originally. I guess this tells me what @KenWhitesell already pointed out which is that my issue is with making the migrations for my new app. So that’s basically confirmed I guess. But when I go to run: $ python manage.py makemigrations landings the output shows: “No changes detected in app ‘landings’”. Then when I run migrate, it says: “No migrations to apply”.

Here is my migrations file:

# Generated by Django 4.1.5 on 2023-03-05 20:36
import ckeditor.fields
from django.db import migrations, models

class Migration(migrations.Migration):
    initial = True
    dependencies = [
    ]
    operations = [
        migrations.CreateModel(
            name='PageContent',
            fields=[
                ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
                ('slug', models.SlugField(blank=True, unique=True)),
                ('page_type', models.CharField(max_length=20)),
                ('body', ckeditor.fields.RichTextField(blank=True, max_length=300000, null=True)),
                ('pure_html_body', models.TextField(blank=True)),
            ],
        ),
    ]

That all checks out as far as I can tell.

Based on my description of how I’ve handled migrations above, what else could I try to verify that migrations are beling applied on the db?

I shared my DATABASE variable declaration already above. As promised, here is my full settings.py:

"""
Django settings for project.

Generated by 'django-admin startproject' using Django 4.1.3.

For more information on this file, see
https://docs.djangoproject.com/en/4.1/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/4.1/ref/settings/
"""

from pathlib import Path
import os
import django_heroku
from decouple import config
import dj_database_url

# Build paths inside the project like this: BASE_DIR / 'subdir'.
BASE_DIR = Path(__file__).resolve().parent.parent


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/4.1/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = config('SECRET_KEY')
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'ckeditor',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'contributors',
    'articles',
    'landings.apps.LandingsConfig',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = '<project_dir>.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [BASE_DIR / 'templates'],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = '<project_dir>.wsgi.application'


# Database
# https://docs.djangoproject.com/en/4.1/ref/settings/#databases
'''
DATABASES = {
   'default': dj_database_url.config(
       default='sqlite:///'+os.path.join(BASE_DIR, 'db.sqlite3'),
       conn_max_age=600)
   }
# DATABASES['default'] = dj_database_url.config(default='')
db_from_env=dj_database_url.config(conn_max_age=600)
DATABASES['default'].update(db_from_env)\
''' 
DATABASES = { 'default' : dj_database_url.config()}
# Password validation
# https://docs.djangoproject.com/en/4.1/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/4.1/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/4.1/howto/static-files/

STATIC_URL = 'static/'
MEDIA_URL = '/imgs/'
STATICFILES_DIRS = [BASE_DIR / 'static']
MEDIA_ROOT = os.path.join(BASE_DIR, 'static/imgs')
STATIC_ROOT = os.path.join(BASE_DIR, 'staticfiles')

CKEDITOR_BASEPATH = "/staticfiles/ckeditor/ckeditor/"

# Default primary key field type
# https://docs.djangoproject.com/en/4.1/ref/settings/#default-auto-field

DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField'

django_heroku.settings(locals())

Manually connect to your database and examine its state.

I’m not talking about your settings, or your configuration. Use something like psql or PgAdmin to connect directly to the database to find out what’s actually happening there.

Side note:

That’s generally an extremely bad idea. Once your database is out-of-sync with your migrations, all bets are off. (I’m primarily referring to the table that Django uses internally to track which migrations have been applied.)

In this situation, the only other suggestion I can make is create another, new DB, and try running against that.

Hi Ken!

Thanks for your reply so far.

PgAdmin seems incompatible with my window manager (Wayland, Gnome) on my operating system (Manjaro Linux). Other Linux users are reporting similar issues. After spending much time troubleshooting I resolved to using psql to analyze my tables instead.

On Heroku I am paying for two separate postgres silos currently - - one instance for my testing pipeline with placeholder content and the other instance for my real production content.

For now I am working with my testing db instance in my local development environment.

I entered some lorem ipsum data into my ‘articles’ (app)’s Article model objects. When navigating to that app’s url location, Django serves the templates as expected. Success! That tells us that I am doing something right (so far). This app works.

In the output below, you will see the schema for the tables for all three of my Django projects. It’s a fairly long list I guess. But I can draw your attention to the entry named “articles_article”. That is the “articles” app and “Article” model mentioned earlier. That is present which explains why I was able to get it working above.

The problem I am trying to address involves the ‘contents’ app’s ‘PageContent’ model. As you can see in the psql output below, no such data entries exist yet. This confirms the migrations are not being applied/instantiated.

It’s also worth pointing out that you will see lots of entries with ‘contents’ app names but that is because I have an app with the same name for a different Django project. At first I thought using the same app name for two different Django projects was the issue, but then I noticed with the nomenclature, there is an underscore which further distinguishes each table entry. So for my current app, I should see “contents_pagecontents” which is unique and distinct without overlapping with any of the other Django projects. But no such entry exists.

The above is my best analysis / examination of the issue with my db and I don’t think I am any further along to identifying a potential solution. What else might you extrapolate based on what you see above? What other psql commands would you recommend to clarify the issue, @KenWhitesell?

To collect the output below, I leveraged this official postgresql doc: PostgreSQL: Documentation: 16: psql

Here is the output discussed above:

<project-name>::DATABASE=> \d+ 
                                                        List of relations
 Schema |               Name                |   Type   |     Owner      | Persistence | Access method |    Size    | Description 
--------+-----------------------------------+----------+----------------+-------------+---------------+------------+-------------
 public | accounts_authtoggle               | table    | <redacted> | permanent   | heap          | 40 kB      | 
 public | accounts_authtoggle_id_seq        | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | accounts_passphrase               | table    | <redacted> | permanent   | heap          | 40 kB      | 
 public | accounts_passphrase_id_seq        | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | articles_article                  | table    | <redacted> | permanent   | heap          | 16 kB      | 
 public | articles_article_id_seq           | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_group                        | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | auth_group_id_seq                 | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_group_permissions            | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | auth_group_permissions_id_seq     | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_permission                   | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | auth_permission_id_seq            | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_user                         | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | auth_user_groups                  | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | auth_user_groups_id_seq           | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_user_id_seq                  | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | auth_user_user_permissions        | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | auth_user_user_permissions_id_seq | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_content                  | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | contents_content_id_seq           | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_gatewayprotect           | table    | <redacted> | permanent   | heap          | 0 bytes    | 
 public | contents_gatewayprotect_id_seq    | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_induction                | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | contents_induction_id_seq         | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_preamble                 | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | contents_preamble_id_seq          | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_research                 | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | contents_research_id_seq          | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_scriptsuggestion         | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | contents_scriptsuggestions_id_seq | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | contents_stockscript              | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | contents_stockscript_id_seq       | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | django_admin_log                  | table    | <redacted> | permanent   | heap          | 56 kB      | 
 public | django_admin_log_id_seq           | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | django_content_type               | table    | <redacted> | permanent   | heap          | 40 kB      | 
 public | django_content_type_id_seq        | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | django_migrations                 | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | django_migrations_id_seq          | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | django_session                    | table    | <redacted> | permanent   | heap          | 72 kB      | 
 public | essays_bibliographyarticle        | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | essays_bibliographyarticle_id_seq | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | essays_contentchanges             | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | essays_contentchanges_id_seq      | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | essays_curatedslashdot            | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | essays_curatedslashdot_id_seq     | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | essays_curatedwatchtower          | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | essays_curatedwatchtower_id_seq   | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | essays_essayarticle               | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | essays_essayarticle_id_seq        | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | essays_objectionsarticle          | table    | <redacted> | permanent   | heap          | 8192 bytes | 
 public | essays_objectionsarticle_id_seq   | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | generators_generator              | table    | <redacted> | permanent   | heap          | 120 kB     | 
 public | generators_generator_id_seq       | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | landings_aboutcontent             | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | landings_aboutcontent_id_seq      | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | landings_essaylist                | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | landings_essaylist_id_seq         | sequence | <redacted> | permanent   |               | 8192 bytes | 
 public | landings_howto                    | table    | <redacted> | permanent   | heap          | 48 kB      | 
 public | landings_howto_id_seq             | sequence | <redacted> | permanent   |               | 8192 bytes | 
(59 rows)

Creating a new db is costly. There has to be a way to reset my app’s tables with the same db: for example using $ python manage.py migrate contents zero which restores the contents’ app to its original state. It’s also worth pointing out that it’s a good thing I backed up my ‘migrations’ directory instead of deleting it. So with some cp and mv operations, everything is back to its original state.

So I see where (either) you don’t have that table in your database, or that your list is truncated.

When you restored your migrations directory, did that include the empty __init__.py files? (Make sure they’re present in every migrations directory across all apps.)

See what the output of a manage.py showmigrations looks like. It should show all your migrations files with some (most? all?) as having been applied.

There is - but potentially problematic. You can try a migrate with the --run-syncdb option, followed by a migrate with the --fake option. If your migrations files are up-to-date and current with your models, this should work reasonably well. (There are potential issues with foreign keys, data migrations, and other situations, so it’s not a perfect solution.)

And as you’ve mentioned, there is the option of backing up your database, migrating back to zero, and rolling forward from there - doing the restore after all tables have been created.

Thanks Ken for your feedback.

I since fiddled around with deleting, replacing, renaming my model and views while also using various migrations / migrate commands (e.g. with parameters such as --run-syncdb, --fake, --prune) without success.

In the end I just started a fresh web app from scratch with different naming conventions. Now my site seems to work.