django开发之规范和细节

·django开发之规范和细节

  1. 编码规范
  2. 项目准备
  3. model层字段介绍

编码规范

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
Beautiful is better than ugly.
Explicit is better than implicit.
Simple is better than complex.
Complex is better than complicated.
Flat is better than nested.
Sparse is better than dense.
Readability counts.
Special cases aren't special enough to break the rules.
Although practicality beats purity.
Errors should never pass silently.
Unless explicitly silenced.
In the face of ambiguity, refuse the temptation to guess.
There should be one-- and preferably only one --obvious way to do it.
Although that way may not be obvious at first unless you're Dutch.
Now is better than never.
Although never is often better than *right* now.
If the implementation is hard to explain, it's a bad idea.
If the implementation is easy to explain, it may be a good idea.
Namespaces are one honking great idea -- let's do more of those!
  1. 适当的缩进
  2. 优选空格
  3. 适当的长度

项目准备

构建虚拟环境

在某盘某个目录下执行命令:

1
python -m venv typeidea-env

激活环境

1
2
3
4
D:\Envs\typeidea-env>cd Scripts
D:\Envs\typeidea-env\Scripts>activate.bat
## 在其目录下安装django
pip install Django==1.11

image-20210219121703646

构建项目

1
2
3
4
(typeidea-env) D:\Envs\typeidea-env\Scripts>cd ..
(typeidea-env) D:\Envs\typeidea-env>mkdir typeidea
(typeidea-env) D:\Envs\typeidea-env>cd typeidea
(typeidea-env) D:\Envs\typeidea-env\typeidea>django-admin startproject typeidea

关于项目依赖

1
2
##启动项目 报错参考https://www.pianshen.com/article/82141167778/
python manage.py runserver

image-20210219142756301

拆分setting适应不同的环境

构建settings文件夹.目录结构如下image-20210219143352146

注意:base.py基于外部的settings.py文件

image-20210219143858599

新增develop配置文件如上图所示,最后修改manage.py和wsgi.py识别新的配置文件

1
2
3
## os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djwwj.settings")
profile = os.environ.get('TYPEIDEA_PROFILE','develop')
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "djwwj.settings.%s" % profile)

并且设置一个环境变量 TYPEIDEA_PROFILE = develop
vscode设置django参考

编写model层代码

image-20210219150221092

在django中有一个app应用的概念。每个app应该是一个自组织的应用。可以根据model的业务性质分别进行处理

根据上面的规划:model可以划分blog相关,配置相关,评论相关

构建blog App

执行命令

1
(typeidea-env) D:\Envs\typeidea-env\typeidea\djwwj>manage.py startapp blog

image-20210219151124987

blog相关的model分类大概有种类,标签以及帖子,构建的model如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
from django.db import models

# user来源自django自带的认证中
form django.contrib.auth.models import User
# Create your models here.
# 种类类
class Category(models.Model):
# 状态申明
STATUS_NORMAL = 1
STATUS_DELETE = 0
STATUS_ITEMS = (
(STATUS_NORMAL,'正常'),
(STATUS_DELETE,'删除')
)

# 字段申明
name = models.CharField(max_length=50, verbose_name='名称')
# 正整数或0类型 PositiveIntegerField
status = models.PositiveIntegerField(default=STATUS_NORMAL,choices=STATUS_ITEMS, verbose_name='状态')
is_nav = models.BooleanField(default=False, verbose_name='是否为导航')
# 外键表明的是多对一 参考文章:https://blog.csdn.net/hpu_yly_bj/article/details/78939748
owner = models.ForeignKey(User, verbose_name='作者')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

# 每个类都有一个源类型可以配置
class Meta:
verbose_name = verbose_name_plural = '分类'
# 标签类
class Tag(models.Model):
# 状态申明
STATUS_NORMAL = 1
STATUS_DELETE = 0
STATUS_ITEMS = (
(STATUS_NORMAL,'正常'),
(STATUS_DELETE,'删除')
)
# 字段申明
name = models.CharField(max_length=10, verbose_name='名称')
status = models.PositiveIntegerField(default=STATUS_NORMAL,choices=STATUS_ITEMS, verbose_name='状态')
owner = models.ForeignKey(User, verbose_name='作者')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

