登录
首页 >  数据库 >  MySQL

Django ORM层日志的两种实现方式

来源:SegmentFault

时间:2023-01-27 17:43:26 407浏览 收藏

本篇文章向大家介绍《Django ORM层日志的两种实现方式》,主要包括MySQL、python、Django,具有一定的参考价值,需要的朋友可以参考一下。

最近开发一个内部的记录系统,其中有一个需求要求将所有数据库操作记录下来,为此想了一些方案.记录一下.

思路演化

这个需求出来的一瞬间我就否定了在业务逻辑层保存操作记录的方案,我认为这样耦合度比较高,成本也太高. 代码也会大量重复.
Django的ORM操作中,删除操作会调用

class TopSecret(models.Model):

    class Meta:
        db_table = "绝密文件"

    name = models.CharField(max_length=32)
    content = models.TextField()

这是原始的model,我改写成了如下

class Logger(models.Model):

    def save(self, *args, **kwargs):
        print("Do some log")
        super(Logger, self).save(*args, **kwargs)


class TopSecret(Logger):

    class Meta:
        db_table = "绝密文件"

    name = models.CharField(max_length=32)
    content = models.TextField()

我觉得这样应该可以的.然而在调用

class Logger(models.Model):

    class Meta:
        abstract = True

    def save(self, *args, **kwargs):
        print("Do some log")
        super(Logger, self).save(*args, **kwargs)


class TopSecret(Logger):

    class Meta:
        db_table = "绝密文件"

    name = models.CharField(max_length=32)
    content = models.TextField()

In [1]: from logged.models import TopSecret

In [2]: obj = TopSecret(name="123",content="测试内容")

In [3]: obj.save()
Do some log

In [4]:

在想起

class Logger(object):

    def save(self, *args, **kwargs):
        print("Do some log")
        models.Model.save(self, *args, **kwargs)


class TopSecret(Logger, models.Model):

    class Meta:
        db_table = "绝密文件"

    name = models.CharField(max_length=32)
    content = models.TextField()

这样做有好处也有坏处,好处是Logger不再继承

def cbd_logger(obj):
    if hasattr(obj, "save"):
        save = obj.save 
        def _save(self, *args, **kwargs):
            print "do some log %s" % self.name
            return save(self, *args, **kwargs)
        setattr(obj, "save", _save)
    return obj


@cbd_logger
class TopSecret(models.Model):

    class Meta:
        db_table = "绝密文件"

    name = models.CharField(max_length=32)
    content = models.TextField()
值得注意的是,_save中不能直接
>>>obj.save()
save 90220624
obj.save 106285376
self.save 106285376
在装饰后的save方法中,
>>>fs = [lambda i:i*2 for i in range(3)]
>>>for f in fs:
...    print(f(1))
2
2
2

总结

类的继承方法和装饰器方法实际上都在做同一件事,就是在框架本身的

save
delete
方法外层增加日志操作.但是需求还没有实现,我们保存日志的时候,不只要知道数据变动,还要知道这些操作是谁做的,如何优雅的将这些信息传递给负责记录的代码?
目前我们选择的是在操作Model时,约定不使用objects,只使用
TopSecret(name="",content="").save(request)
这种方法,将request传递给save,再由之前实现的logger从request取出必要的信息进行记录,比如IP,User,甚至UA等等.这么做业务层需要多传一个参数,还是有了感知,但是也是没办法的事.对现有代码的改动也是我知道的办法中最小的.
这套下来感觉django文档中的给出的信息很充分,实现这个需求并不难.一开始出现的问题还是因为对文档印象不够深,没有第一时间解决问题.

文中关于mysql的知识介绍,希望对你的学习有所帮助!若是受益匪浅,那就动动鼠标收藏这篇《Django ORM层日志的两种实现方式》文章吧,也可关注golang学习网公众号了解相关技术文章。

声明:本文转载于:SegmentFault 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>
评论列表