i have two different SQL databases and three apps in my django project.
The apps are named PROD, TEST and common.
I am trying to route everything that comes from an url of PROD to models.py from PROD and database1, and everything that comes from an url of TEST to models.py from TEST and database2.
TEST
-- models.py
PROD
-- models.py
common
It worked fine, until i introduced 'common'(after cloning the project to another folder) and i don't know why.
settings.py:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'cfg_db_ic2_net_dev_test',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
},
'proddb': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'cfg_db_ic2_net_dev_prod',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
DATABASE_ROUTERS = ['PROD.dbRouter.ProdDBRouter']
PROD/dbRouter.py:
def db_for_read(self, model, **hints):
"Point all operations on prod models to 'proddb'"
from django.conf import settings
print(model._meta.app_label)
if model._meta.app_label == 'PROD':
return 'proddb'
return None
...
PROD/views.py:
def hosts(request):
print("I did this")
return render(request=request, template_name="common/hosts.html", context={"hosts": NetDefined.objects.all, "landscape": landscape})
The models.py for each TEST and PROD is pretty identical.
The issue that i have is that the template hosts.html is populated with data from the default data base and not from proddb database.
The reason for this is that the DBRouter doesn't recognize the model's model._meta.app_label, it says it's "TEST".
Even though the url is definitely routed correctly, the "I did this" is printed.
This only occured after reinstalling the project and introducing the third app.
So my question is: why doesn't Django recognize, that the views and models from "PROD" are being used and instead provides the wrong app_label to the router?
Thanks for your help!
Related
I have a Django application using decouple and dj_database_url (it is not on Heroku). If I put my connection information in settings.ini (DB_NAME, DB_USER, DB_PASSWORD, DB_HOST, and DB_PORT) and set up my database connection in settings.py like this:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': config('DB_NAME'),
'USER': config('DB_USER'),
'PASSWORD': config('DB_PASSWORD'),
'HOST': config('DB_HOST'),
'PORT': 'DB_PORT',
}
}
It works fine.
However, if I put this in my settings.ini:
DATABASE_URL=postgres://johndoe:mypassword#123.456.789.000:5000/blog_db
and reference it like this in my settings.py:
DATABASES = {"default": dj_database_url.config(default=config("DATABASE_URL"))}
It doesn't work. I just get a 500 when I try to run my server. I presume there is something wrong with my syntax. Can anyone point out what I'm doing wrong?
Thanks!
I want to keep my unit test database completely separate from other environments including using different user credentials. This is mostly to prevent anyone from unintentionally running unit tests against the development database and mangling the dev data or wiping it out entirely if the --keepdb option isn't specified. The code below detects the "test" in the sys args and this seems to work but is very clunky. If I'm missing a better way to do this please advise.
I have separate settings files for each environment so this will only be on the development server where the unit tests are run automatically and won't end up on any production servers.
Environment:
Django 1.11
Python 3.4.x
MariaDB
# this works but is clunky
import sys
if 'test' in sys.argv:
DATABASES = { # test db and user
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db_test',
'USER': 'test_user',
'PASSWORD': 'secretpassword',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': { # redundant but explicit!
'NAME':'dev_db_test',
},
}
}
else:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db',
'USER': 'dev_db_user',
'PASSWORD': 'dev_password',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': {
'NAME':'dev_db_test', # redundant but explicit!
},
}
}
I'd like to do this but unfortunately Django doesn't look at the TEST credentials
# cleaner approach but doesn't work - don't do this!
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dev_db',
'USER': 'dev_db_user',
'PASSWORD': 'dev_password',
'HOST': 'the-db-host',
'PORT': '3306',
'TEST': {
'NAME':'dev_db_test', # Django uses the test db NAME
'USER':'test_user_ignored', # but ignores the USER and PASSWORD
'PASSWORD':'ignoredpassword',
},
}
}
Would something like this work for your situation?
import sys
if 'test' in sys.argv:
NAME = 'dev_db_test'
USER = 'test_user'
PASSWORD ='secretpassword'
else:
NAME = 'dev_db'
USER = 'dev_db_user'
PASSWORD ='dev_password'
DATABASES ={ # test db and user
'default':
{
'ENGINE': 'django.db.backends.mysql',
'NAME': NAME,
'USER': USER,
'PASSWORD': PASSWORD,
'HOST': 'the-db-host',
'PORT': '3306',
'TEST':
{ # redundant but explicit!
'NAME':'dev_db_test',
},
}
}
print(DATABASES)
AFAIK, you don't need to create a separate test database if you want to run unit tests over it. Here is the documentation link of test database.
It states that:
Tests that require a database (namely, model tests) will not use your “real” (production) database.
Separate, blank databases are created for the tests.
You can follow this link to write your tests and it will not affect your production or development database.
i am creating database according this now: Saperate PostgreSQL db for each client, with automated migrations on creating client on single Django app and on same server
Now I want to serve the db per user. We can return db from db routers only if they exists in the DATABASES varriable in the settings file.
Does anybody know how to serve db which are created on server but not added in settings.py, which will be according to the logged in user.
There will be a main db for user, in which their relations with their db name is saved.
Settings.py
DATABASE_ROUTERS = ['app.router_middleware.DataBaseRouter']
DATABASES = {'default':
{
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': 'abc',
'USER': 'xyz',
'PASSWORD': '*****',
'HOST': 'localhost',
'PORT': '5432',
}
}
import django
django.setup()
from Client.views import ALL_DB
DATABASES.update(ALL_DB)
Client.views
ALL_DB = { x.db_name: {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': x.db_name,
'USER': 'xyz',
'PASSWORD': '****',
'HOST': 'localhost',
'PORT': '5432',
} for x in Client.objects.all()}
router_middleware.py
db_name = 'default'
class RouterMiddleware(CoreSessionMiddleware):
def process_request(self, request):
if request.user.is_authenticated() :
user = request.user
if ClientEmployee.objects.filter(user=user).exists():
client_employee = ClientEmployee.objects.get(user=user)
db_name = client_employee.client.db_name
class DataBaseRouter(object):
def db_for_read(self, model, **hints):
return db_name
def db_for_write(self, model, **hints):
return db_name
I originally had a django project with a single app and all models were defined in that app. The project, when initiated only used the default database. It has now become an unwieldy app that I'm trying to break down into smaller apps. Doing so, I want to use different databases for the different apps. I've setup new databases and a router in the settings.py file. However, I'm confused about how to migrate existing tables to the new databases.
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name',
'USER': 'db_user_name',
'PASSWORD': 'password',
'HOST': 'hostname',
'PORT': '3306',
},
'db2': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'db_name2',
'USER': 'db_user_name2',
'PASSWORD': 'password2',
'HOST': 'hostname2',
'PORT': '3306',
}
}
I would want an app (e.g. app1) to be moved from default to db2. The router already knows to specify app1 to db2 but running migrations is doing nothing. Any ideas?
#knbk's answer was ultimately correct, except that the solution involved an additional step.
1. python manage.py migrate auth --database=db2
2. python manage.py migrate app1 --database=db2
I have two settings files for my django project with different database settings.
First:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'dbname',
'USER': 'user',
'PASSWORD': 'megahardbreakingpassword',
'HOST': 'localhost',
'PORT': '',
'OPTIONS': {
'init_command': 'SET storage_engine=INNODB',
}
}
}
And second:
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': 'db.sqlite3',
'USER': '',
'PASSWORD': '',
'HOST': '',
'PORT': '',
}
}
When I run server with second database settings project works fine, but when I run first settings file with mysql, django returns 404 error for all urls.
I also use django-hosts for implementing subdomains patterns, so maybe something wrong here. My hosts.py code:
from django_hosts import patterns, host
host_patterns = patterns('',
host(r'^$', 'project.urls', name='host'),
)
I use django 1.4.2 and Python 2.7.9
And finally I found answer! According to e4c5's comment I searched problem in my views instead of my settings files. I wrote simple unittest and it gives me some strange tracebeck about my MySQL database such as wrong column name and deprecation warnings about duplication indexes.
I reinstall older version of MySQL server (5.0.70 instead of 5.6.25), run syncdb and migrations again and it completely solved my problems. So God bless TDD!