class Meta:
verbose_name = verbose_name_plural = '标签'

# 帖子
class Post(models.Model):
# 状态申明
STATUS_NORMAL = 1
STATUS_DELETE = 0
STATUS_ITEMS = (
(STATUS_NORMAL,'正常'),
(STATUS_DELETE,'删除')
)

# 字段申明
title = models.CharField(max_length=255 , verbose_name='标题')
desc = models.CharField(max_length=1024, verbose_name='摘要')
content = models.TextField(verbose_name='正文' help_text='正文必须为Markdown格式')
status = models.PositiveIntegerField(default=STATUS_NORMAL,choices=STATUS_ITEMS, verbose_name='状态')
category = models.ForeignKey(Category, verbose_name='分类')
# 一个帖子对应多个标签,一个标签对应多个帖子
tag = models.ManyToManyField(Tag, verbose_name='标签')
owner = models.ForeignKey(User, verbose_name='作者')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

class Meta:
verbose_name = verbose_name_plural = '文章'
# 排序可以参考 https://blog.csdn.net/old_man31/article/details/86377988
ordering = ['-id'] # 根据id进行降序排序

注意:上面总体构建的步骤就是规划模型—–>设计模型——>构建模型

构建config App

同理我们构建配置选项,model里面主要是连接和侧边栏

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
from django.db import models
from django.contrib.auth.models import User

# Create your models here.
# 连接类
class Link(models.Model):
# 状态申明
STATUS_NORMAL = 1
STATUS_DELETE = 0
STATUS_ITEMS = (
(STATUS_NORMAL,'正常'),
(STATUS_DELETE,'删除')
)

# 字段申明
title = models.CharField(max_length=50, verbose_name='标题')
href = models.URLField(verbose_name='链接')
status = models.PositiveIntegerField(default=STATUS_NORMAL,choices=STATUS_ITEMS, verbose_name='状态')
weight = models.PositiveIntegerField(default=1,
choices=zip(range(1,6),range(1,6)),
verbose_name='权重',
help_text='权重高展示顺序靠前')
owner =models.ForeignKey(User, verbose_name='作者')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

class class Meta:
verbose_name = verbose_name_plural = '友链'

# 侧边栏
class SideBar(models.Model):
STATUS_SHOW = 1
STATUS_HIDE = 0
STATUS_ITEMS = (
(STATUS_SHOW, '展示'),
(STATUS_HIDE, '隐藏')
)
SIDE_TYPE = (
(1, 'HTML'),
(2, '最新文章'),
(3, '最热文章'),
(4, '最热评论')
)

# 申明字段
title = models.CharField(max_length=50, verbose_name='标题')
display_type = models.PositiveIntegerField(default=1, choices=SIDE_TYPE, verbose_name='展示类型')
content = models.CharField(max_length=500, blank=True, verbose_name='内容', help_text='设置不为HTML类型,可为空')
status = models.PositiveIntegerField(default=STATUS_SHOW, choices=STATUS_ITEMS, verbose_name='状态')
owner = models.ForeignKey(User, verbose_name='作者')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

class class Meta:
verbose_name = verbose_name_plural = '侧边栏'

构建comment App

在这里暂时将评论和文章耦合起来。当然以后可以独立出来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from django.db import models

# 和文章耦合起来
from blog.models import Post
# Create your models here.

#评论类
class Comment(models.Model):
# 状态申明
STATUS_NORMAL = 1
STATUS_DELETE = 0
STATUS_ITEMS = (
(STATUS_NORMAL,'正常'),
(STATUS_DELETE,'删除')
)

# 申明字段
target = models.ForeignKey(Post, verbose_name='评论目标')
content = models.CharField(max_length=2000, verbose_name='内容')
nickname = models.CharField(max_length=50, verbose_name='昵称')
website = models.URLField(verbose_name= '网站')
email = models.EmailField(verbose_name= '邮箱')
status = models.PositiveIntegerField(default=STATUS_NORMAL, choices=STATUS_ITEMS, verbose_name='状态')
create_time = models.DateTimeField(auto_now_add=True, verbose_name='创建时间')

