How to automatically create postgis database for Django testing? - python

I'm trying to test my Django apps which run on a PostGIS database, by following the info in the Django testing docs.
Normally I create a new database by copying a template:
(as user postgres)
createdb -T template_postgis -O lizard test_geodjango2
When I run ./manage.py test, I get the following message:
Creating test database...
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_geodjango2', or 'no' to > cancel:
What's the best way to let the system create the database?

It may be that your DATABASE_USER doesn't have permissions to create a new database/schema.
Edit
If you read the source for the Django test command, you'll see that it always creates a test database. Further, it modifies your settings to reference this test database.
See this: http://docs.djangoproject.com/en/dev/topics/testing/#id1
What you should do is use fixtures. Here's how we do it.
From your template database, create a "fixture". Use the manage.py dumpdata command to create a JSON file with all of your template data. [Hint, the --indent=2 option gives you readable JSON that you can edit and modify.]
Put this in a fixtures directory under your application.
Reference the fixtures file in your TestCase class definition. This will load the fixture prior to running the test.
class AnimalTestCase(TestCase):
fixtures = ['mammals.json', 'birds']
def testFluffyAnimals(self):
etc.
The fixtures replace your template database. You don't need the template anymore once you have the fixtures.

As S.Lott mentioned, use the standard test command.
Using geodjango with postgis you'll need to add the following to your settings for the spatial templates to be created properly.
settings.py
POSTGIS_SQL_PATH = 'C:\\Program Files\\PostgreSQL\\8.3\\share\\contrib'
TEST_RUNNER='django.contrib.gis.tests.run_tests'
console
manage.py test
Described here:
http://geodjango.org/docs/testing.html?highlight=testing#testing-geodjango-apps
I haven't looked into it yet, but when I do this I get prompted for the database password when it attempts to install the necessary sql.

As of Django 1.11, Django supports the Postgres-only setting settings.DATABASE[whatever]['TEST']['TEMPLATE'] that dictates what template the test database is created from:
https://docs.djangoproject.com/en/dev/ref/settings/#template

Related

Django dumpdata from multiple databases

Running on Django 3.2 I use dumpdata -o db.json -a to export multiple databases to .json.
Looking into dumpdata.py, it retrieves all objects from a model by calling
queryset = objects.using(using).order_by(model._meta.pk.name)
https://github.com/django/django/blob/main/django/core/management/commands/dumpdata.py, line 185
My problem is that in my case, using is set to 'default' by default, even though I use --all parameter. And later, when calling objects.using(using) it tries to retrieve all objects from default database, even though it's supposed to be 'MIFIR'. What did I do wrong? Have I misconfigured something in my database? I set the app_label in _meta and added my app_label to dbrouter.py, I can see it resolving database name correctly.
Manager, Still tries to use default, Error
Seems that you can use --database to specify a databse.
Also keep in mind that to add new database to Django project you need to create a DBRouter for that database. Not sure, but that might be the problem...

Wrong table used when running tests Django Pycharm

I used inspectdb to import the Models schema from MySQL database connected with MySQL Connector/Python.
When I run the tests, the system shows:
django.db.utils.ProgrammingError: Table 'test_mydb.cards' doesn't exist
But the table name is just mydb.cards, not test_mydb.cards
Why is this prefix being added? My app's name is just container.
Django uses unittest module for testing, also it creates a blank database for testing as tests should be run ideally always on same blank database or fixtures filled database.
Tests that require a database (namely, model tests) will not use your
“real” (production) database. Separate, blank databases are created
for the tests.
Regardless of whether the tests pass or fail, the test databases are
destroyed when all the tests have been executed.
Check out if you are having migration sorted for the table test tries to access, as all tables that don't have migrations aren't accessible to test suite without monkeypatching or workarounds
I found the reason: I had managed property to False in models.py Class Meta for each table. I never set it there myself, it is the default after doing inspectdb.
Please read: Django Models Options: Managed

creating test database for Django Unit testing

