Opened 5 years ago

Closed 4 years ago

#14610 closed New feature (fixed)

fixtures should be able to specify their database

Reported by: cyberlogi Owned by: nobody
Component: Testing framework Version: 1.2
Severity: Normal Keywords:
Cc: brenthoover Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

I have a product that has two databases, one is the member related database and the other is a 10gb static database. For performance reasons, I have to keep them separate and I have a database router which handles this. For testing purposes I need to load both databases for some of my function and view tests. The initial load of the test databases works correctly and I have two separate test databases, but when I specify fixtures in my TestCase, they all run against the default database, which causes the fixtures to fail to load.

After spending the last 24 hours diving through the Django source code and talking to other developers, I cannot find a way to specify the database on which a fixture should load (when the 'syncdb' command is executed). This seems like a feature that should be build into fixtures (or the TestCase framework), otherwise developers can't test code that runs against multiple databases.

My database setup is:

DATABASES = {
	'default': {
		'NAME': 'matt',
		'ENGINE': 'mysql',
		'USER': 'myuser',
		'PASSWORD': 'changeit',
		'HOST': ''
	},
	'voters': {
		'NAME': 'voters',
		'ENGINE': 'mysql',
		'USER': 'myuser',
		'PASSWORD': 'changeit',
		'HOST': ''
	}
}

Here is my simple router:

from django.conf import settings

class VotizenRouter(object):
	"""A router to control all database operations on models in
		the myapp application"""

	def db_for_read(self, model, **hints):
		"Point all operations on myapp models to 'other'"
		if model._meta.app_label == 'verifier':
			return 'voters'
		return None

	def db_for_write(self, model, **hints):
		"Point all operations on myapp models to 'other'"
		if model._meta.app_label == 'verifier':
			return 'voters'
		return None

	def allow_relation(self, obj1, obj2, **hints):
		"Allow any relation if a model in myapp is involved"
		if obj1._meta.app_label == 'verifier' or obj2._meta.app_label == 'verifier':
			return True
		return None

	def allow_syncdb(self, db, model):
		"Make sure the myapp app only appears on the 'other' db"
		if db == 'voters':
			return model._meta.app_label == 'verifier'
		elif model._meta.app_label == 'verifier':
			return False
		return None

The 'db' should be 'voters' when the 'app_label' of the model is 'verifier'. Since the fixture loading logic has the database set to 'default' it fails to load the fixture. For testing purposes I rewrote the 'allow_syncdb' function to always return None and as expected Django attempted to write the fixtures to the 'default' databases, instead of the one specified by the router.

Change History (5)

comment:1 Changed 5 years ago by mariarchi

  • Needs documentation unset
  • Needs tests unset
  • Patch needs improvement unset
  • Triage Stage changed from Unreviewed to Accepted

Sounds like a reasonable idea to me. Can you propose a syntax for fixtures to specify DB?

P.S. You don't actually need to explicitly "return None", function which is not returning anything is returning None anyway.

comment:2 Changed 4 years ago by julien

  • Severity set to Normal
  • Type set to New feature

comment:3 Changed 4 years ago by anonymous

  • Easy pickings unset

Any updates on this?

comment:4 Changed 4 years ago by brenthoover

  • Cc brenthoover added
  • UI/UX unset

According to the docs, this feature already exists (in 1.3)

https://docs.djangoproject.com/en/1.3/ref/django-admin/#database-specific-fixtures

Database-specific fixtures

If you are in a multi-database setup, you may have fixture data that you want to load onto one database, but not onto another. In this situation, you can add database identifier into . If your DATABASES setting has a 'master' database defined, you can define the fixture mydata.master.json or mydata.master.json.gz. This fixture will only be loaded if you have specified that you want to load data onto the master database.

So it would seem that the syntax is already prescribed for multi-db fixtures. However, from my experience this does not work correctly, or at least always. I found this looking for an existing bug report before submitting one. However it is in here as a feature request and I do not feel qualified to change it to a bug.

comment:5 Changed 4 years ago by aaugustin

  • Resolution set to fixed
  • Status changed from new to closed

Indeed, the problem originally described here is fixed.

If you find a bug, please open a separate ticket, and provide enough information for someone else to reproduce the problem.

Note: See TracTickets for help on using tickets.
Back to Top