tutorial primary form foreign fields create django proxy multiple-databases user-profile django-authentication

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?