Foreign keys for very different databases in Django

I am writing a Django site that uses two different databases. One of them is local, let it be called "Django", a database that stores all the standard tables with a fairly standard installation - auth, sites, comments, etc. - plus a few additional tables.

Most of the data, including users, comes from a database on another server, call it the Legacy database.

I am looking for suggestions on clean, Putinโ€™s ways of connecting two databases, especially regarding users.

I use a proxy model that works fine when I can use it explicitly, but I am having problems accessing the user object as a related object (for example, when using the django built-in comments system).

Here is what the code looks like:

models.py : (points to the Django database)

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 to the Legacy database)

 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' 

I also hacked my own middleware, so request.user also a User proxy.

The real problem is that I am using what has the user as a related object, especially in a template where I have even less control.

In the template:

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

With the exception of creating a complete version of the commenting system that uses my User proxy model instead, is there anything else I can do?

+4
source share
1 answer

Here is how I resolved it. I did not use user proxies at all.

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 

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

Finally, in settings.py :

 AUTH_PROFILE_MODULE = 'myauth.LegacyPerson' 

This is a simpler solution, but at least it works! This means that whenever I need an outdated record, I have to call user_profile , which means that for each user report there is an additional request, but this is a fair compromise, because in fact it is unlikely that I will often do cross- verification.

+3
source

Source: https://habr.com/ru/post/1334729/


All Articles