4

2つの異なるデータベースを使用するDjangoサイトを作成しました。 1つはローカルですが、かなり標準的なインストール(認証、サイト、コメントなど)からすべての標準テーブルを格納するデータベースである "Django"と、さらにいくつかの追加テーブルがあります。Djangoの非常に異なるデータベース間の「外部キー」

ユーザーを含むほとんどのデータは、別のサーバーのデータベースから取得されます。これを「レガシー」データベースとしましょう。

私は2つのデータベースを接続するきれいな、pythonicの方法について、ユーザーに関して特にを探しています。

プロキシモデルを使用していますが、明示的に使用すると効果的ですが、私は関連オブジェクトとしてユーザーオブジェクトにアクセスしているときに問題に遭遇します(たとえば、組み込みのdjangoコメントシステム)。ここで

は、コードは次のようになります。

models.py:(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:( "レガシー" のデータベースへのポイント)

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' 

私も自分のミドルウェアを手に入れたので、request.userはprですオキシUserオブジェクトも。

実際の問題は、ユーザーが関連オブジェクトとして使用しているものを使用している場合です。特に、私が管理しにくいテンプレートでは特にそうです。テンプレートで

:代わりに私のプロキシ・ユーザー・モデルを使用して、コメントシステムの包まれたバージョンを作成する

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

ショート、私にできること何かはありますか?

答えて

3

私はそれをどのように解決しましたか?私は、Userプロキシの使用をやめました。

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 

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' 

最後に、settings.pyで:

AUTH_PROFILE_MODULE = 'myauth.LegacyPerson' 

これは簡単な解決策ですが、少なくとも機能します!レガシーレコードが必要なときはいつでもuser_profileに電話しなければならないということです。これは、各ユーザーレコードに対して追加のクエリがあることを意味しますが、これは公正なトレードオフです。なぜなら、クロスチェックは頻繁に。

関連する問題