Relation does not exist error in Django after postgresql integration - python

I used sqlite3 during development, then changed my database settings to postgresql:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'test2',
'USER': 'postgres',
'PASSWORD': 'aman',
'HOST': 'localhost',
'PORT': '5432',
}
}
Regardless of any command I write, it gives me the error:
django.db.utils.ProgrammingError: relation "taksist_category" does not exist
LINE 1: ...st_category"."id", "taksist_category"."name" FROM "taksist_c...
Category model exists inside taksist application. If I take back my database settings to sqlite3, then application runs successfully.
I cannot even run my server. Even if there is a problem with my model taksist/Category, my application should run. Here strange thing is whatever command is written, I got this error. I cannot do makemigrations, migrate, runserver.
What did I do to solve the issue:
deleted migrations folder, and tried makemigrations
I created empty migrations folder with init.py inside, and
tried makemigrations
python manage.py migrate --fake
none of above worked.
Here is taksist.category model, in case.
class Category(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length = 20)
def __str__(self):
return self.name
Any help of yours is appreciated. thank you in advance.

The root cause for "relation does not exist" is that migrations have not been run.
However, via the comments:
whatever command I execute, I got this error. even runserver, makemigrations and migrate. after change database settings to postgresql, i could not migrate. i can do nothing.
That is likely to mean you've written your application in a way that it accesses the database during initialization time, e.g. something like
from my_app.models import Blog
default_blog = Blog.objects.get(pk=1)
def view(...):
This means Django will attempt to access the database as soon as that module is imported. If that module gets imported while Django is trying to initialize itself for migrate, you get an exception.
You can look at the traceback for your django.db.utils.ProgrammingError to figure out what the offending access is and fix it. For instance, the above pattern would be better served by something like a get_default_blog() function.
If I take back my database settings to sqlite3, then application runs successfully.
This bug also means that if you rename or delete your current, working SQLite database, you can't get a new one going either, since attempting to migrate it would fail with a similar error. This is not just Postgres's "fault" here.

If it' a test DB do a py manage.py flush
command, then run the py manage.py makemigrations again, then the py manage.py migrate command.
That should resolve.

Related

I can't run tests in Django, I'm getting the error, "Got an error creating the test database: permission denied to create database"

I'm really new to django, in fact this is my first project for a course I'm doing. I've finished it, but I still need to run tests. I've created one test, tried to run it, and this error came up: "Got an error creating the test database: permission denied to create database"
From my understanding of researching the problem so far, the problem is that the user doesn't have permission to create the temporary test database. But I don't understand, because on Django admin I have logged in as the superuser. Shouldn't they have access?
I've read I can use the command ALTER USER conorg180 CREATEDB. But I've tried this in the python shell and it's not working, it says that I have a syntax error. I'm not sure if the username is right. My superuser is called conorg180. However, I'm not sure if I need to use the superuser username or a different username, like one registered to the database.
I don't have a username property on my database, because I have it set up using dj-database-url and postresql, you can see below. Is there a way I can find out the user property to get this command to run? Or another way around it?
You can see my settings.py and testing file below.
**
settings.py
**
DATABASES = {
'default': dj_database_url.parse(os.environ.get('DATABASE_URL'))
}
test-role-forms.py
from django.test import TestCase
from .forms import RoleForm
class TestRoleForm(TestCase):
def test_role_id_is_required(self):
form = RoleForm({"role_id": "", 'title': 'test_title', "hourly_wage": "10.00"})
self.assertFalse(form.is_valid())
self.assertIn('role_id', form.errors.keys())
self.assertEqual(form.errors['role_id'][0], "This field is required.")

Django ORM using external database to unmanaged model in view says relation does not exist

I have two Postgres database connections and when using another than default ORM calls fail on views, but not raw. I am using docker and containers are connected and using Django's own runserver command. Using ORM in django command or django shell works fine, but not in a view.
As a side note, both databases are actually Django-projects, but main project is reading some data directly from another project's database using own unmanaged model.
Python: 3.9.7
Django: 3.2.10
Postgres: 13.3 (main project), 12.2 (side project)
# settings
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'USER': 'pguser',
'PASSWORD': 'pguser',
'NAME': 'mainproject',
'HOST': 'project-db', # docker container
'PORT': '5432',
},
'external': {
'ENGINE': 'django.db.backends.postgresql',
'USER': 'pguser',
'PASSWORD': 'pguser',
'NAME': 'sideproject',
'HOST': 'side-db', # docker container, attached to same network
'PORT': '5432',
},
}
# My unmanaged model
class MyTestModel(models.Model):
​
class Meta:
# table does not exist in 'default', but it does exist in 'external'
db_table = 'my_data_table'
managed = False
# my_data_table is very simple it has id field as integer
# and primary key (works out of the box with django)
# it has normal fields only like IntegerField or CharField
# But even if this model is empty then it returns normally the PK field
# My custom command in Main project
# python manage.py mycommand
# ...
def handle(self, *args, **options):
# This works fine and data from external is populated in MyTestModel
data = MyTestModel.objects.using('external').all()
for x in data:
print(x, vars(x))
# My simple view in Main project
class MyView(TemplateView):
# But using example in views.py, random view class:
def get(self, request, *args, **kwargs):
# with raw works
data = MyTestModel.objects.using('external').raw('select * from my_data_table')
for x in data:
print(x, vars(x))
# This does not work
# throws ProgrammingError: relation "my_data_table" does not exist
data = MyTestModel.objects.using('external').all()
for x in data:
print(x, vars(x))
return super().get(request, *args, **kwargs)
So somehow runserver and views does not generate query correctly when using ORM. It cannot be a connection error, because when running command or view with ".raw()" works.
Now the funny thing is that if I change "db_table" to something what is common in both database lets say "django_content_type" ORM "filter()" and "all()" works in view too. And yes then it actually returns data from correct database. So if main project has 50 content types and side project (external) has 100 content types it actually returns those 100 content types from external.
I have tried everything, rebuilding docker, creating new tables to database directly, force reload postgres user and made sure all is owner permissions and all permissions (should be ok anyway because command side works). I even tried to use another database.
I know I didn't post the full settings and my local settings which could have helped more to solve this case.
But I noticed that I had installed locally Django Silk, which captures the request and tries to analyze called database queries. Looks like it may have been loaded too early or it doesn't like external databases. But disabling Django silk from installed apps and removing it's middleware removed the problem.

