共享PostgreSQL数据库的两个Django项目共享自定义User模型最佳实践
Django跨项目关联外部User模型的最佳实践
方法1:直接声明外部User模型(推荐同数据库/跨数据库共享场景)
通过在第二个项目中声明与第一个项目完全匹配的User模型,同时告知Django不管理该模型的迁移,避免伪造迁移的问题。
步骤1:配置数据库连接
如果两个项目共用同一个PostgreSQL数据库,直接沿用默认配置即可;如果User数据存放在单独的数据库,在第二个项目的settings.py中添加对应数据库配置:
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'your_main_db', 'USER': 'db_user', 'PASSWORD': 'db_password', 'HOST': 'localhost', 'PORT': '5432', }, 'user_db': { 'ENGINE': 'django.db.backends.postgresql', 'NAME': 'user_auth_db', 'USER': 'db_user', 'PASSWORD': 'db_password', 'HOST': 'localhost', 'PORT': '5432', } }
步骤2:创建匹配的RemoteUser模型
在第二个项目的任意app(比如新建shared_users app)中,创建与第一个项目完全一致的User模型,关键是设置managed=False让Django不生成迁移:
from django.db import models from django.contrib.auth.models import AbstractBaseUser, PermissionsMixin class RemoteUser(AbstractBaseUser, PermissionsMixin): # 完全复制第一个项目自定义User的所有字段 email = models.EmailField(unique=True) username = models.CharField(max_length=150, unique=True) is_active = models.BooleanField(default=True) is_staff = models.BooleanField(default=False) date_joined = models.DateTimeField(auto_now_add=True) # 同步第一个项目的USERNAME_FIELD和REQUIRED_FIELDS USERNAME_FIELD = 'email' REQUIRED_FIELDS = ['username'] class Meta: # 必须与第一个项目User表的表名完全一致(格式通常为`appname_modelname`) db_table = 'auth_app_user' # 核心设置:禁止Django为该模型创建/管理迁移 managed = False # 如果User在单独数据库,指定数据库别名 db = 'user_db'
步骤3:关联RemoteUser到Car模型
在第二个项目的Car模型中,直接关联上述RemoteUser:
from django.db import models from shared_users.models import RemoteUser class Car(models.Model): # 同数据库可保留db_constraint,跨数据库需设置为False(因为跨库无法创建外键约束) owner = models.ForeignKey(RemoteUser, on_delete=models.CASCADE, db_constraint=False) make = models.CharField(max_length=50) model = models.CharField(max_length=50)
方法2:API调用关联(适合微服务解耦场景)
如果两个项目是独立微服务,更推荐通过API交互而非直接数据库关联,实现完全解耦:
- 第一个项目提供User查询、验证的API接口
- 第二个项目的Car模型仅存储User的ID,通过API获取用户信息:
from django.db import models class Car(models.Model): owner_id = models.IntegerField() make = models.CharField(max_length=50) model = models.CharField(max_length=50) # 自定义方法获取用户详情 def get_owner_info(self): import requests # 调用第一个项目的用户API resp = requests.get(f'http://user-service/api/users/{self.owner_id}/') return resp.json() if resp.status_code == 200 else None
这种方式需要处理API异常、添加缓存优化,适合完全独立的服务架构。
关键注意事项
- 方法1中,RemoteUser模型必须与第一个项目的User表结构完全同步,字段类型、长度、约束都要一致,否则会出现查询错误
- 跨数据库场景下,无法使用
select_related这类ORM关联查询,需手动查询用户数据 - 若第一个项目的User模型更新,第二个项目的RemoteUser必须同步修改
内容的提问来源于stack exchange,提问作者McMazalf
相关产品推荐
相关产品推荐

