Django(个人推荐, 如果项目较大 需要协同开发, 建议使用django这种重量级框架, 如果类似于纯api的后端应用建议使用 flask, 轻量小巧 , 麻雀虽小五脏俱全)
1.Django是什么
他是一个基于python语言的WEB框架
为什么使用Django
- 他是python中最大的框架集成很多api
- 他是全球第五大框架(代表作豆瓣)
- 适合开发工期短,效率高使用
Django的优势
- 开发效率高,功能强大
通过wsgi模块理解Django的工作集成原理
- 路由分发器通过写一个函数上传一个字典,如果传进来的environment.get('PATH_INFO')在字典中存在,就执行对应的函数,否则返回404f
wsgi是一种规范,wsgiref是基于wsgi规范开发的模块
- 浏览器是socket客户端,网站是socket服务端
- wsgi是一种web server开发的规范,wsgiref实现了这个规范并在其内部实现了socket服务端
- 根据url的不同执行不同的函数 - 路由分发
- 函数 - 处理业务逻辑的进程
- 图案css js文件统一称为静态文件,需要读取内容直接返回给用户浏览器
- 虽然自己写web server比较的麻烦,但是我们也从中了解了web框架的本质
2.创建Django项目
django-admin.py startproject my_site 创建my_site项目
- 创建app django-amdin.py startapp app01
- ├── admin.py 数据库管理后台
├── apps.py django把项目和app 关联起来的一个文件
├── init.py
├── migrations 与数据库相关
│ └── init.py
├── models.py 数据库增删该查操作的文件
├── tests.py 单元测试
└── views.py 业务逻辑函数代码存放的位置 - manage.py # 管理程序的文件,启动和结束等
- my_site #
- init.py
- settings.py # 程序的配置文件 - 数据库配置之类的
- urls.py # 程序的路由系统
- wsgi.py # 指定框架的wsgi
- 创建成功后会有几个默认的文件
- 在my_site大项目下创建app每一个业务线都要有一个app
第一次django请求
- 1.首先匹配路由,查找对应的url对应的关系,找到了就调用返回页面,否则404
- 2.业务函数,执行业务逻辑
- 3.返回数据给浏览器
启动django web服务器 python3 manage.py runserver 0.0.0.0:8000
retrun HttpResponse方法返回我们定义的数据
3.模板初探
- 1.配置settings DIRS
- 2.配置views.py return render(request,'form.html')
- MVC & MTV
- m model 模型 一般对数据库操作,数据的存取 models.py
- v views 视图 决定着如何展示数据 views.py
- c controller 控制器 负责处理用户交互的部分,控制器负责从视图读取数据,控制用户输入,并向模型发送数据. urls.py
Django是一个MTV框架,其框架模板上看起来和传统的MVC架构没有什么太大的区别.
Django将MVC中的视图进一步分解为Django视图和Django模板两个部分
- Django中的html文件就是模板 视图就是views.py
T 就是Templates 数据展示
在Django的MTV框架中MVC C控制器部分由Django框架的urlconf来实现代替
严格来说Django是MVTC C被实现替代了
urls.py文件中 re_path是使用正则匹配用户请求的url 主要配合动态路由
Django路由的匹配心法
Django 在2.0之后使用了新的语法path,不使用re_path
path('articles/<int:arg1>/<month:arg2>/<int:arg3>', views.kw)
str 字符串 除了/ 之外的任何字符串都能匹配
int 匹配任意数字
slug 匹配任意的**-**-**
uuid 匹配uuid格式的,特定场景下才会使用的到
path / + str 可以匹配到/
使用include管理app下的url
在顶级的urls.py文件中导入from django.urls import include
path('app01/',include('app01.urls')),
Django的模型(admin文件的操作)
- views中操作数据库
- 自己写sql语句的问题 - 有sql注入的风险,代码与sql写死在一起了,导致解耦性差,开发人员的sql水平层次不齐,导致性能可能会变差,开发效率低下
4.ORM的引出
ORM是什么?
- 对象关系映射,他的实质就是将关系数据库中的业务数据用对象的形式表示出来,并通过面向对象的方式将这些对象组织起来,实现系统业务逻辑过程
- ORM中最重要的概念就是映射,通过这种映射可以使业务对象与数据库分离,从面向对象来说,数据库不应该和业务逻辑绑定到一起,ORM则起到这样的分离作用,使数据库层透明,开发人员真正的面向对象.
ORM的作用
- 牺牲性能 - 将对象转换成原生的sql
- 复杂语句难以实现
- 实现了代码与数据库操作的解耦
- 不需要自己写原生的sql,提高了开发效率
- 有效的防止了sql注入
- 缺点
ORM映射字段的语法
AutoField (设置自增)
BigAutoField (设置更大的自增)
BigIntegerField (更大的整数)
BinaryField (二进制的数据)
BooleanField (布尔类型的数据)
CharField (字符串类型的数据)
DateField (年与日时间类型)
DataTimeField(精确到时分秒的时间类型)
DecimalField ()
DurationField()
EmailField(邮箱类型)
FileField(存储文件的类型)
FloatField(浮点数类型)
ImageField(图片类型)
IntegerField(整数类型)
GenericIPAddressField(ipv4地址类型)
NullBooleanField (允许boolean类型为空)
TextField(大的文本)
ForeignKey(外键关联)
ManyToManyField(多对多)
OneToOneField(1对1)
将models文件中的类同步到mysql数据库中(必须要注意models文件中的外键和多对多要一一对应)
- 1.生成同步文件 python manage.py makemigrations
- 2.同步数据库 python manage.py migrate
在Django官网找到数据库的配置https://docs.djangoproject.com/en/3.0/ref/settings/#databases 写到settings文件当中
在项目下的init.py文件中写入
import pymysql pymysql.version_info = (1, 3, 13,"final",0) pymysql.install_as_MySQLdb()
创建数据库mysql> create database blogdatabase charset utf8;
在settings文件中设置INSTALLED_APPS 加上app的名字
使用Django数据库的同步工具migrations
使用ORM映射插入数据 首先 python manage.py shell
- 先创建完对象在关联o.tags.set([id,id]) 这是覆盖性设置
- o.tags.add(id,id) 这是添加
普通创建
>>> models.Account.objects.create( >>> ... username = 'jeke', >>> ... email = '123@163.com', >>> ... password = '123', >>> ... )
外键关联创建
>>> o = models.Article( >>> ... title = '我是Peter', >>> ... content = 'xixi', >>> ... pub_data = '2020-6-11') >>> o >>> <Article: Article object (None)> >>> o.account_id = 1 > >>> o.save()
多对多的创建数据
ORM对数据进行查询(后来找到的查询语法https://www.cnblogs.com/ls1997/p/10955402.html)
- models.Account.objects.filter(username__regex=r'(zj|j)$') 以zj或者j结尾
- models.Account.objects.filter(username__iregex=r'(zj|j)$') 加上i就是大小写不敏感都匹配
models.Account.objects.all() ==> select *
models.Account.objects.filter(id=1) ==> select * where id=1
models.Account.objects.filter(id__gt=1) ==> where id > 1
models.Account.objects.filter(id__gt=1,password='111') ==> where id >1 and password ='111';
models.Account.objects.filter(password__startswith=1) ==> where password like '1%'
models.Account.objects.filter(username__contains='zj') ==> 只要username包含大小写的zj
models.Account.objects.filter(username__icontains='zj') ==> 只能匹配到小写的zj
models.Account.objects.filter(id__in=[1,2]) ==> where id in (1,2)
models.Account.objects.filter(username__endswith='j') ==> where username like '%j'
日期的待补充
filter正则表达式
上边拿到的都是queryset的对象,不是数据,想要拿到数据可以使用很多方法
>>> a = models.Account.objects.filter(username__regex=r'(zj|j)$') >>> b = a.values() >>> b.values('id').order_by('id') #升序 <QuerySet [{'id': 2}, {'id': 3}]> >>> b.values('id').order_by('-id') <QuerySet [{'id': 3}, {'id': 2}]> #降序 >>> *想要用reverse 必须要用先order_by排序* >>> b.values('id').order_by('-id').reverse() #翻转 <QuerySet [{'id': 2}, {'id': 3}]> >>> b.values('id').order_by('id').reverse().first() #取最后一个值,先翻转在取第一个 {'id': 3}
5.ORM语句总结
a = models.Account.objects.get(id=1) 精确查询某一字段 #返回的是真实的对象了,不是queryset对象了
直接调用a.id a.username 即可
models.Account.objects.exclude(id=1)
<QuerySet [<Account: Account object (2)>, <Account: Account object (3)>]>
get 返回一个对象,没有或者多个会报错,不常用但是要不filter查询速率快
filter 返回多个对象
all 返回所有数据
exclude 排除符合匹配条件的数据,返回其他的数据
- 修改和删除操作
- 修改全部
>>> models.Account.objects.exclude(id=1).update(password='1234656') #批量修改只要是id不等于1的密码都改成123456
- 单条修改(先get在赋值后保存)
>>> a = models.Account.objects.get(id=1) >>> a.password = '123456789' >>> a.save()
- 批量删除,关联的表的数据也会删除或者变成设置的默认的
>>> models.Account.objects.get(password='123456').delete()
- 单条删除
>>> a = models.Account.objects.get(id=1) >>> a.delete()
外键关联操作(模块创建)
正向外键关联(在有关联字段的表中查询)
>>> a = models.Article.objects.create(title = 'hahahaha322332', content = '阿光高你刚42151啊方法',account_id = 8 ,pub_data = '2020-06-12') >>> a.account.id # a 定义的是Article的数据,但是可以通过外键关联到Account 查询到Account的数据
反向外键关联(无关联字段的表中查询, ORM会自动的帮助我们创建一个表)
>>> obj = models.Account.objects.all()[0] >>> obj.article_set.all() <QuerySet [<Article: Article object (6)>]> >>> obj.article_set.all().values() <QuerySet [{'id': 6, 'title': 'hahahaha', 'content': '阿光高你刚啊方法', 'account_id': 4, 'pub_data': datetime.date(2020, 6, 12)}]>
多对多关联
>>> a.tags.all() >>> t = models.tag.objects.all()[1] >>> t.article_set.all()
6.Django Admin (组件)
admin 是Django自带的让你用来进行数据库管理的web app
提供了很多定制化的功能,你甚至可以用它来进行公司内部的内容管理
首先创建登录的用户 >> python3 manage.py createsuperuser
如果app01想要被管理的话,必须授权允许管理admin.py文件写入下面的内容
from django.contrib import admin from app01 import models # Register your models here. admin.site.register(models.Account) admin.site.register(models.Article) admin.site.register(models.Tag)
开启Django >> python3 manage.py runserver 0.0.0.0:8000
打开localhost:8000/admin 就可以看到对应的数据库进行操作了
7.定制Django admin
from django.contrib import admin from app01 import models class AccountAdmin(admin.ModelAdmin): list_display = ('username', 'email', 'signature') # 显示这三个字段 search_fields = ('username', 'email','signature') # 加入搜索按钮 list_filter = ('email', ) # 过滤, 针对重复的字段过滤 list_per_page = 2 # 设置分页 # list_display_links = ('email',) class ArticleAdmin(admin.ModelAdmin): list_display = ('title', 'content', 'account', 'pub_data') list_filter = ('account', 'pub_data') search_fielshituds = ('title',) fields = ('title', 'content', ('pub_data', 'account', 'tags')) # 设置admin修改创建页面可修改的数据 exclude = ('account',) # 排除不显示一些字段 date_hierarchy = 'pub_data' # 按照时间的分组(只能用时间) fieldsets = ( ('文章基本信息', { 'fields': ['title', 'content'], }, ), ('高级选项', { 'fields': ['account', 'tags', 'pub_data'], 'classes': ('collapse',), # 让这个高级选项变成有收缩折叠功能 } ) ) filter_horizontal = ('tags',) # 只能针对多对多 filter_vertical = ('tags',) radio_fields = {'account': admin.VERTICAL} # 将下拉框变成按钮以供选择 autocomplete_fields = ['account',] readonly_fields = ('title',) # 设置只读字段 admin.site.register(models.Account,AccountAdmin) admin.site.register(models.Article,ArticleAdmin) admin.site.register(models.Tag)
自定义Admin字段
在models文件中写入
def get_comment(self): return 10
再在admin对应的库中加上list_display = ('get_comment',) 字段
class Meta: # verbose_name = "用户列表" # 针对英文的 verbose_name_plural = '用户列表' # 针对中文的
自定义字段名 在,models中修改
signature = models.CharField("签名", max_length=255, null=True) # null允许值为空,签名
自定义表名 在models文件中类中加入
8.views 视图(views文件的操作)
视图中的字段抛开讲解
HttpRequest对象属性
- 他封装了本次请求所涉及的用户浏览器端数据,服务器端数据等,在views里可以通过request对象来调取相应的属性
- request.scheme ==> 查看是https 协议还是http
- request.path == > 返回的是当前请求的url
- request.method ==> 查看获取网页的方法 post get put delete
- request.content_type ==> 返回mime的类型
- request.GET ==> 打印网页GET请求的参数
- request.POST ==> 打印网页POST请求的参数
- request.COOKIE ==> 获取浏览器的cookie数据
- request.FILES == > 拿到通过前端页面上传来的文件,放到内存当中
- request.POST.get("test_f") ==> 拿到选择文件的文件名
- request.META ==> 返回所有的请求头
除了属性HttpRequest的方法
- request.get_host() ==> 返回网站服务器地址,example: '127.0.0.1':'8000'
- request.get_port() ==> 返回服务器主机端口
- request.get_full_path() ==> 返回请求的路径
- request.build_absolute_uri(locaiton) ==> 返回请求完整的url
- request.is_srcure() ==> 判断他是不是https
- request.is_ajax() ==> 判断是否是ajax请求
Httpresponse(content_type格式参考手册https://www.w3school.com.cn/media/media_mimeref.asp)
设置下载文件的方法
def download(request): f = open("static_data/15s第三方软件设备适配情况.xlsx", 'rb') res = HttpResponse(f.read(),content_type='application/vnd.ms-excel') # 设置返回的内容格式为excel文档格式 res['Content-Disposition'] = 'attachment; filename ="15s.xlsx"' # 设置用户请求的时候下载下来的是一个attachement附件和文件名 return res
设置重定向
def redirect(request): return HttpResponseRedirect("/app01/download")
CBV(class base view) 类视图
- 使用类的方式来定义视图,提高代码的可复用性,还可以加入判断条件,还有继承
from django.views import view class TestView(View): def get(self,request): return HttpResponse("测试get请求自动的使用这个get()函数") def post(self,request): return HttpResponse("测试post")
在url 定义的时候加入as.view()方法
path('class_view',view.TestView.as_view())