How do I populate the test database created while testing the Django test cases with the values from some other database(for ex: the Production database.)
In detail:
when I run the below command,
$ python manage.py test
a test data base is created for the testing purpose, but it doesn't have any data in it. I want the test database created to be populated with some initial values.
Thanks..
You can use dumpdata to get a file with data from your live db.
Then you can load data from a file automatically for a test (see Django tests):
from django.test import TestCase
from django.core.management import call_command
class Tests(TestCase):
#classmethod
def setUpTestData(cls):
call_command('loaddata', 'myfile', verbosity=0)
You may use django fixtures to populate your test database.
Create a fixture of your production db and write it to some file
python manage.py dumpdata > backup.json
You can populate your test database using this command
python manage.py loaddata backup.json
if you want to do this by running python manage.py test then you should write custom django-admin commands
You want to check out fixtures. Here's a link to docs page: https://docs.djangoproject.com/en/1.8/howto/initial-data/
Basically you might want to dump your current database for testing purposes, so you'd do something like:
python manage.py dumpdata
Then you want to place your file in a directory that Django will look for fixtures. You can either specify it in settings with FIXTURE_DIRS variable or use default. The default is simply inside a fixtures directory in your Django app.

Django tests: how to specify the apps whose databases I want to use?

My default database is not being migrated into Django's test database. A database is being created with default tables that Django uses to log tests (such as django_content_type and django_admin_log), but not my app's tables.
When I run the tests with a verbosity level of 3 (-v 3), I see that my app is categorized under Synchronizing apps without migrations... which confirms that the migrations aren't being performed.
I don't, however, know how to tell Django's tests to migrate my app's database tables. I can output python manage.py makemigrations easily but apparently that doesn't carry over to the tests.
What am I missing?
Thank you!
Edit: Sorry, I meant the relations are not being created. I want to test views which rely on models in the database. In order to do so, I'm uploading fixtures (to not deal with data on production). However, when I try to upload a fixture I get a relation "mymodel" does not exist error.
Django's tests are designed to create a test database to perform tests.
I think that making your tests depend of a prod database is a bad idea.
You should design your tests to cover as many cases as possible, not to check if it works with your current database (which can evolve).
Here are some pages about testing with django 1.8 :
https://docs.djangoproject.com/en/1.8/intro/tutorial05/
https://docs.djangoproject.com/en/1.8/topics/testing/

Why does Django throw a 'does not exist' error when I try to add a field

Currently I'm using the default admin portal which is working fine. Then inside models.py I try to add a field as follows:
class MyModel(models.Model):
# new field is 'info'
info = models.CharField(max_length=100)
MyModel has already been successfully defined and used in the above code I simply wish to add a single field. I rerun sync
python manage.py syncdb
Creating tables ...
Installing custom SQL ...
Installing indexes ...
Installed 0 object(s) from 0 fixture(s)
However then Django throws an error when I try to use the interface
column myproject_mymodel.info does not exist
What am I doing wrong?
manage.py syncdb will only create tables that do not exist, it will not work for adding or removing columns, or for modifications to columns.
I suggest reading through the following chapter of the Django Book (which is free online):
Chapter 10: Advanced Models
Here are the steps given in that chapter for adding fields:
First, take these steps in the development environment (i.e., not on the production server):
Add the field to your model.
Run manage.py sqlall [yourapp] to see
the new CREATE TABLE statement for the model. Note the column
definition for the new field.
Start your database’s interactive
shell (e.g., psql or mysql, or you can use manage.py dbshell). Execute an ALTER TABLE statement that adds your new column.
Launch
the Python interactive shell with manage.py shell and verify that
the new field was added properly by importing the model and
selecting from the table (e.g., MyModel.objects.all()[:5]). If you
updated the database correctly, the statement should work without
errors.
Then on the production server perform these steps:
Start your database’s interactive shell.
Execute the ALTER TABLE statement you used in step 3 of the development environment steps.
Add the field to your model. If you’re using source-code revision control and you checked in your change in development environment step 1, now is the time to update the code (e.g., svn update, with Subversion) on the production server.
Restart the Web server for the code changes to take effect.

Categories