Django后台代码质量改善建议集锦(一)

2018 年 11 月 21 日 Python程序员

“写代码”技术的提高有两个阶段:第一个阶段是让代码能实现功能、并且少出错;第二个阶段是让代码更易于理解、潜在问题更少。


第一个阶段要怎么做是非常清晰的,功能能实现,调用接口有合适的数据返回,就算完成了任务。到了第二阶段,“应该怎么做”这个问题就变得隐晦了,变得更加没有标准答案了,因为每个人对“易于理解”这个要求的理解是不同的。虽然没有标准答案,但是答案大纲还是有的,有一些规律或要求是被大多数人认可的。


本篇,我们就试着梳理一些“隐晦”的共识,让在第二阶段的读者多一盏路灯。


1、定义Model类时,以一行数据的含义命名


举个例子来说明这个问题:假设我们需要定义一张数据表,这张数据表中的每一行是A校期末考试中一名学生的成绩,那么这张数据表本身就是A校期末考试的总成绩单。这时我们需要为这个数据表写一个Model类,那么这个Model类的名字应该是StudentScore(一个学生的成绩),还是ScoreReport(学校成绩单)呢?


答案应该是StudentScore。为什么用StudentScore更合理呢?让我们看一下我们通常是如何使用这个类的。


比如当我们想新建一条数据的时候,我们会这样写:

这段代码,即便是不懂Python的人来看,也可以大致猜出,这是在为张良创建一条学生成绩记录,并保存到数据库。如果我们当初将Model命名为ScoreReport,代码就变成了这样:

这段代码,看的人会有这样的困惑:创建了一个成绩单,里面写入了一个学生的成绩,那这个成绩单是只有一个学生的成绩吗?如果有第二个学生,需要再创建一个成绩单吗?还是report这个对象有一些方法,可以再添加第二个学生?


可以看出,命名为ScoreReport会给代码阅读者带来很多困惑,不如命名为StudentScore表意清晰。在调用delete方法时这个表意的差别更加明显,score.delete()很清楚地表达了删除的是一个学生的成绩,如果用report.delete(),读者很容易误解为把整个成绩单都删除了。


所以,给Model类取名字的时候要依据一行数据的含义命名,而不是依据整张表的含义命名。


用相似的思维方法,我们还可以得出一个结论,就是“给Model类取名字的时候要用单数,而不是复数。”为什么这样?大家可以自己思考一下。

2、变量命名单复数一定要分清


这个其实是PEP8标准中要求的一部分,这里单独拿出来说,是因为很多同学主要靠工具来完成PEP8的格式化,而工具是不会为你纠正这个命名问题的。


Python由于其动态性,编辑器往往没法告诉你某个变量是什么类型,这实际上增加了代码阅读者理解代码数据结构的难度,也对Python变量的命名提出了更为苛刻的要求。


举个例子,我们在Django中经常需要查询某表的很多行,然后遍历这些行,对它们依次进行一些操作,一个比较典型的代码是这样的:

这里有几个要点:

  1. 通过Model.objects.filter(...)这个句式得到的是多行的一种集合。所以这个句式的结果变量应该用复数。

  2. 因为集合变量名用了复数,在for循环中就不必动脑筋再想一个临时变量了,直接将复数变单数作为临时变量名。

  3. 这样的命名方式也很容易可以看出score和scores之间是什么样的关系。


但是有些同学不注意变量的单复数,经常会写出这样的代码:

这样的代码,让阅读者搞不清楚score到底是一个成绩还是多个成绩?obj和score是什么关系?如果相同函数中还有另外一个查询,要如何命名?叫obj2?总体来说,歧义太多,让人困惑。


即便是前面一种比较好的命名方式,小编也认为仍有改进的空间,比如可以把scores改叫score_queryset。这样改更加突出了这个变量的类型,是一个QuerySet,这样也可以提醒编码者,这个变量是不能JSON化的,是不能直接通过HttpResponse返回的。


3、尽量少用null=True


很多新手分不清blank=True和null=True有什么区别,导致胡乱使用,这里我们解释一下:

  1. blank=True表示该字段在代码层面可不可以不传值,如果blank=False(默认情况),但是通过Model创建对象时却没有给该字段赋值,Django会报错。

  2. null=True表示该字段在数据库层面可不可以不传值,如果null=False(默认情况),写入数据库时该字段没有赋值,或者赋值为None,则数据库会报错。


