Question

J'ai écrit un site Django qui utilise deux bases de données différentes. L'un est local, nous allons appeler de lui, « Django », base de données qui stocke toutes les tables standards d'une jolie installation standard - auth, les sites, les commentaires, etc. -. Et quelques tables supplémentaires

La plupart des données, y compris les utilisateurs, vient d'une base de données sur un autre serveur, que l'appel de la base de données, il « Legacy ».

Je cherche des suggestions sur les moyens propres, pythonique de relier les deux bases de données, notamment en ce qui concerne les utilisateurs.

J'utilise un modèle proxy, ce qui fonctionne très bien quand je peux l'utiliser de façon explicite, mais que je rencontrerai des problèmes quand j'accéder à l'objet utilisateur comme un objet lié (par exemple, lorsque vous utilisez le django commentaires intégrés système).

Voici ce que l'apparence de code comme:

models.py : (pointe vers la base de données 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 : (points à la base de données "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'

Je l'ai aussi fouetté mon propre middleware, donc request.user est l'objet proxy User également.

Le vrai problème est quand j'utilise quelque chose qui a l'utilisateur comme un objet lié, en particulier dans un modèle où j'ai encore moins de contrôle.

Dans le modèle:

{{ 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 %}

Court de créer une version enveloppée du système de commentaires qui utilise mon proxy modèle de l'utilisateur à la place, il n'y a rien que je puisse faire?

Était-ce utile?

La solution

Voici comment je l'a résolu. Je me suis arrêté en utilisant le proxy de l'utilisateur tout à fait.

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

et 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'

Enfin, settings.py :

AUTH_PROFILE_MODULE = 'myauth.LegacyPerson'

Ceci est une solution plus simple, mais au moins ça marche! Cela signifie que chaque fois que je veux que le dossier de l'héritage que je dois appeler user_profile, et cela signifie qu'il ya une requête supplémentaire pour chaque enregistrement de l'utilisateur, mais c'est un compromis équitable parce qu'en fait, il est peu probable que je vais faire un contrôle qui lui souvent.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top