Django是一个优秀的Python web框架,被众多python开发者所喜爱。新开这个Django专栏,并不是从零开始详细使用Django框架来开发web网页,而是用来开发api。前后分离是当前的技术栈潮流

1.Django基础知识
2.初识drf
3.创建程序并初始化模型
4.model.py模块
5.urls.py模块

1.Django基础知识

Django搭建web页面的知识,我在GitHub上已经写过了,若想了解搭建网站,请移步👉👉👉Django搭建网站知识基础

首先,我们需要了解三种开发模式:

  • MVT(model,view,templates)模式:Django
  • MVC(model,view,controller)模式:php
  • MVVM(model,view,view—model)模式:vue

django是典行的mvt模式,前后分离,后端给前段返回json数据,所以我们编写API时仅需要考虑model层,view层,抛弃template层。

2. 初识drf

  1. 安装restful框架
script
1
pip3 install djangorestframework
  1. 使用
  • 注册app(rest_framework本质上也是一个APP,也需要注册)
1
2
3
4
5
6
7
8
9
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'rest_framework'
]
  • 写路由
1
2
3
4
5
6
7
from django.conf.urls import url
from django.contrib import admin
from . import views

urlpatterns = [
url(r'^drf/info/', views.DrfInfoView.as_view()),
]
  • 写视图
1
2
3
4
5
6
7
8
9
10
11
12
13
from rest_framework.views import APIView
from rest_framework.response import Response

class DrfInfoView(APIView):

def get(self,request,*args,**kwargs):
data = [
{'id': 1, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 2, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 3, 'title': '震惊了...王阳居然...', 'content': '...'},
{'id': 4, 'title': '震惊了...王阳居然...', 'content': '...'},
]
return Response(data)
  1. DRF的应用场景

以后在公司参与前后端分离项目、参与为app写接口时,用drf会比较方便。

  • restful规范
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
- URL中一般用名词: 
http://www.luffycity.com/article/ (面向资源编程,网络上东西都视为资源)
- 根据请求不同做不同操作:GET/POST/PUT/DELETE/PATCH
- 筛选条件,在URL参数中进行传递:
http://www.luffycity.com/article/?page=1&category=1

一般传输的数据格式都是JSON


1. 建议用https代替http
2. 在URL中体现api,添加api标识
https://www.cnblogs.com/xwgblog/p/11812244.html # 错误
https://www.cnblogs.com/api/xwgblog/p/11812244.html # 正确
https://api.cnblogs.com/xwgblog/p/11812244.html # 正确

建议:https://www.cnblogs.com/api/...
3. 在URL中要体现版本
https://www.cnblogs.com/api/v1/userinfo/
https://www.cnblogs.com/api/v2/userinfo/
4. 一般情况下对于api接口,用名词不用动词。
https://www.cnblogs.com/api/v1/userinfo/
5. 如果有条件的话,在URL后面进行传递。
https://www.cnblogs.com/api/v1/userinfo/?page=1&category=2
6. 根据method不同做不同操作
get/post/put/patch/delete
  • drf框架

不基于drf也可以实现restful规范来开发接口程序。
使用了drf之后,可以快速帮我们开发restful规范来开发接口。

3. 创建程序并初始化模型

DRF引入了一个扩展Django常规 HttpRequest 对象的 Request 对象,并提供了更灵活的请求 解析能力。 Request 对象的核心功能是 request.data 属性,它与 request.POST 类似,但 对于使用Web API更为有用。

1
2
request.POST  # 只处理表单数据  只适用于'POST'方法
request.data # 处理任意数据 适用于'POST','PUT'和'PATCH'等方法,是字典型

rest_framework框架默认传输数据格式为x-www-urlencoded,并不是通常的json
在DRF中,请始终使用 request.data ,不要使用 request.POST

4. model.py模块

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


# Create your models here.
class Category(models.Model):
"""
文章分类表
verbose_name 代表别名
"""
name = models.CharField(verbose_name="分类", max_length=32)
objects = models.Manager()


class Article(models.Model):
"""
文章明细表
"""
title = models.CharField(verbose_name="标题", max_length=32)
summary = models.CharField(verbose_name="简介", max_length=255)
content = models.TextField(verbose_name="内容")
category = models.ForeignKey(verbose_name="分类", to="Category", on_delete=models.CASCADE)
objects = models.Manager()

关于objects的说明:

objects : 管理器对象,Manager类型的对象,定义在from django.db import models中,用于模型对象和数据库交互,是默认自动生成的属性,但是可以自定义管理器对象

自定义管理器对象:例如 books= models.Manager(),一旦自定义管理器对象,默认的objects 就不再自动生成

