早前的一篇文章Django开发密码管理表实例有写我们写了个密码管理工具来实现对密码的管理,当时加密解密的功能在view层实现,一直运行稳定所以也没有过多关注实现是否优雅的问题。最近要多加几个密码表再次回头看之前的代码发现加解密在view层实现较为繁琐,尤其是使用了Sadmin公共库之后view的代码简洁了很多,若再在view层处理显然不够优雅,是时候用更优雅的方式来实现了

Sadmin增删改查

对数据库表的增删改查是开发过程中最常用到的功能,之前的文章也介绍过我们通过封装Sadmin公共库用最为简洁的代码实现了对表的增删改查操作,具体有多简洁,看下边的代码

class TableList(ListCreateView):
model = Table
template = 'password/table.html'
permission = {'get': 'password.select_table', 'post': 'password.create_table'} class TableDetail(RetrieveUpdateDestroyView):
model = Table
permission = {'get': 'password.select_table', 'put': 'password.update_table',
'delete': 'password.delete_table'}

TableList类可以实现对表的查询以及新建表数据,TableDetail可以实现对表内单条数据的查询、修改和删除,对应了两条URL

path('table/', views.TableList.as_view(), name='table-list-url'),
path('table/<int:pk>/', views.TableDetail.as_view(), name='table-detail-url'),

如果在view层实现表字段的加密的话,那就要重写TableList的post方法,以及TableDetail类的put方法,非常麻烦,那有什么更为优雅的方法呢?对表字段的处理最好能在表发生变化的时候来处理,直接在model层来实现显然要比view更合适,model层来实现的话通过Django的signals或是重写model的save方法都是不错的选择

至于究竟是用signals还是重写save方法,两者都可以实现,个人觉得对于简单的处理逻辑采用重写save的方式比较好,而对于复杂的处理逻辑采用signals更清晰,而对于我们这个对字段进行加密的需求,逻辑简单代码也不需要太多,直接采用重写save的方式就好了

重写model的save方法

对于加密解密的核心代码可以参考文章Django开发密码管理表实例给出的源码,重写model的save方法代码如下

class Table(models.Model):
username = models.CharField(max_length=64, verbose_name='用户名')
password = models.CharField(max_length=512, verbose_name='密码') def __str__(self):
return self.application_name def save(self, *args, **kwargs):
_encrypt = True if self.pk:
old_password = Table.objects.get(id=self.id)
_encrypt = False if old_password.password == self.password else True if _encrypt:
_m = RsaCrypto().encrypt(self.password)
if _m.get('state'):
self.password = _m.get('message')
else:
raise Exception('加密失败:' + _m.get('message')) super(Table, self).save(*args, **kwargs)

对于密码加密,通常会在首次新加记录,以及更新记录密码发生变化的情况下进行

每当save时如何判断是insert还是update呢?可以通过是否存在self.pk来判断,Django的model必须有一个字段为主键,如果用户没有设置主键字段,那么Django会默认创建一个名为id的字段作主键,主键也用pk别名来表示,所以可以通过self.pk是否存在来判断本次save究竟是insert还是update

当本次save为update时,我们也需要判断密码字段是否发生了变化,如果没有变化则不需要调用加密方法,判断字段是否变化就需要获取字段提交前的值,提交前的值可以通过Table.objects.get(id=self.id)来获取

有了以上这些信息,那加密就水到渠成了。我们优雅的实现了字段的加密,那对于解密呢?个人觉得同样放在model里比写在veiw里更合适,可以在mdel里加个decode_password的方法

class Table(models.Model):
... def decode_password(self):
_m = RsaCrypto().decrypt(self.password)
if _m.get('state'):
return {
'state': 1,
'message': _m.get('message'),
'username': self.username
}
else:
return {'state': 0, 'message': 'Error: ' + _m.get('message')}

需要解密时调用Model的decode_password方法就可以了

def decode_password(request, pk):
try:
_t = Table.objects.get(id=pk)
return JsonResponse(_t.decode_password())
except Exception as e:
return JsonResponse({'state': 0, 'message': 'Error: ' + str(e)})

写在最后

个人对代码有一点洁癖,实现功能也以简单实用为主,能2行搞定的绝对不会写3行,能有更优的解法就会毫不犹豫去重构,同时也坚决反对“又不是不能用”的说法。对于以上实现是否优雅,或是有更好的解决方法,欢迎讨论

