primary - "Foreign Keys" en bases de datos muy separadas en Django
models django primary key (1)
Así es como lo resolví. Dejé de usar el proxy de usuario por completo.
models.py :
from django.db import models
from legacy_models import Person
from django.contrib.auth.models import User
class UserPerson(models.Model):
user = models.OneToOneField(User, related_name="person")
person_id = models.PositiveIntegerField(verbose_name=''PeopleID'', help_text=''ID in the Legacy Login system.'')
def __unicode__(self):
return "%s" % self.get_person()
def get_person(self):
if not hasattr(self, ''_person''):
self._person = Person.objects.get(pk=self.person_id)
return self._person
person=property(get_person)
class LegacyPersonQuerySet(models.query.QuerySet):
def get(self, *args, **kwargs):
person_id = UserPerson.objects.get(*args, **kwargs).person_id
return LegacyPerson.objects.get(pk=person_id)
class LegacyPersonManager(models.Manager):
def get_query_set(self, *args, **kwargs):
return LegacyPersonQuerySet(*args, **kwargs)
class LegacyPerson(Person):
objects = LegacyPersonManager()
class Meta:
proxy=True
y legacy_models.py :
class Person(models.Model):
id = models.AutoField(primary_key=True, db_column=''PeopleID'') # Field name made lowercase.
code = models.CharField(max_length=40, blank=True, db_column="person_code", unique=True)
first_name = models.CharField(max_length=50, db_column=''firstName'', blank=True) # Field name made lowercase.
last_name = models.CharField(max_length=50, db_column=''lastName'', blank=True) # Field name made lowercase.
email = models.CharField(max_length=255, blank=True)
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
def get_user(self):
from models import User
if not hasattr(self,''_user''):
self._user = User.objects.get_for_id(self.pk)
return self._user
def set_user(self, user=None):
self._user=user
user = property(get_user, set_user)
class Meta:
db_table = u''People''
Finalmente, en settings.py :
AUTH_PROFILE_MODULE = ''myauth.LegacyPerson''
Esta es una solución más simple, ¡pero al menos funciona! Significa que siempre que quiera el registro heredado tengo que llamar a user_profile
, y eso significa que hay una consulta adicional para cada registro de usuario, pero esto es una compensación justa porque en realidad no es muy probable que lo haga. una verificación cruzada que a menudo.
He escrito un sitio de Django que usa dos bases de datos diferentes. Uno es el local, vamos a llamarlo, "Django", una base de datos que almacena todas las tablas estándar de una instalación bastante estándar (autenticación, sitios, comentarios, etc.) más algunas tablas adicionales.
La mayoría de los datos, incluidos los usuarios, provienen de una base de datos en otro servidor, llamémosla la base de datos "Legacy".
Estoy buscando sugerencias sobre formas limpias y pitónicas de conectar las dos bases de datos, particularmente con respecto a los usuarios.
Estoy usando un modelo de proxy, que funciona muy bien cuando puedo usarlo explícitamente, pero tengo problemas cuando accedo al objeto del usuario como un objeto relacionado (por ejemplo, cuando uso el sistema integrado de comentarios django).
Así es como se ve el código:
models.py : (apunta a la base de datos Django)
from django.db import models
from django.conf import settings
from django.contrib.auth.models import User as AuthUser, UserManager as AuthUserManager, AnonymousUser as AuthAnonymousUser
class UserPerson(models.Model):
user = models.OneToOneField(AuthUser, related_name="person")
person_id = models.PositiveIntegerField(verbose_name=''Legacy ID'')
def __unicode__(self):
return "%s" % self.get_person()
def get_person(self):
if not hasattr(self, ''_person''):
from legacy_models import Person
from utils import get_person_model
Person = get_person_model() or Person
self._person = Person.objects.get(pk=self.person_id)
return self._person
person=property(get_person)
class UserManager(AuthUserManager):
def get_for_id(self, id):
return self.get(person__person_id=id)
def get_for_email(self, email):
try:
person = Person.objects.get(email=email)
return self.get_for_id(person.pk)
except Person.DoesNotExist:
return User.DoesNotExist
def create_user(self, username, email, password=None, *args, **kwargs):
user = super(UserManager,self).create_user(username, email, password, *args, **kwargs)
try:
person_id = Person.objects.get(email=email).pk
userperson, created = UserPerson.objects.get_or_create(user=user, person_id=person_id)
except Person.DoesNotExist:
pass
return user
class AnonymousUser(AuthAnonymousUser):
class Meta:
proxy = True
class User(AuthUser):
class Meta:
proxy=True
def get_profile(self):
"""
Returns the Person record from the legacy database
"""
if not hasattr(self, ''_profile_cache''):
self._profile_cache = UserPerson.objects.get(user=self).person
return self._profile_cache
objects = UserManager()
legacy_models.py : (apunta a la base de datos "Legacy")
class Person(models.Model):
id = models.AutoField(primary_key=True, db_column=''PeopleID'') # Field name made lowercase.
code = models.CharField(max_length=40, blank=True, db_column="person_code", unique=True)
first_name = models.CharField(max_length=50, db_column=''firstName'', blank=True) # Field name made lowercase.
last_name = models.CharField(max_length=50, db_column=''lastName'', blank=True) # Field name made lowercase.
email = models.CharField(max_length=255, blank=True)
def __unicode__(self):
return "%s %s" % (self.first_name, self.last_name)
def get_user(self):
from models import User
if not hasattr(self,''_user''):
self._user = User.objects.get_for_id(self.pk)
return self._user
user = property(get_user)
class Meta:
db_table = u''People''
También he mejorado mi propio middleware, por lo que request.user
es el User
proxy.
El verdadero problema es cuando estoy usando algo que tiene al usuario como un objeto relacionado, particularmente en una plantilla donde tengo incluso menos control.
En la plantilla:
{{ request.user.get_profile }}
{# this works and returns the related Person object for the user #}
{% for comment in comments %} {# retrieved using the built-in comments app %}
{{ comment.user.get_profile }}
{# this throws an error because AUTH_PROFILE_MODULE is not defined by design #}
{% endfor %}
Si no se crea una versión envolvente del sistema de comentarios que utiliza mi modelo de Usuario proxy, ¿hay algo más que pueda hacer?