You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从PHP迁移至Django,能否实现MySQL AES加密并兼容ORM与迁移?

如何在Django中复现PHP的AES_ENCRYPT/DECRYPT逻辑并保留ORM核心特性

完全可以实现,且能完整保留Django ORM、数据迁移等核心功能,核心思路是自定义字段类型,在字段的读写环节对接MySQL的AES加密函数,具体实现步骤如下:

一、自定义加密字段

基于Django的BinaryField扩展,重写字段的入库和出库逻辑,自动调用MySQL的AES_ENCRYPT和AES_DECRYPT函数:

# myapp/fields.py
from django.db import models
from django.conf import settings

class AESEncryptedField(models.BinaryField):
    def get_prep_value(self, value):
        # 入库时调用AES_ENCRYPT加密
        if value is None:
            return None
        # 使用配置中的密钥,必须和PHP端完全一致
        return models.functions.AESEncrypt(value, settings.AES_ENCRYPTION_KEY)
    
    def from_db_value(self, value, expression, connection):
        # 出库时调用AES_DECRYPT解密,转成字符串返回
        if value is None:
            return None
        decrypted = models.functions.AESDecrypt(value, settings.AES_ENCRYPTION_KEY)
        return decrypted.decode('utf-8') if decrypted else None
    
    def to_python(self, value):
        # 处理表单提交等场景的类型转换
        if isinstance(value, str):
            return value
        return super().to_python(value)

二、在模型中使用自定义字段

直接替换原有的CharField等类型,用自定义字段映射加密列:

# myapp/models.py
from django.db import models
from .fields import AESEncryptedField

class User(models.Model):
    id = models.AutoField(primary_key=True)
    username = AESEncryptedField(max_length=255)
    email = AESEncryptedField(max_length=255)
    
    def __str__(self):
        return self.username

三、配置加密密钥

在settings.py中添加密钥,确保和PHP端使用的密钥完全一致:

# settings.py
AES_ENCRYPTION_KEY = "你的加密密钥"

四、关键注意事项

  • 字段类型兼容:PHP中AES_ENCRYPT返回二进制数据,因此Django字段基于BinaryField,迁移时会自动创建对应数据库列(若迁移现有数据,需确保原列是BLOB或VARBINARY类型)。
  • 加密字段查询:若需基于加密字段过滤,不能直接用常规查询,需结合annotate和AESDecrypt函数:
    from django.db.models.functions import AESDecrypt
    from django.conf import settings
    
    # 过滤邮箱为user@example.com的用户
    users = User.objects.annotate(
        decrypted_email=AESDecrypt('email', settings.AES_ENCRYPTION_KEY)
    ).filter(decrypted_email='user@example.com')
    
  • 字符集一致性:确保MySQL数据库字符集与PHP端一致(如utf8mb4),避免解密后出现乱码。

五、数据迁移

Django迁移系统会自动识别自定义字段,执行python manage.py makemigrations和python manage.py migrate即可完成表结构创建/更新。若迁移现有加密数据,直接将原表二进制数据导入对应列即可,无需额外处理。

内容的提问来源于stack exchange,提问作者Elex Promise

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 23:55:08