将用户主键改为UUID后出现bigint与uuid不匹配的Django报错求助
解决将用户表主键改为UUID后出现的类型不匹配问题
1. 修复django_admin_log的user_id类型冲突
内置的django_admin_log表中user_id字段默认是bigint类型,和你的UUID主键不兼容,提供两种解决方案:
方案一:直接修改数据库字段(适合已上线项目)
- 如果你用PostgreSQL,执行SQL修改字段类型:
ALTER TABLE django_admin_log ALTER COLUMN user_id TYPE uuid USING user_id::uuid;
- 如果你用MySQL,改成
CHAR(36)(MySQL无原生UUID类型):
ALTER TABLE django_admin_log MODIFY COLUMN user_id CHAR(36) NULL;
注意:操作前务必备份数据库,若原有
django_admin_log中有旧数据,要确认数据转换的兼容性,必要时可清空日志表。
方案二:自定义AdminLog模型(适合新项目或可重构场景)
- 在你的业务app中创建自定义日志模型:
from django.contrib.admin.models import LogEntryManager, DELETION from django.db import models from django.contrib.contenttypes.models import ContentType from django.utils.translation import gettext_lazy as _ from your_app.models import User # 替换成你的用户模型 class CustomAdminLog(models.Model): action_time = models.DateTimeField(_('action time'), auto_now_add=True) user = models.ForeignKey( User, on_delete=models.CASCADE, verbose_name=_('user'), null=True, ) content_type = models.ForeignKey( ContentType, on_delete=models.SET_NULL, verbose_name=_('content type'), null=True, blank=True, ) object_id = models.TextField(_('object id'), blank=True, null=True) object_repr = models.CharField(_('object repr'), max_length=200) action_flag = models.PositiveSmallIntegerField(_('action flag')) change_message = models.TextField(_('change message'), blank=True) objects = LogEntryManager() class Meta: verbose_name = _('log entry') verbose_name_plural = _('log entries') ordering = ('-action_time',) def __str__(self): return f"{self.user} {self.get_action_flag_display()} {self.object_repr}" def is_addition(self): return self.action_flag == LogEntryManager.ADDITION def is_change(self): return self.action_flag == LogEntryManager.CHANGE def is_deletion(self): return self.action_flag == DELETION
- 在
settings.py中配置替换默认模型:
ADMIN_LOG_ENTRY_MODEL = 'your_app.CustomAdminLog'
- 生成并执行迁移:
python manage.py makemigrations python manage.py migrate
2. 适配oauth2_provider的Token模型
oauth2_provider默认的AccessToken和RefreshToken表中user_id也是bigint,同样需要适配:
方案一:直接修改数据库字段
- PostgreSQL执行:
ALTER TABLE oauth2_provider_accesstoken ALTER COLUMN user_id TYPE uuid USING user_id::uuid; ALTER TABLE oauth2_provider_refreshtoken ALTER COLUMN user_id TYPE uuid USING user_id::uuid;
- MySQL执行:
ALTER TABLE oauth2_provider_accesstoken MODIFY COLUMN user_id CHAR(36) NULL; ALTER TABLE oauth2_provider_refreshtoken MODIFY COLUMN user_id CHAR(36) NULL;
方案二:自定义Token模型
- 在业务app中创建自定义模型:
from oauth2_provider.models import AbstractAccessToken, AbstractRefreshToken from django.db import models from your_app.models import User class CustomAccessToken(AbstractAccessToken): user = models.ForeignKey( User, on_delete=models.CASCADE, blank=True, null=True, related_name="oauth2_access_tokens" ) class CustomRefreshToken(AbstractRefreshToken): user = models.ForeignKey( User, on_delete=models.CASCADE, blank=True, null=True, related_name="oauth2_refresh_tokens" )
- 在
settings.py中配置:
OAUTH2_PROVIDER = { 'ACCESS_TOKEN_MODEL': 'your_app.CustomAccessToken', 'REFRESH_TOKEN_MODEL': 'your_app.CustomRefreshToken', }
- 生成并执行迁移:
python manage.py makemigrations python manage.py migrate
3. 确保/login和/register API正常工作
- 检查用户模型,确保UUID主键自动生成:
import uuid from django.db import models class User(models.Model): id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False) # 其他字段...
- 验证登录注册视图逻辑,确保创建用户时主键正确生成,OAuth2认证环节用UUID格式查询用户,避免类型转换错误。
- 测试接口,确认返回的Token中关联的
user_id是UUID格式,无类型匹配报错。
内容的提问来源于stack exchange,提问作者user14948875
相关产品推荐
相关产品推荐

