Hi Vinay,

On 02/02/2016 08:11 AM, 'Vinay Sajip' via Django users wrote:
> I've set up a simple project using with two databases, foo and bar in
> settings.py:
> 
> |
> DATABASES ={
>     'foo':{
>         'ENGINE':'django.db.backends.sqlite3',
>         'NAME':os.path.join(BASE_DIR,'foo.sqlite'),
>     },
>     'bar':{
>         'ENGINE':'django.db.backends.sqlite3',
>         'NAME':os.path.join(BASE_DIR,'bar.sqlite'),
>     }
> }
> DATABASES['default']=DATABASES['foo']
> 
> |
> 
> I have a simple model:
> 
> |
> classThing(models.Model):
>     name =models.CharField(max_length=20,unique=True)
> |
> 
> I have a simple management command:
> 
> |
> classCommand(BaseCommand):
>     help ='Add all the things.'
> 
> 
>     defadd_arguments(self,parser):
>         parser.add_argument('--database',nargs='?',metavar='DATABASE',
>                             default='default',
>                             help='Database alias to use')
>         parser.add_argument('things',nargs='+',metavar='THING',
>                             help='Things to add')
> 
> 
>     defhandle(self,*args,**options):
>         alias=options['database']
>         self.stdout.write('using alias %s'%alias)
>         withtransaction.atomic(using=alias):
>             forname inoptions['things']:
>                 try:
>                     Thing.objects.create(name=name)
>                     self.stdout.write('Added %s.\n'%name)
>                 exceptIntegrityErrorase:
>                     self.stderr.write('Failed to add thing %r: %s'%(name,e))
>                     break
> |
> 
> After running migrations to set up the two databases, using python
> manage.py migrate --data foo and python manage.py migrate --data bar, I
> then run python manage.py add_things fizz buzz which results in two
> records being added to foo.sqlite, as expected. 
> 
> If I then run python manage.py add_things fizz buzz --data bar, it seems
> reasonable to expect it to add the records to bar.sqlite. However, this
> is not what happens: it tries to add them to foo.sqlite, even though
> I've specified using=alias with the alias set to bar. So I get a
> constraint violation:
> 
> |
> usingaliasbar
> Failedto add thing 'fizz':UNIQUE constraint failed:hello_thing.name
> |
> 
> What have I overlooked? In a real case the atomic block might be
> manipulating lots of models in nested code, and I can't see that it's
> practical to call using() for every model. Somewhere, it looks like
> Django code is caching a connection based on what
> settings.DATABASES['default'] was when settings was imported, even
> though it is being overridden in the command line. If not actually a
> bug, this behaviour doesn't seem particularly intuitive, so any advice
> would be gratefully received.

Nothing in your code ever "overrides" settings.DATABASES['default'].
Defining an atomic block on a certain database has no effect on the
default database within that block, it just opens a transaction on the
requested database. "Which database is default" and "which database(s)
has/have transactions open on them" are completely orthogonal questions,
there is no implicit link between them. Nothing prevents you from having
simultaneous transactions open on multiple databases, and interspersing
queries to different databases while those transactions are open.

If calling .using() explicitly to use a non-default database is
burdensome (and the situation can't be handled automatically with a
custom database router class), you could look at a third-party solution
like django-dynamic-db-router [1], which provides an `in_database`
context manager that does what you were expecting `transactions.atomic`
to do for you.

Carl

[1]
https://github.com/ambitioninc/django-dynamic-db-router/blob/master/docs/quickstart.rst

-- 
You received this message because you are subscribed to the Google Groups 
"Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to django-users+unsubscr...@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-users/56B0CA99.2090308%40oddbird.net.
For more options, visit https://groups.google.com/d/optout.

Attachment: signature.asc
Description: OpenPGP digital signature

Reply via email to