那为什么说要尽量少用null=True呢?是因为数据库表的一列中只要有一个null值,那么这一列的索引都会失效。null会导致数据库查询性能的大幅下降。


我们再反过来想,当你用了blank=True或者null=True的时候,你实际上想表达什么意思?你想的是这个字段可以不传值。而我们知道数据库中的一列无论你传不传值,本质上都是有值的,只不过这个值可能是null。而由于null会导致索引失效,所以我们希望在你不传值的时候,数据库中写入的值最好不要是null。那么想到这里,你就会意识到,你应该自己设置一个默认值。所以当你想写blank=True,null=True的时候,其实你更应该写blank=True, default=XXX。这样,当你不传值的时候,数据库中存储的是一个你意料中特殊值。如果当前定义的这个字段是整数,那么这个特殊值经常是0;如果当前定义的这个字段是字符串,那么这个特殊值经常是“”(空字符串)。无论如何,不是null就好。


当然,也不是没有例外。ForeignKey字段如果允许不填值,blank=True并且null=True是可以接受的。因为虽然ForeignKey底层本质上是一个整数,但是这个整数如果你填写非正整数,Django在取值的时候会报错。所以不得已地,这里可以用下null=True。(自我安慰一下,ForeignKey里需要null=True的场景还是不太多、比较少)



今天先总结到这里,未完待续~~ 如果你也有什么想说的,欢迎在下方留言哦。

登录查看更多
0

相关内容

Django 是用 Python 语言写的开源 Web 开发框架,它鼓励快速开发,并遵循 MVC 设计和 BSD 版权。Django 根据比利时的爵士音乐家 Django Reinhardt 命名。
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
192+阅读 · 2020年6月29日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【资源】100+本免费数据科学书
专知会员服务
107+阅读 · 2020年3月17日
《代码整洁之道》:5大基本要点
专知会员服务
49+阅读 · 2020年3月3日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
179+阅读 · 2020年1月1日
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
深度 | 推荐系统评估
AI100
24+阅读 · 2019年3月16日
已删除
将门创投
18+阅读 · 2019年2月18日
程序猿的终极噩梦,祖传代码,一动,修半年!
九章算法
4+阅读 · 2018年12月20日
拆台BigGan:“失败”图像生成集锦
论智
5+阅读 · 2018年11月19日
教你用机器学习匹配导师 !(附代码)
数据派THU
3+阅读 · 2018年5月17日
干货:10 种机器学习算法的要点(附 Python代码)
全球人工智能
4+阅读 · 2018年1月5日
Attend More Times for Image Captioning
Arxiv
6+阅读 · 2018年12月8日
Doubly Attentive Transformer Machine Translation
Arxiv
4+阅读 · 2018年7月30日
Arxiv
3+阅读 · 2018年3月21日
Arxiv
5+阅读 · 2017年7月23日
VIP会员
相关VIP内容
【实用书】学习用Python编写代码进行数据分析,103页pdf
专知会员服务
192+阅读 · 2020年6月29日
【干货书】流畅Python,766页pdf,中英文版
专知会员服务
224+阅读 · 2020年3月22日
【资源】100+本免费数据科学书
专知会员服务
107+阅读 · 2020年3月17日
《代码整洁之道》:5大基本要点
专知会员服务
49+阅读 · 2020年3月3日
Transformer文本分类代码
专知会员服务
116+阅读 · 2020年2月3日
【书籍推荐】简洁的Python编程(Clean Python),附274页pdf
专知会员服务
179+阅读 · 2020年1月1日
相关资讯
在K8S上运行Kafka合适吗?会遇到哪些陷阱?
DBAplus社群
9+阅读 · 2019年9月4日
深度 | 推荐系统评估
AI100
24+阅读 · 2019年3月16日
已删除
将门创投
18+阅读 · 2019年2月18日
程序猿的终极噩梦,祖传代码,一动,修半年!
九章算法
4+阅读 · 2018年12月20日
拆台BigGan:“失败”图像生成集锦
论智
5+阅读 · 2018年11月19日
教你用机器学习匹配导师 !(附代码)
数据派THU
3+阅读 · 2018年5月17日
干货:10 种机器学习算法的要点(附 Python代码)
全球人工智能
4+阅读 · 2018年1月5日
Top
微信扫码咨询专知VIP会员