django项目总结 | django基础
创建Django项目
配置数据库
在
settings.py
里的DATABASES
里配置数据库1
2
3
4
5
6
7
8
9# 定义数据库配置
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql', # 使用MySQL作为数据库引擎
'NAME': 'movie', # 数据库名称为movie
'USER': 'root', # 数据库用户名为root
'PASSWORD': '123456' # 数据库密码为123456
}
}使用PyMySQL来替代MySQL,并在配置文件中movie/init.py文件中设置
1
2
3
4
5# 导入PyMySQL模块
import pymysql
# 将PyMySQL模块安装为MySQLdb的别名,以便在Django项目中使用MySQL数据库
pymysql.install_as_MySQLdb()在vscode终端输入命令来安装PyMySQL
1
pip install pymysql
安装完PyMySQL后,再次执行迁移文件命令,将数据库应用到数据表中
执行完,django项目所应用到的数据表会出现在navicat中1
2python manage.py makemigrations
python manage.py migrate
启动django项目
- 执行命令启动服务
1
python manage.py runserver
- 在浏览器地址中输入:
http://127.0.0.1:8000/
查看项目效果
django后台
- 输入:
127.0.0.1:8000/admin
入到后台的登录页面 - 通过命令来创建管理员用户
1
python manage.py createsuperuser
创建电影应用
创建应用
使用命令来创建movie应用
1 | python manage.py startapp movie |
编写模型
在movie/models.py文件中来编写模型
- 项目中需要用到电影的分类,这些分类主要包含了电影、综艺、纪录片、短片,所以要创建一个category类
1
2
3
4
5
6
7
8
9
10
11
12
13
14from django.db import models
class Category(models.Model):
# 分类信息
id = models.AutoField(primary_key=True) # 自增主键字段
category_name = models.CharField(max_length=100, verbose_name='分类名') # 分类名字段,最大长度为100
class Meta:
db_table = u'category' # 数据库表名
verbose_name = '分类管理' # 在Admin后台显示的单个对象的名称
verbose_name_plural = '分类管理' # 在Admin后台显示的对象列表的名称
def __str__(self):
return self.category_name # 返回对象的字符串表示形式,即分类名 - 还需要电影的信息,所以在movie/models.py文件中来继续创建一个movie类
这个电影下面的字段比较多,包括id、电影名称、上映年份、导演、编剧、主演等等。
- 地区是写死的,用一个region表示。
- 另外,还有一个字段是Hot,表示是否为热门,是否为置顶,它们都是布尔值。
- 还有一个可选项是quality,表示视频质量。
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
71
72
73
74
75
76
77
78
79from django.db import models
# 地区选项
Region = [
(1, '中国大陆'),
(2, '中国香港'),
(3, '中国台湾'),
(4, '美国'),
(5, '韩国'),
(6, '日本'),
(7, '其他')
]
# 清晰度选项
Quality = [
(1, '720P'),
(2, '1080P'),
(3, '4K')
]
# 热门精选选项
Hot = [
(False, '否'),
(True, '是')
]
# 置顶选项
Top = [
(False, '否'),
(True, '是')
]
# 是否限制选项
SHOW = [
(False, '否'),
(True, '是')
]
# 是否免费选项
FREE = [
(False, '否'),
(True, '是')
]
class Category(models.Model):
# 分类信息
class Movie(models.Model):
# 电影信息
id = models.AutoField(primary_key=True) # 自增主键
movie_name = models.CharField(max_length=100, verbose_name='电影名') # 电影名
release_year = models.IntegerField(verbose_name='上映年份') # 上映年份
director = models.CharField(max_length=100, verbose_name='导演') # 导演
scriptwriter = models.CharField(max_length=100, verbose_name='编剧') # 编剧
actors = models.CharField(max_length=200, verbose_name='主演') # 主演
region = models.SmallIntegerField(choices=Region, verbose_name='地区') # 地区
types = models.CharField(max_length=50, verbose_name='类型') # 类型
language = models.CharField(max_length=100, verbose_name='语言') # 语言
release_date = models.DateField(verbose_name='上映日期') # 上映日期
duration = models.CharField(max_length=50, verbose_name='时长(或集数)') # 时长(或集数)
alternate_name = models.CharField(max_length=100, blank=True, verbose_name='又名') # 又名,可选
image_url = models.CharField(max_length=300, blank=True, verbose_name='图片链接') # 图片链接,可选
rate = models.FloatField(blank=True, verbose_name='豆瓣评分') # 豆瓣评分,可选
review = models.TextField(max_length=500, blank=True, verbose_name='简介') # 简介,可选
is_hot = models.BooleanField(choices=Hot, default=False, verbose_name='是否热门') # 是否热门
is_top = models.BooleanField(choices=Top, default=False, verbose_name='是否置顶') # 是否置顶
quality = models.SmallIntegerField(choices=Quality, blank=False, verbose_name='清晰度') # 清晰度
subtitle = models.CharField(max_length=100, blank=True, verbose_name='字幕') # 字幕,可选
update_info = models.CharField(max_length=100, blank=True, verbose_name='更新信息') # 更新信息,可选
update_progress = models.CharField(max_length=100, blank=True, verbose_name='更新进度') # 更新进度,可选
download_info = models.TextField(max_length=500, blank=True, verbose_name='网盘信息',
help_text="每个网盘信息占一行,每个字段用网盘名:网址 提取码:字符 组成(无提取码不写)。 如 百度网盘:http://www.baidu.com 提取码:8888 ") # 网盘信息,可选
is_show = models.BooleanField(choices=SHOW, default=True, verbose_name='是否显示') # 是否显示
is_free = models.BooleanField(choices=FREE, default=False, verbose_name='是否免费') # 是否免费
category = models.ForeignKey(Category, blank=False, verbose_name='分类名', on_delete=models.CASCADE) # 分类名,外键
class Meta:
db_table = 'movie' # 数据库表名
verbose_name = '电影管理' # 在Admin后台显示的单个对象的名称
verbose_name_plural = '电影管理' # 在Admin后台显示的对象列表的名称
def __str__(self):
return self.movie_name # 返回对象的字符串表示形式,即电影名
配置应用
在settings.py文件中找打INSTALLED APPS代码块,把movie应用加上去
1 | INSTALLED_APPS = [ |
执行迁移操作来生成数据表
1 | python manage.py makemigrations |
在admin.py里将模型里的类注册到后台上
1 | from django.contrib import admin |
启动项目,在后台可以进行增删改查操作,比如添加分类和电影等等
1 | python manage.py runserver |
创建接口
restful API
以前编写接口时,缺乏规范性,从而诞生了一套接口规范,符合这套规范的API被称为”restful API”。
在rest中定义了四个主要方法:GET用于获取资源,POST用于新建资源,PUT用于更新资源,DELETE用于删除资源。
为什么要使用restful API呢?
在前后端分离的项目中,后端与数据库打交道并对数据进行读取,前后端之间通常选择一种通用的数据格式,如JSON格式数据。
后端读取数据库后以JSON形式展示数据(后端也有页面的),前端通过请求后端接口获取JSON数据并展示在页面上,这是前后端分离的核心思想。
传统方式创建接口
配置URL
在全局配置文件中找到urls.py文件中的urlpatterns代码块,然后添加一个路由,命名为API/movie,并使用include引入movie.urls。1
2
3
4
5
6
7
8
9
10
11
12
13
14# 从Django中导入必要的模块
from django.contrib import admin
from django.urls import path, include
# 为项目定义URL模式
urlpatterns = [
# 管理员站点URL
path('admin/', admin.site.urls),
# 用于电影相关端点的URL模式
# 当请求以'aip/movie/'开头时,将重定向到'movie.urls'的URL配置。
# 'namespace'参数用于通过为包含的URL配置中定义的URL名称添加前缀来区分URL。
path('aip/movie/', include('movie.urls', namespace='movie')),
]在movie文件夹下创建一个urls.py文件。在这个文件中,写上路由,模仿刚才的代码形式。
首先,导入模型,代码如下:1
2
3
4
5
6
7
8
9
10
11
12# 从Django中导入路径函数和views模块
from django.urls import path
from movie import views
# 设置应用程序名称
app_name = 'movie'
# 定义URL模式列表
urlpatterns = [
# 对根路径的视图MovieList进行映射,并命名为'list'
path('', views.MovieList.as_view(), name='list'),
]接下来在movie文件下的views.py文件中创建movie list函数:
1
2
3
4
5
6
7
8
9
10
11
12
13
14# 从Django中导入render和JsonResponse函数
from django.shortcuts import render
from django.http import JsonResponse
# 从models模块中导入Movie模型
from .models import Movie
def movie_list(request):
# 获取所有电影数据
movies = Movie.objects.all().values_list()
# 将数据转换为列表形式
data = list(movies)
# 返回JSON响应
return JsonResponse(data, safe=False)启动服务,在浏览器地址栏输入ulr
127.0.0.1:8000/aip/movie/
,此时浏览器页面就以列表显示了JSON格式数据
如果想返回一个数据,例如电影信息,可以自定义“data”字典,以包含特定的细节,如电影名称、上映日期和评分。无论输出什么内容,都取决于后台传递的数据。
1 | # 从Django中导入render和JsonResponse函数 |
DRF方式创建接口
DRF 即 Django REST Framework
在使用DRF的时候,要创建一个序列化器,所谓的序列化器就是实现将Python转化为JSON格式数据。
在这个转化的过程中,可以加一些验证,比如说用户输入的一些信息,可以对它进行验证。
- 在movie文件夹应用中创建一个文件,叫做
serializers.py
。 - 接着从rest_framework中导入serializers。
- 创建一个序列化器,定一个类叫做MovieListSerializer,让它继承serializer类。
1 | # 从rest_framework模块中导入序列化器基类 |
接下来,就可以在movie文件夹下的views.py视图文件中导入这个序列化器。
1 | # 从Django中导入render和JsonResponse函数 |
重新启动一下服务,再访问127.0.0.1:8000/api/movie/这个接口,就获取到了所有的电影的数据,包含了两个,一个是ID,一个是movie。
在使用这个DRF的时候,重点是创建这么一个
serializers.py
,把所有的需要序列化的内容全部放到这个文件中,然后对字段进行相应的处理。这就是一个最简单的DRF的实例。
使用ModelSerializer简化代码
由于字段比较多,在serializers.py里一个一个写的话,会非常麻烦。而在models.py文件中,同样创建了ID、电影名称等多个字段。
Model Serializer这个类的作用就是可以将模型中定义的字段类型转化为serializer中的字段类型。并且在内部进行了模型字段到序列化器字段的映射。通过使用ModelSerializer类,可以省去一个个定义字段的步骤,让它自动匹配模型中的字段。这样可以使代码更简洁,不需要手动定义每个字段的序列化过程。
在movie/serializers.py文件中修改代码让MovieListSerializer继承的是Model Serializer类。使用这个类以后,让它自动从模型中去匹配。
1 | # 从rest_framework模块中导入序列化器基类 |
这样的话,的接口就会显示全部字段。
如果只选择需要的字段,可以使用一个列表,将所有需要序列化的字段全部填写到这里。
1 | # 从rest_framework模块中导入序列化器基类 |
再刷新浏览器页面,这次只显示4个字段
类的视图
DRF提供了多种方式来支持类的视图。DRF要提供这么多方式,考虑到了灵活性和便利性。
不同的情况可能需要不同的解决方式,但大多数操作都涉及到基本的增删改查功能。
即使模型不同,操作方式也基本相同,只需稍作调整。因此,DRF提供了多种方式来满足不同需求。
使用APIView实现
创建一个新的电影详情页。
在movie/views.py中,首先从rest_framework中导入views,然后导入APIView。
接着,创建一个类,命名为MovieDetail,并让它继承APIView。
接下来,实现增删改查操作方式。这些操作方式包括GET、POST、PUT、DELETE等方法。
首先,实现获取电影详情的方法,使用GET请求。
在这个方法中,需要获取请求对象,并根据电影的ID来获取对应的电影详情。如果电影不存在,则返回404错误。修改代码如下:
1 | # 从Django中导入render函数 |
接下来,使用序列化将电影信息返回给前端。
最后,在movie/serializers.py文件中定义一个MovieDetailSerializer来对电影详情进行序列化。
1 | # 导入rest_framework中的serializers模块 |
接下来,在URL中定义该路由。
- 在movie/urls.py文件中来进行定义,这个路由是有一些特殊的,它是在基础URL的基础上加上了一个数字ID,这个数字是可变的,所以不能写死。可以使用
int:pk
来定义这个参数。 - 然后,在视图中将使用MovieDetail类,并将其转化为可以执行的视图对象。同时,给它起一个别名
Detail
。
1 | # 导入django.urls中的path函数 |
接下来,将修改电影信息的功能添加到接口中。
在movie/views.py中使用PUT方法来进行修改,同样需要指定一个ID来确定要修改的电影。
- 首先,判断电影是否存在,如果不存在则报错。
- 然后,使用序列化器对用户提交的数据进行验证。
- 验证通过后,进行提交操作。
1 | # 从Django中导入render函数 |
同样的流程适用于删除功能,使用DELETE方法来删除电影信息。同样需要指定一个ID来确定要删除的电影。
- 首先判断电影是否存在,存在则进行删除操作,然后返回相应的响应码。
1 | # 从Django中导入render函数 |
综上实现了查看、修改和删除功能,使用了继承自APIView的视图类,并创建了不同的方法来实现不同的功能。这是操作视图的一种方式,即继承APIView类。
使用通用的视图实现
对于数据的增长改查,可以说是每个项目的通用操作。如果有多个模型,每个都这么写get、put、delete,那是非常麻烦的,也体现不出DRF(Django REST Framework)它的优势。所以可以把一些相同的操作提取出来,可以把核心的内容给它提取出去,然后创建一个单独的类。
在movie/views.py文件中来新建一个 MovieDetail 类。在原始数据中还需要对模型进行各种操作,增删改查。
这个时候需要引入一个新的类,这个类叫做 mixins 也是复合类。它可以对模型的各种操作,所以对模型操作直接导入这个 Mixins里面的已经写好类就可以执行这样的操作了。
1 | # 从Django中导入render函数 |
上面的这些方法可以再进行简化。
在movie/views.py文件中来来修改,在generics.py中寻找能够替代这些操作的类。发现有RetrieveUpdateDestroyAPIView这个类,它相当于刚才继承了一系列类的情况。因为它的父类已经实现了这些操作,可以直接导入这个类,而无需再单独实现这些方法。这样操作后,代码量显著减少,但功能依然完整。
1 | # 从Django中导入render函数 |
在postman中,尝试使用put方法来修改电影信息,当点击提交后,报错了,提示错误信息是电影的其他字段必须填写。
引入的是RetrieveUpdateDestroyAPIView这个类,找到这个源码发现它这里要是提交更改部分信息使用的是patch方法。
所以试一下把put修改为patch,点击send,这一次就修改成功了,这也是put和patch这两种方式的区别。
当有不同的需求的时候,比如说要更改整个电影信息的话那么就使用put方法,如果只需要更改部分就使用patch方法。
如果想要修改MovieList方法,也可以采取相同的方法。
- 首先注册这个视图,然后创建一个新的类来继承ListCreateAPIView,因为ListCreateAPIView已经包含了列表和新增的功能。
- 接着只需要定义QuerySet和SerializerClass,就完成了对该接口的定义。
这种方式使得只需简单地选择合适的类名进行继承,而无需再手动编写大量代码。
1 | # 从Django中导入render函数 |
接下来再来测试这个接口能不能实现,回到postman中,找查看电影列表,点击发送,服务器已经断开了,解决这个错误需要修改一下url,把movie_list改成MovieList,找到movie/urls.py文件,来修改代码
1 | # 导入 Django 中的路径模块和 movie 应用中的视图模块 |
综上使用了DRF中的通用视图类,通过继承相应的类,实现了各种接口功能。DRF的便利之处在于,只需定义少量代码,就能够实现完整的接口规范,包括列表查看、新增、修改和删除等功能。
使用视图集实现
称其为视图集是因为它将一系列操作进行了集合处理,包括列表展示、新增数据、查看详情、修改信息、删除等。可以将这些操作看作是一个集合,而视图集的作用就是将它们整合在一起。
实际上,对于REST接口来说,只是在操作一个接口,即/api/moive,对电影进行各种操作。视图集的作用就是将这些功能整合在一起。
新定义一个视图集,命名为MovieViewSet。让它继承DRF提供的ModelViewSet,并导入相应的模块。
1 | # 从Django中导入render函数 |
在queryset 中使用了之前的查询对象,即Movie.objects.all。
在serializer_class 中,新定义了一个MovieSerializer,用于对电影进行序列化。这个MovieSerializer同样继承了DRF提供的ModelSerializer。
接下来在movie /serializers.py文件中来修改代码:
1 | # 导入 REST Framework 中的序列化模块和 movie 应用中的电影模型 |
接下来定义路由。
在全局的URL配置中,使用了DRF提供的DefaultRouter。这样,就可以通过路由注册的方式将接口注册到全局路由中。这样的话,在创建新的路由时,只需在全局路由下进行添加,而访问API后面的对应接口时,就会自动使用include进行包含。
在urls.py文件中修改代码如下:
1 | # 导入 Django 中的管理模块、路径模块和包含默认路由器的 REST Framework 模块 |
最后,将原始的movie/urls.py文件内容全部注释掉,因为通过视图集的方式,DRF会按照其规则将所有电影的增删改查操作自动进行路由注册。
总的来说,视图集的最大优势在于最大程度地减少了所需的代码量,使能够专注于API的交互和表现形式,甚至可以忽略URL的细节。然而,由于抽象程度较高,一些需要定制化的需求可能需要特殊处理。在选择使用views、genericviews还是viewsets时,可以根据实际情况进行选择。