class class Meta:
verbose_name = verbose_name_plural = '评论'

到此3个model类型构建完毕。还有值得修改的地方

一系列流程

在installedapps添加 文件在bast.py

1
2
3
4
5
6
7
8
9
10
11
INSTALLED_APPS = [
'blog',
'config',
'comment',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]

在djwwj目录下执行数据库迁移的操作

1
2
3
4
5
manage.py makemigrations
manage.py migrate
# sqlite3如果看不到,可以参考https://blog.csdn.net/foryouslgme/article/details/52034149
# 可以将文件放到djwwj目录下来查看
manage.py dbshell

image-20210220130938034

model层说明

常用的字段类型

数值型

1.AutoField 自增主键,可以被重写

2.BooleanField 布尔类型字段,一般记录状态标记

3.DecimalField decima 数据精度比较高的字段。注意需要在python中使用Decimal类型进行转换

4.IntegerField 整数字段,不自增

5.PostiveIntegerField 只包含正整数

6.SmallIntegerField smallint 小整数

字符型

1.CharField 基础的varchar类型

2.UrlField 对url的特殊处理

3.UUIDField 存放唯一id

4.EmailField 对email的处理

5.FileField 对文件的特殊处理,在admin展示可以自动生成一个上传文件的按钮

6.TextField 存放正文类容

7.ImageField 处理图片相关的数据

日期类型

分别为DateField 和 DateTimeField 以及 TimeField 就不在细说了

关系类型

ForeignKey 多对一 OneToOneField 一对一 以及 ManyToManyField 多对多

1
# 可以参考文章https://www.cnblogs.com/navysummer/p/10200154.html

字段参数类型

1.null 空类型

2.blank 不能为空

3.choices可选项

4.db_column对应数据库字段类型

5.db_index 索引配置

6.default 默认配置

7.editable 是否可编辑

8.error_messages 检查异常是提示

9.help_text 字段提示语

10.primary_key 主键设置

11.unique 唯一约束

12.unique_for_data/month/year 可以针对日期,月和年的约束

13.verbose_name 字段展示相应的文案

14.validators 自定义逻辑校验

QuerySet的使用

QuerySet的主要作用是数据库的所有查询以及有更新的交互都是需要这个来完成的

在model层中django提供了一个objects属性来提供数据操作的接口。并且支持链式操作,同时queryset是懒加载的

常用的接口

支持链式调用

1.all接口等于查询所有

2.filter接口根据条件过滤数据

3.exclude根据条件排除之外,和filter相反

4.reverse接口 结果倒序

5.distinct 去重查询

6.none接口 返回空

不支持链式调用

1.get接口根据条件进行查询

2.create接口创建一个model对象

3.get_or_create根据条件进行查找,没有就创建

4.update_or_create 根据条件更新没有就创建

5.lastest接口返回最新的记录

6.earliest接口获取第一个记录

7.last接口获取最后一条

8.exists 返回布尔值.判断是否存在

9.bulk_create接口 批量创建记录

10.in_bluk 批量查询

11.update接口 批量更新

12.delete接口 批量删除

13.values接口 明确只需要某个返回字段值,不需要实例时

14 values_list接口 返回的是元组的queryset

进阶接口

defer 不需要的字段做延迟加载,但是在循环查询中会产生N+1,重复查询的问题

only接口 与defer相反

select_related 关联查询 针对一对多 也可以解决N+1的问题

prefetch_related 关联查询 针对多对多的

常用的字段查询

针对QuerySet 方法 filter()exclude()get() 的关键字参数。

contains 包含相似查询

icontains 同上,忽略大小写

exact 精确匹配

in 指定某个集合

gt 大于 gte 大于等于

lt 小于 lte 小于等于

startswith endwith 以什么开始,什么结尾

range 用于时间范围查找

进阶查询

F 用来保证数据避免出现竞争状态 保证数据的原子性

Q 执行and 或者 or 的复杂表达式

聚合运算可以参考文档也可以 使用annotate() 执行更简便的操作

执行原生sql

可以通过raw接口来执行