简要
使用mongoengine、singals实现MySQL和MongoDB的共用。
需求
在不影响原有MySQL表的情况下,加入MongoDB来处理EMQX的用户验证。
代码
模型定义
class MQTTUser(models.Model):
username = models.CharField(max_length=255, db_index=True, null=False, blank=False, unique=True)
password = models.CharField(max_length=255, null=False, blank=False)
salt = models.CharField(max_length=100, null=True, blank=True)
is_superuser = models.BooleanField(default=False)
expired_date = models.DateTimeField(default=timezone.now, null=True)
create_by = models.ForeignKey(User, on_delete=models.CASCADE)
上面的为MYSQL所使用的模型,那现在我们要使用mongoengine定义Document与MYSQL的模型进行同步。
import mongoengine
class MQTTUser_MongoModel(mongoengine.Document):
username = mongoengine.StringField(max_length=255)
password = mongoengine.StringField(max_length=255)
salt = mongoengine.StringField(max_length=100)
is_superuser = mongoengine.BooleanField(default=False)
created = mongoengine.DateTimeField()
meta ={
"collection": "mqtt_user"
}
类名定义随意,我习惯性后面加上下划线进行分类,meta中的collection为集合名称,如果不定义集合名称,它自动生成的是根据类名大写来的,如:m_q_t_t_user_mongo_model ,建议自定义好类名。
连接
原有settings中存在MySQL引擎的连接。
mongo的连接
定义好两个模型后,我们需要先加入mongo的连接定义,在Django的配置文件数据库配置后面加上即可。
...
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': '',
'USER': '',
'PASSWORD': '',
'HOST': '127.0.0.1',
'PORT': '3306',
},
}
from mongoengine import connect
connect(host='mongodb://<username>:<password>@<host>:<port>/<database>?authSource=admin')
connect的参数如下:
- db=None,
- name=None,
- host=None,
- port=None,
- read_preference=READ_PREFERENCE,
- username=None,
- password=None,
- authentication_source=None,
- authentication_mechanism=None,
这里用到host参数,如mongodb://admin:admin@localhost:27017/emqx?authSource=admin 后面的authSource=admin 是必要的,指明mongo的验证集合。
模型之间的连接
我们可以使用Django的信号函数,在MQTTUser 模型创建新纪录后(post_save )调用create_mqtt_user_in_emq 函数,传入实例,在函数中调用实例创建后信息进行Mongo中的创建。
from django.dispatch import receiver
from django.db.models import signals
@receiver(signals.post_save, sender=MQTTUser)
def create_mqtt_user_in_emq(sender, instance, created, **kwargs):
if created:
MQTTUser_MongoModel.objects.create(
username=instance.username,
password=instance.password,
salt=instance.salt,
is_superuser=instance.is_superuser,
created=instance.created,
)
|