#26163: Wrong related fields in ._meta.get_fields with multiple database on
foreignkey
-------------------------------------+-------------------------------------
Reporter: aRkadeFR | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) | Keywords: models, meta,
Severity: Normal | get_fields, fields, router,
| multiple, databases
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Hello,
I tried to find a similar ticket and didn't find it.
I setup a simple use case to show the error.
2 applications: appa and appb.
You override (by inheritance) django.contrib.auth.models.Group in <appa>,
you have a model ModelB in <appb> that has a foreign key to Group of
django.contrib.auth.
You setup a DatabaseRouter to route every <appa> model to the 'default'
database, and all <appb> model to the 'other' database.
If you ._meta.get_fields() on GroupA, you see the foreign key of the
ModelB which is related to django.contrib.auth in the other database. The
related field shouldn't be visible from the get_fields() on GroupA.
I got this error from debugging a "missing attribute" while Django was
emulating the DELETE ON_CASCADE in python and following the wrong parent
model to get then the related_fields.
Thanks for all the information and keep up the good work :)
{{{
# settings
DATABASE_ROUTERS = ['projecta.router.CustomRouter']
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'HOST': 'localhost',
'PORT': '5432',
'NAME': 'default',
'USER': 'postgres_user',
'PASSWORD': 'pouetpouet',
},
'other': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'HOST': 'localhost',
'PORT': '5432',
'NAME': 'other',
'USER': 'postgres_user',
'PASSWORD': 'pouetpouet',
}
}
# projecta/router.py
class CustomRouter(object):
""" CustomRouter """
def db_for_read(self, model, **hints):
if model._meta.app_label == 'appb':
return 'other'
if model._meta.app_label == 'auth':
return 'other'
return None
def db_for_write(self, model, **hints):
if model._meta.app_label == 'appb':
return 'other'
if model._meta.app_label == 'auth':
return 'other'
return None
def allow_relation(self, obj1, obj2, **hints):
if obj1._meta.app_label == 'auth' or \
obj2._meta.app_label == 'auth':
return True
return None
def allow_migrate(self, db, app_label, model=None, **hints):
""" auth need to go to the other database (for projectb) """
if app_label == 'appa':
return db == 'default'
if app_label == 'appb':
return db == 'other'
return None
# appa/models.py
from django.contrib.auth.models import Group
from django.db import models
class GroupA(Group):
extra_field = models.IntegerField()
# appb/models.py
from django.contrib.auth.models import Group
class ModelB(models.Model):
group = models.ForeignKey(Group, null=False)
# ipython
In [3]: GroupA._meta.get_fields()
Out[3]:
(<ManyToManyRel: auth.user>,
<ManyToOneRel: projectb.modelb>,
<...>
}}}
--
Ticket URL: <https://code.djangoproject.com/ticket/26163>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/051.d6bfa1f84249644fef7e82235e1188b0%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.