表字段类型及说明

表字段 描述
models.AutoField 默认会生成一个名为id的字段并未int类型
models.CharField 字符串类型
models.BooleanField 布尔类型
models.ComaSeparatedIntegerField 用逗号分隔的整数类型
models.DateField 日期(Date)类型,生成 年月日 e.g., 2020-06-10
models.DateTimeField 日期(datetime)类型,生成年月日是分秒 e.g., 2020-06-10 16:31:00
models.DecimalField 十进制小数类型
models.EmailField 字符串类型(正则表达式邮箱)
models.FloatField 浮点类型
models.IntegerField 整数类型
models.BigIntegerField 长整数类型
models.IPAddressField 字符串类型(IPV4正则表达式)
models.GenericIPAddressField 字符串类型,参数protocol可以是: both,IPv4 和ipv6,验证IP地址
models.NullBooleanField 允许为空的布尔类型
models.PositivelntegerField 正整数的整数类型
models.PositiveSmallIntegerField 小正整数类型
models.SlugField 包含字母、数字、下曲线和连字符的字符串, 常用于URL
models.SmaIlIntegerField 小整数类型, 取值范围C -32,768—+32,767 )
models.TextField 长文本类型
models.TimeField 时间类型, 显东时分秒HH:MM[:ss[ .uuuuuu]]
models.URLField 字符串, 地址为正则表达式
models.BinaryField 二进制数据类型
- -
表字段参数及说明 参数说明
Null 如为True,字段是否可以为空
Blank 如为True,设置添加数据时可以允许空值
Default 设置默认值
primary_key 如为True,将字段设置成主键
db_column 设置数据库中的字段名称
Unique 如为True,将字段设置成唯一属性,默认为False
db_index 如为True,为字段添加数据库索引,索引知识点
verbose_name 设置字段的显示名称,别名
related_name 关联对象反向引用描述符,用于多表查询,可解决一个数据表有两个外键同时指向另一个数据表而出现重名的问题

拓:

  1. 关于model的表字段说明
  • auto_now,默认值为false,设置为true时,每次执行 save 操作时,将其值设置为当前时间,并且每次修改model,都会自动更新。
    注意:设置该参数为true时,并不意味着字段的默认值设为当前时间,而是指字段会被“强制”更新到当前时间,你无法程序中手动为字段赋值;如果使用django自带的admin管理器,那么该字段在admin中是只读的。

使用场景:该属性通常被用在存储“创建时间”的场景下。

  • auto_now_add,默认值为false,设置为true时,会在model对象第一次被创建时,将字段的值设置为创建时的时间,以后修改对象时,字段的值不会再更新。一旦被设置为True,就无法在程序中手动为字段赋值,在admin中字段也会成为只读的。
  1. null与blank的区别
  • null:如果为True,表示允许为空,默认值是False
  • blank:如果为True,则该字段允许为空白,默认值是False
  • 对比:null是数据库范畴的概念,blank是表单验证证范畴的
  1. 表结构设计
  • 不会经常变化的值放在内存:choices形式,避免跨表性能低
1
2
3
4
5
6
7
8
9
choices形式
category_choices = (
(1,'咨询'),
(2,'公司动态'),
(3,'分享'),
(4,'答疑'),
(5,'其他')
)
category = models.IntegerField(verbose_name='分类',choices=category_choices)

choices用于页面上的选择框标签,需要先提供一个二维的二元元组,第一个元素表示存在数据库内真实的值第二个表示页面上显示的具体内容。在浏览器页面上将显示第二个元素的值。

解决方案:https://blog.csdn.net/qq_41854273/article/details/84987899

1
2
3
4
5
6
7
8
9
# 序列化文件
class BrandSerializer(serializers.ModelSerializer):
etype = serializers.SerializerMethodField()
class Meta:
model = Brand
fields = "__all__"

def get_etype(self,obj):
return obj.get_etype_display()
  • 分表:如果表中列太多/大量内容可以选择水平分表
  • 表自关联

关系模型

关系型数据库的关系包括三种类型

  • ForeignKey:一对多,将字段定义在多的一端中。
  • ManyToManyField:多对多,将字段定义在任意一端中。
  • OneToOneField:一对一,将字段定义在任意一端中

外键(ForeignKey)和一对一(OneToOneField)的参数中可以看出,都有on_delete参数,而 django 升级到2.X之后,表与表之间关联的时候,必须要写on_delete参数,否则会报异常