Django Model字段加密的优雅实现的更多相关文章

  1. Django model字段类型清单

    转载:<Django model字段类型清单> Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField ...

  2. Django model 字段类型清单

    Django model字段类型清单 Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField 一个自动递增的整型字 ...

  3. Django model 字段类型及选项解析---转载

    model field 类型1.AutoField() 自增的IntegerField,通常不用自己设置,若没有设置主键,Django会自动添加它为主键字段,Django会自动给每张表添加一个自增的p ...

  4. Django——model字段类型 2

    Django 通过models实现数据库的创建.修改.删除等操作,Django中model作为数据资源指定了字段以及一些相应的功能,通常每个model对应数据库中的一张表,(每个model都是从dja ...

  5. Django model 字段类型及选项解析

    字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...

  6. Django model 字段详解

    字段类型选择: AutoField(Field) - int自增列,必须填入参数 primary_key=True BigAutoField(AutoField) - bigint自增列,必须填入参数 ...

  7. Django model字段类型(转)

    AutoField     一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.(参阅 _自 ...

  8. django进行model字段的自定义

    相信大家一定有web应用被攻击的经历,数据库安全是一个网站的必须课.django有很好的orm,但sql注入,或其他方式的攻击都是无法完全屏蔽的. 所以一般数据库都会对用户数据,如text类型的数据进 ...

  9. Django使用Signals监测model字段变化发送通知

    上一篇文章<运维效率之数据迁移自动化>中讲到了工单通知,本文将介绍工单通知实现过程中的一些小技巧.所有演示均基于Django2.0 阅读此篇文章你可以: 解锁一个python if的使用新 ...

随机推荐

  1. Python之pyyaml模块

    pyyaml模块在python中用于处理yaml格式数据,主要使用yaml.safe_dump().yaml.safe_load()函数将python值和yaml格式数据相互转换.当然也存在yaml. ...

  2. 解析Prometheus PromQL

    解析PromQL 目前对Prometheus 的promQL 的解析文章比较少,且Prometheus官方也没有提供一个公共的库来对齐进行解析.下面实现对promQL的解析,并实现注入label功能. ...

  3. Java环境搭建与HelloWprld—改变世界的第一步

    1. JDK下载 访问oracle官网:http://www.oracle.com 在首页点击Downloads,进入oracle软件下载页. 在下载页面,点击Java. 选择Java (JDK) f ...

  4. AtCoder Regular Contest 069 D - Menagerie 枚举起点 模拟递推

    arc069.contest.atcoder.jp/tasks/arc069_b 题意:一堆不明身份的动物排成一圈,身份可能是羊或狼,羊一定说实话,狼一定说假话.大家各自报自己的两边是同类还是不同类, ...

  5. php安装imagick扩展

    下面/usr/local/php5是php的安装目录 安装imagickcd /usr/local/srcwget http://pecl.php.net/get/imagick-3.0.1.tgz  ...

  6. Java基础系列(15)- 用户交互Scanner

    Scanner对象 之前我们学的基本语法中我们并没有实现程序和人的交互,但是Java给我们提供了这样一个工具类,我们可以获取用户的输入.java.util.Scanner是Java5的新特征.我们可以 ...

  7. Linux系列(33)- rpm命令管理之RPM包校验提取(5)

    校验 格式 rpm -V 已安装的包名 选项: - -V:校验指定RPM包中的文件(verify) 例子 rpm -V httpd 后, 无任何提示, 代表该文件没有被做任何修改 # 判断本地的apa ...

  8. Oracle Haip无法启动问题学习

    一.目标:Oracle Haip 启动报错 需求:日常运维过程中,已经遇到两次由于HAIP引发的问题,特此进行记录. 本次问题是看着大佬-李海清操作,整完了记录一下,上一次HAIP折腾了4个小时. O ...

  9. mysql 不常用的存储引擎

    csv 数据文件可以编辑;每一列不能为空,不支持索引:文件保存数据,cat可以查看数据;用处:数据交换中间表--excel表导入数据等; Archive 对表数据进行压缩,磁盘i/o减少:节省空间;只 ...

  10. 怎么让jenkins保持后台运行

    今天在腾讯云直接使用命令启动jenkins,java -jar jenkins.war --httpPort=8080,这样启动关掉shell窗口或退回shell窗口,进程就会结束,需要重新 启动,非 ...