How do I obtain a cursor for a routed database? - django

django.db.connection.cursor() turns out to return a connection to default database, not a routed one.
How do I create a cursor to a database selected for my Django application by project configuration?

django.db provides a dictionary of all connections, according to the keys you use in your dictionary within the settings module:
from django.db import connections
cursor = connections['my_db_alias'].cursor()
This is documented here.

Ok, I've examined django.db.models.Model class and found out that routed connection if obtained through router each time:
from django.db import connections, router
using = using or router.db_for_write(self.__class__, instance=self)
connection = connections[using]
Unfortunately, router takes Model subclass as first argument of its db_for_write() method.

Related

Django - setUpTestData & Many to Many relationship

I need to add a many-to-many relationship in my setUpTestData sequence so that my tests will run correctly.
According to the docs, Many-to-Many relationships cannot be created until an object has been saved, as the primary key must first exist. This means that I cannot set the relationship in setUpTestData with Model.objects.create() as I do with other variables.
Is there any way to include a Many-to-Many relationship in setUpTestData?
As a partial answer, a solution I found in the docs seems to work half way. Here is my code:
(I'm linking a social app to Django's Sites framework so that my tests will be able to run).
SetupTestData.py
from django.test import TestCase
from django.contrib.sites.models import Site
from allauth.socialaccount.models import SocialApp
class TestData(TestCase):
#classmethod
def setUpTestData(cls):
cls.current_site = Site.objects.get_current()
cls.SocialApp1 = cls.current_site.socialapp_set.create(
provider="facebook",
name="facebook",
client_id="123456789",
secret="0987654321",
)
test_sandbox.py
from MyApp.tests.SetupTestData import TestData
from django.contrib.sites.models import Site
from allauth.socialaccount.models import SocialApp
class TestHomePage(TestData):
def test_sandbox(self):
print(Site.objects.all())
print(Site.objects.get_current())
print(Site.objects.get_current().socialapp_set.all())
print(self.SocialApp1)
print(self.SocialApp1.sites)
print(SocialApp.objects.get(provider='facebook').sites)
Test Output
Creating test database for alias 'default'...
[<Site: example.com>]
example.com
[<SocialApp: facebook>]
facebook
sites.Site.None
sites.Site.None
Destroying test database for alias 'default'...
You can see from the results that I can locate the app via Sites, but it doesn't seem to work backwards. I suppose if I somehow reversed the relationship in setUpTestData I could make it work the opposite way instead. I'll leave the question open for a better solution.

Django, multiple databases with raw sql. How to choose db?

I have a Django project that utilizes multiple databases. https://docs.djangoproject.com/en/dev/topics/db/multi-db/
I perform a lot of raw queries like this:
cursor = connection.cursor()
cursor.execute("select * from my_table")
....
transaction.commit_unless_managed()
How can I specify which database to use?
Refer django docs on executing custom query directly. Specify database in your connection as given below:
from django.db import connections
cursor = connections['db_alias'].cursor()
cursor.execute("select * from my_table")
And then commit using
from django.db import transaction
transaction.commit_unless_managed(using='db_alias')
try this may be it should works.
from django.db import connections
cursor = connections[’my_db_name’].cursor()
# Your code here...
transaction.commit_unless_managed(using=’my_db_name’)

Django + mongoengine, connect to mongo when used as auxiliary database

I'm trying to connect to mongodb using mongoengine.
Mysql is my default database, and I have 'mongoengine.django.mongo_auth' in my installed apps. I removed the 'AUTH_USER_MODEL = 'mongo_auth.MongoUser'' due to errors about not having a default connection.
I use mongo with celery so I don't think there's a problem with the setup. This is how I am attempting to connect - the code is in views.py
from mongoengine import connect
my_connect = connect('my_db', alias='mongo')
test = test(name='a_name', desc='a desc')
test.save(using='mongo')
my_connect.connection.disconnect()
Have finally managed to sort this out:
#settings.py
from mongoengine import register_connection
register_connection(alias='default',name='db_name')
#models.py
from mongoengine import Document, StringField (etc)
class my_col(Document):
field_a = StringField()
#in your app
from mongoengine import connect
my_con = connect('db_name', alias='default')
item = my_col(field_a='something')
item.save()
my_con.disconnect()

Django - how to enable foreign keys in SqLite3 backend

When trying to use SqlLite3 as the DB backend to Django, I'd like to be able to use SqLite's Foreign Key support.
According to http://www.sqlite.org/foreignkeys.html, you can enable foreign key support by running:
PRAGMA foreign_keys = ON;
This support is disabled by default, and would be desirable while running most db dependent tests.
How would one control this feature while using Django test framework? Can you send backend-specific commands in your setUp/tearDown methods? Would you rather specify this option in connection settings ('DATABASE = ' settings) globally?
It's partially answered here: https://stackoverflow.com/a/6843142/552671.
You can just activate it in your app (typically in myapp/apps.py).
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;')
class MyAppConfig(AppConfig):
def ready(self):
connection_created.connect(activate_foreign_keys)
You have to configure MyAppConfig as well, write default_app_config = 'myapp.apps.PanelConfig' to myapp/__init__.py.
Note: This will activate foreign keys not only for tests but also SQLite in general. I think that is what you want, though.
In current django it is not needed anymore. Closed in https://code.djangoproject.com/ticket/14204
And from 2.2 it is also on during unit testing :)

Language stored in Useprofile.language field applied on user log in

I need to set language for user in 2 cases:
User logs in (django checks his UserProfile field for language field value and sets the proper lang)
Users chenges lang in "user preferences" page.
I've tried with "user_logged_in" signal receiver
from django.utils import translation
from django.dispatch import receiver
from django.contrib.auth.signals import user_logged_in
#receiver(user_logged_in)
def setlang(sender, **kwargs):
translation.activate(kwargs['user'].get_profile().language)
kwargs['request'].session['django_language'] = translation.get_language()
This works fine until I restart my django instance. Though session is alive (no need to log in again) website is being displayed in language specified in settings.LANGUAGE
I think the same applies to situation #2 (on user preferences form save())
Following up to Timmy's answer you can find an already published middleware that does the job for you!
The translation of a Django app with the preferred language selected by a registered user can be done with the middleware django-user-language-middleware. This allows easy translation of your Django app by looking at the selected language in the user.language field.
Usage:
Add a language field to your user model:
class User(auth_base.AbstractBaseUser, auth.PermissionsMixin):
# ...
language = models.CharField(max_length=10,
choices=settings.LANGUAGES,
default=settings.LANGUAGE_CODE)
Install the middleware from pip:
pip install django-user-language-middleware
Add it to your middleware class list in settings to listen to requests:
MIDDLEWARE = [ # Or MIDDLEWARE_CLASSES on Django < 1.10
...
'user_language_middleware.UserLanguageMiddleware',
...
]
I hope this may help people landing on this question in the future.
I think it's better if you use middleware to achieve this. Django provides a way to add in hooks at various places throughout a request so that you can add custom code.
In your case: check on every request if there is a language variable in the session, if not, fetch the users language preference from the database and save it to the session variable. Check on a save signal whether or not the user has changed their preference; if so, update the session variable (you might have problems getting access to the request from the model level so it might be better to do this in the view).
I've used this snippet, but it conflicts with the Regular LocaleMiddleware, and thus I can't add a multilingual content farm.
http://django-hotclub.googlecode.com/svn-history/r708/trunk/pinax/profiles/middleware.py