How to migrate existing table using Django and Python

I need one help. I have one existing mysql table in my localhost database and I need it to migrate using Django and Python. Here is my code:
settings.py
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'djangotest',
'USER': 'root',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
I am giving my table structure below.
Person:
id name phone age
models.py:
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Person(models.Model):
name = models.CharField(max_length=200)
phone = models.CharField(max_length=15)
age = models.IntegerField()
Actually I am new to Django and Python and here I need to know command which can migrate the existing table.
to create migrations you need to use this command -
python manage.py makemigrations
the above command will create a file inside the migrations folder in your app directory and
to create/update table using the migration file in the database
python manage.py migrate
The above command will create/update a table in your DB.
Django Migration Docmentation
Let me know, if this is what you want!
In reference to akhilsp, I did not have to worry about table names using the _ format. Using the inspectdb command returned a Meta data for whatever the current table name is that I used in my model.
class Meta:
managed = False
db_table = 'malware'
Add --fake option to migrate command:
--fake
Tells Django to mark the migrations as having been applied or unapplied, but without actually running the SQL to change your
database schema.
This is intended for advanced users to manipulate the current
migration state directly if they’re manually applying changes; be
warned that using --fake runs the risk of putting the migration state
table into a state where manual recovery will be needed to make
migrations run correctly.
If you just start django project and didn't have initial migration: comment your Person model, make initial migration, apply it, uncomment Person, make migration for Person and at last migrate Person with --fake option.
You can use inspectdb command from the shell.
python manage.py inspectdb
This will print models corresponding to the current database structure. You copy the required model, make changes like adding validations, and then add other models.
python manage.py makemigrations will create migrations, and
python manage.py migrate will apply those migrations.
N.B: Your table name should be in the format "appname_modelname" where appname is name for django app name (not project name).

python manage.py migrate relation "" does not exist

I have 2 models - Facility and Slot.
class Facility(BaseModel):
name = models.CharField()...
class Slot(BaseModel):
name = models.CharField()...
slot = models.ForeignKey(Facility)
These work perfectly fine.
Now I am adding another model:-
class BlockedSlot(BaseModel):
slots = models.ManyToManyField(Slot)
Now when I run python manage.py makemigrations, it successfully creates a migration file.
But when I run python manage.py migrate, it gives the error - relation "facilities_slot" does not exist.
(models are in facilities.py)
I even tried resetting the db and trying, but it still fails.
I even deleted all the existing migrations and reran makemigrations that generated the 0001_initial.py and again ran migrate, but still fails.

Django test runner ignoring the --settings option

I'm trying to use a different set of configs for testing my django app (like, using in-memory sqlite3 instead of mysql) and for this purpose I'm trying to use another settings module. I run my tests this way:
python manage.py test --settings=test_settings
But Django seems to ignore my test_settings module. Am I doing something wrong?
Is test_settings a file or a directory?
Here's how I load different settings for tests. In settings.py, at the bottom:
# if manage.py test was called, use test settings
if 'test' in sys.argv:
try:
from test_settings import *
except ImportError:
pass
Super bonus! If you want to use sqlite3 for tests, you should activate integrity constraints, so you get the same foreign key exceptions as with mysql (lost of lot of time with this one). In some file of your project:
from django.db.backends.signals import connection_created
def activate_foreign_keys(sender, connection, **kwargs):
"""Enable integrity constraint with sqlite."""
if connection.vendor == 'sqlite':
cursor = connection.cursor()
cursor.execute('PRAGMA foreign_keys = ON;')
connection_created.connect(activate_foreign_keys)
I just bumped into this and confirm that on Django 1.6.1 --settings option is ignored.
I filed a ticket on the Django bug tracker:
https://code.djangoproject.com/ticket/21635#ticket

Categories

Resources