I have a Django app that adds and displays stuff to my postgresql database online at elephantsql.com. My project file setup looks like this:
website/
website/
music/
playlist/
__pycache__/
migrations/
static/
templates/
__init__.py
admin.py
apps.py
models.py
tests.py
urls.py
views.py
.coverage
db.sqlite3
manage.py
My project works right now where when I run the server and go to /playlist/ it displays stuff correctly and connects to my postgresql database fine.
My settings.py DATABASES object looks like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql',
'NAME': 'kxvmghva',
'USER': 'kxvmghva',
'PASSWORD': '--an actual password---',
'HOST': 'raja.db.elephantsql.com',
'PORT': '5432',
}
}
Now I'm trying to write test cases in my playlist/tests.py file, but when I try to run these tests I'm getting errors.
my testing file I'm trying to run /playlist/tests.py
from django.test import TestCase
from .models import plays
from django.utils import timezone
class AnimalTestCase(TestCase):
def setUp(self):
print("setup")
#Animal.objects.create(name="lion", sound="roar")
#Animal.objects.create(name="cat", sound="meow")
def test_animals_can_speak(self):
"""Animals that can speak are correctly identified"""
print("test")
#lion = Animal.objects.get(name="lion")
#cat = Animal.objects.get(name="cat")
#self.assertEqual(lion.speak(), 'The lion says "roar"')
#self.assertEqual(cat.speak(), 'The cat says "meow"')
When I run the command "python manage.py test playlist" I get these errors:
C:\Users\marti\Documents\kexp\website>python manage.py test playlist
Creating test database for alias 'default'...
C:\Python36-32\lib\site-packages\django\db\backends\postgresql\base.py:267: RuntimeWarning: Normally Django will use a connection to the 'postgres' database to avoid running initialization queries against the production database when it's not needed (for example, when running tests). Django was unable to create a connection to the 'postgres' database and will use the default database instead.
RuntimeWarning
Got an error creating the test database: permission denied to create database
Type 'yes' if you would like to try deleting the test database 'test_kxvmghva', or 'no' to cancel:
if I type 'yes' it leads to this error:
Destroying old test database for alias 'default'...
Got an error recreating the test database: database "test_kxvmghva" does not exist
I've been trying to solve this error by searching it online and have tried stuff like giving my user 'kxvmghva' CREATEDB permissions as well as running this line in my elephantsql db:
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA public TO kxvmghva;
But I'm still getting these errors when trying to run the tests.py file for my playlist/ app. This is my first time setting up test cases for a postgresql database in django and I would really appreciate any help or guidance. Thanks.
I suppose the plan you are using for database is free/shared, in case which you do not have rights to create additional databases.
This is not a Django problem but restrictions of the service you are using.
As pointed in the first answer, ElephantSQL free tier (I suppose you're using this one) is shared. In that server, they have several DBs, so you have access to one and can't create another one.
I've tried to create an instance just for tests, but it also fails because "On PostgreSQL, USER will also need read access to the built-in postgres database." (from django docs).
So, my solution, and understand it is not the best of practices (because you'll have a different environment for testing) is replacing the engine for testing:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
},
}
This configuration works because (from the django docs):
When using SQLite, the tests will use an in-memory database by default (i.e., the database will be created in memory, bypassing the filesystem entirely!)
Two notes:
Use GitHub actions or a similar solution to test against PostgreSQL in each commit (this way, you reduce the danger of using different test and prod databases)
The easiest way to have a different setting config is to use separate files. I follow the logic in cookiecutter-django
Related
I am building an app using Django and Postgres. I managed to do migrations and I want to test it. When I test with sqlite everything works fine, but when I run tests with postgres I'm getting this error:
Creating test database for alias 'default'...
Got an error creating the test database: permission denied to create database
I've checked user's permissions and I'm sure that this user have permission to create database.
My database config looks like this:
# DATABASES = {
# 'default': {
# 'ENGINE': 'django.db.backends.sqlite3',
# 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
# }
# }
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': '***',
'USER': '***',
'PASSWORD': '***',
'HOST': '****',
'PORT': '****',
}
}
My postgres db is on a server.
My questions are:
What is the right way to config my db and run tests?
Should I be using sqlite for testing?
If so how my code should look like, so I don't have to comment configs?
It looks like your DB user doesn't have permission to create a new database. Please, take a look here. This command-line utility allows you to create a user and set their permissions.
Example:
createuser my_user --createdb -W --username postgres
Note: you are creating user "my_user" on behalf of PostgreSQL admin role which is postgres by default.
Answering your questions:
You may have several configs for different stages, e.g development, testing, production.
You could use both SQLite and Postgres databases for testing purposes to some extent. You should be awarded, though, if your app relies on some specific features available only in Postgres, then using SQLite for testing doesn't make sense. I personally prefer using the same database for all stages. You could also use docker if you don't want to install DB server on your machine.
I have an API running on Heroku and would like to be able to test it using the test database. My problem I have is that the TestCase setUp(self) method adds the data to an automatically created test database. Then my tests send a POST request to the locally running version of itself. That code then is just using the regular default database instead of the test database the tests are running in.
Here's some code and what I've tried.
In my main settings.py I have named my database like so
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'theOneTrueDB',
}
}
And I read here (https://docs.djangoproject.com/en/3.0/topics/testing/overview/#the-test-database) that
The default test database names are created by prepending test_ to the value of each NAME in DATABASES.
So I figured in my views file for one of my apps I could just do
Tenant.objects.using('test_theOneTrueDB').all() and that would work but it says
django.db.utils.ConnectionDoesNotExist: The connection test_theOneTrueDB doesn't exist
I have also tried
Tenant.objects.using('test_default')
and many other things. I am lost. I would also be okay with setting up another database and then using that in the setup with
Tenant.objects.save(using='theOneTrueDBTest)
or something like that.
Any help would be appreciated!
EDIT:
I know have my settings looking like this
DATABASES = {
'default': {
'NAME': 'theOneTrueDB',
'ENGINE': 'django.db.backends.sqlite3',
},
'other': {
'NAME': 'theOneTrueTest',
'ENGINE': 'django.db.backends.sqlite3',
}
}
but then if I try to save to the other database like this
tempPM.save(using='other')
Then I get this error
AssertionError: Database queries to 'other' are not allowed in this test. Add 'other' to API.tests.TenantLogin.databases to ensure proper test isolation and silence this failure.
You don't need to access the test database directly. It will be used by default and you don't need to worry about it.
By default for sqlite3 backend will be used in-memory database, with the name like this file:memorydb_default?mode=memory&cache=shared,
you can examine the settings while tests are running via:
from django.conf import settings
print(settings.DATABASES)
I'm working on my first-ever Heroku/Django app. I just want to be sure I'm setting my DATABASE_URL and DATABASES variables correctly. Here's what's in my code:
import dj_database_url
DATABASE_URL = 'postgresql:///my_app'
# Parse database configuration from $DATABASE_URL
DATABASES = {
'default': dj_database_url.config(default=DATABASE_URL)
}
When I just have DATABASES['default'] = dj_database_url.config() and I try to use Django commands like run server or migrate I get the following error: NameError: name 'DATABASES' is not defined. I set the DATABASE_URL since doing so appears to solve this issue (after I create the my_app database).
Everything appears to be working fine as I code and test, but I've also seen a half-dozen different ways to set the database variables on the internet. If this isn't correct, I'd like to fix it now. The thing that really confuses me is, when I push my app to Heroku, how will the data get pushed to the web, when the database is /usr/local/var/postgres? Or will this not happen at all? Am I just too confused/tired at this point?
This is documented on Heroku Devecenter
# Parse database configuration from $DATABASE_URL
import dj_database_url
# DATABASES['default'] = dj_database_url.config()
#updated
DATABASES = {'default': dj_database_url.config(default='postgres://user:pass#localhost/dbname')}
If you need Database connection pooling add this bits too. More details
# Enable Connection Pooling
DATABASES['default']['ENGINE'] = 'django_postgrespool'
This is a simple matter of logic. You can't set the "default" key of the DATABASES dictionary before you have defined the dictionary itself.
Whether or not you set the default parameter to dj_database_url inside the call or as a separate DATABASE_URL variable is irrelevant, especially as that won't even be used on Heroku as it will be overridden by environment variables.
This allows you to use any database settings during development,
but at production (on Heroku), DATABASES['default'].update(db_from_env) changes the database settings to the one created by Heroku.
import dj_database_url
DATABASES = {
'"default": {
"ENGINE": "django.db.backends.sqlite3",
"NAME": os.path.join(BASE_DIR, "db.sqlite3"),
}
}
db_from_env = dj_database_url.config(conn_max_age=500)
DATABASES['default'].update(db_from_env)
You could use any database settings, but the last two lines allow heroku to create its own database for you.
I'm new to Django and MySQL, and am trying to continue a project written by a previous developer.
I've just finished a fresh install of MySQL (didn't set any password). When I run python manage.py syncdb, I get the error:
python manage.py syncdb
/home/home/.virtualenvs/sorrento/local/lib/python2.7/site-packages/debug_toolbar/settings.py:134: DeprecationWarning: INTERCEPT_REDIRECTS is deprecated. Please use the DISABLE_PANELS config in theDEBUG_TOOLBAR_CONFIG setting.
"DEBUG_TOOLBAR_CONFIG setting.", DeprecationWarning)
OperationalError: (1045, "Access denied for user 'home'#'localhost' (using password: NO)")
This is the database config in settings.py:
########## DATABASE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '',
}
}
########## END DATABASE CONFIGURATION
Since NAME is empty, does this mean there isn't a database set up? Do I need to get a database dump from the previous developer? Or is there something else I'm missing?
It is telling that you don't have permissions to edit the DB. To be able to connect you will need the NAME of the database and a USER and PASSWORD to connect with.
You don't need to get a copy of the db from the previous developer unless you actually need any of the data from there.
You have a fresh install of MySQL, so you just need to create an (empty) database.
Firstly, edit your db settings so that the USER attribute is 'root' and the NAME attribute is a relevant name (perhaps the name of your project).
Then, from the shell, do mysql -u root and then CREATE DATABASE <dbname> where dbname is the NAME you used above.
Now you should be able to run syncdb.
In this tutorial, it never says to edit the settings.py, in the previous docs, which supported django 1.5 you needed to edit settings.py.
So do you need to edit that file or not? Did the author skip that part because it was kinda obvious?
I actually don't see the name settings.py in the new docs, and there aren't too many mongo db django tutorials on the web. And the questions here, if any are outdated. Thereby I'm sorry if this turns out to be a naive question.
And if you want to use pymongo, AFAIK you don't connect from settings.py so I just had to ask.
Personally, I like to have all my database configs in settings, so I have mongo database configuration in settings.py along with my relational database configs:
MONGO_DBS = {
'default': {
'alias': 'default', # the alias that Documents refer to
'name': 'default', # the name of the database to connect to
'host': 'localhost', # the host
'port': 27017, # the port
'username': '', # not implemented
'password': '', # not implemented
'enabled': False, # whether or not we connect to this database
},
}
Then, I have a little snippet of code that runs in settings.py (cue some grumbling) and connects to all of the relevant mongo instances:
from mongoengine import connect
import sys
if not (len(sys.argv) > 1 and sys.argv[1] == 'test'):
# Don't run this if we're running in unit tests. The test runner will spin
# up the appropriate databases and spin them down appropriately.
for db_name in MONGO_DBS:
db_meta = MONGO_DBS[db_name]
if db_meta['enabled'] and 'alias' in db_meta:
connect(db_meta['name'], alias=db_meta['alias'], host=db_meta['host'], port=db_meta['port'],
lazy_connect=db_meta.get('lazy', True))
Obviously, this code is still somewhat incomplete in so far as authentication doesn't happen. But it should be a reasonable launching point for you.
I should add that I just dug up references to settings.py in the django documentation page for mongoengine. Currently, it's located at http://docs.mongoengine.org/en/latest/django.html.
Lastly, I should add that this advice applies through mongoengine 0.8.7 (latest as of this answer). YMMV with future versions.