举例:一对多关系

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from django.db import models
class ServerInfo(models.Model):
server_hostname = models.CharField(max_length=20, default=None)
server_intranet_ip = models.CharField(max_length=20, default=None)
server_internet_ip = models.CharField(max_length=20, default=None)
server_shelves_date = models.DateField(auto_now_add=True) # 数据加入时间
update_time = models.DateTimeField(auto_now=True) # 数据更新时间
is_delete = models.BooleanField(default=False) # 逻辑删除
objects = models.Manager()

class MiddlewareInfo(models.Model):
name = models.CharField(max_length=20)
port = models.IntegerField()
server = models.ForeignKey('ServerInfo',on_delete=models.CASCADE, default=None)
shelves_date = models.DateTimeField(auto_now_add=True) # 数据加入时间
update_time = models.DateTimeField(auto_now=True) # 数据更新时间
is_delete = models.BooleanField(default=False) # 逻辑删除
objects = models.Manager()
  • 关于objects的说明

object是模型属性—用于模型对象和数据库交互。
objects = Manager() 是管理器类型的对象 ,是Model和数据库进行查询的接口.

假如不设置管理器对象,在进行数据库查询,更新时就会报错

1
2
3
queryset = Article.objects.all()
article_object = Article.objects.filter(id=pk).first()
Article.objects.filter(id=pk).delete()

5. urls.py模块

关于路由url,path,re_path的说明

在新版本Django2.x中,url的路由表示用path和re_path代替,
模块的导入由django1.x版本的 from django.conf.urls import url,include
变成现在的Django2.x中的 from django.urls import path, re_path, include

path中不能有正则表达式,不然会找不到页面,此时可以使用re_path

path(‘delete/(\d+)’, views.delete), # 删除点击的图书,path中有正则,找不到页面
使用re_path可以解决这个情况
re_path(‘delete/(\d+)’, views.delete), # 删除点击的图书

举例说明

urls.py模块

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from django.conf.urls import url
from django.contrib import admin
from . import views
urlpatterns = [
# 管理员后台
url(r'^admin/', admin.site.urls),
# as_view()是将类作为view
url(r'^info/', views.InfoView.as_view()),
url(r'^drf/info/', views.DrfInfoView.as_view()),
url(r'^drf/category/', views.DrfCategoryView.as_view()),
# 获取一条数据
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),

]
  • 接口:实现访问接口时,创建一个文章类型
1
2
3
4
5
6
7
8
9
10
from rest_framework.views import APIView
from rest_framework.response import Response
from . import Category, Article

class DrfCategoryView(APIView):

def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
Category.objects.create(**request.data)
return Response('成功')
  • 接口:获取所有文章类型
1
2
3
4
5
6
7
8
9
10
11
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类"""
queryset = Category.objects.all().values('id','name')
data_list = list(queryset)
return Response(data_list)

def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
Category.objects.create(**request.data)
return Response('成功')
  • 接口:获取一条文章类型的详细信息
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
from api import models
from django.forms.models import model_to_dict
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类/单个文章分类"""
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all().values('id','name')
data_list = list(queryset)
return Response(data_list)
else:
category_object = models.Category.objects.filter(id=pk).first()
data = model_to_dict(category_object)
return Response(data)

def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
models.Category.objects.create(**request.data)
return Response('成功')
  • 接口:文章分类的更新和删除
1
2
3
4
5
6
7
from django.conf.urls import url
from django.contrib import admin
from api import views
urlpatterns = [
url(r'^drf/category/$', views.DrfCategoryView.as_view()),
url(r'^drf/category/(?P<pk>\d+)/$', views.DrfCategoryView.as_view()),
]

views.py模块

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
from api import models
from django.forms.models import model_to_dict
class DrfCategoryView(APIView):
def get(self,request,*args,**kwargs):
"""获取所有文章分类/单个文章分类"""
pk = kwargs.get('pk')
if not pk:
queryset = models.Category.objects.all().values('id','name')
data_list = list(queryset)
return Response(data_list)
else:
category_object = models.Category.objects.filter(id=pk).first()
data = model_to_dict(category_object)
return Response(data)

def post(self,request,*args,**kwargs):
"""增加一条分类信息"""
models.Category.objects.create(**request.data)
return Response('成功')

def delete(self,request,*args,**kwargs):
"""删除"""
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).delete()
return Response('删除成功')

def put(self,request,*args,**kwargs):
"""更新"""
pk = kwargs.get('pk')
models.Category.objects.filter(id=pk).update(**request.data)
return Response('更新成功')

 评论

联系我 | Contact with me

Copyright © 2019-2020 谁知你知我,我知你知深。此恨经年深,比情度日久

博客内容遵循 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 协议