[TOC]css
发送HTTP请求html
经过TCP套接字,客户端Web服务器发送一个文本的请求报文,一个请求报文由请求行、请求头部、空行、和 请求数据四部分组成
服务器接受请求并返回HTTP响应前端
Web服务器解析请求,定位请求资源。服务器将资源副本写到TCP套接字,由客户端读取。一个响应由状态行、响应头部、空行和响应数据四部分组成
在浏览器地址栏键入URL,按下回车以后经历的过程node
1. 浏览器向DNS服务器请求解析该URL中的域名所对应的IP地址。 2. 解析出IP地址后,根据该IP地址和默认端口80,和服务器创建TCP链接。 3. 浏览器发出读取文件(URL中域名后面部分对应的文件)的HTTP请求,该请求报文做为TCP三次握手的第三次报文的数据发送给服务器 4. 服务器对浏览器做出响应,并把对应的html文本发送给浏览器 5. 释放TCP链接 6. 浏览器渲染HTML并显示内容
HTTP请求方法python
1. GET : 向指定的资源发出"显示"请求。使用GET方法应该只用在读取数据上,而不该被用于产生"反作用"的操做中,例如在Web Application中,其中一个缘由是GET可能会被网络蜘蛛等随意访问. 2. HEAD : 与GET方法同样,都是向服务器发出指定资源的请求。只不过服务器将不传回资源的本文部分。它的好处在于,使用这个方法能够在没必要传输所有内容的状况下,就能够获取其中“关于该资源的信息”(元信息或称元数据)。 3. POST : 向指定资源提交数据,请求服务器进行处理(例如提交表单或者上传文件)。数据被包含在请求本文中。这个请求可能会建立新的资源或修改现有资源,或两者皆有。 4. PUT : 向指定资源位置上传其最新内容。 5. DELETE : 请求服务器删除Request-URI所标识的资源。 6. TRACE : 回显服务器收到的请求,主要用于测试或诊断。 7. OPTIONS : 这个方法可以使服务器传回该资源所支持的全部HTTP请求方法。用'*'来代替资源名称,向Web服务器发送OPTIONS请求,能够测试服务器功能是否正常运做。 8. CONNECT : HTTP/1.1协议中预留给可以将链接改成管道方式的代理服务器。一般用于SSL加密服务器的连接(经由非加密的HTTP代理服务器)
HTTP状态码mysql
1xx消息——请求已被服务器接收,继续处理 2xx成功——请求已成功被服务器接收、理解、并接受 : 200 ok - 请求成功 3xx重定向——须要后续操做才能完成这一请求 4xx请求错误——请求含有词法错误或者没法被执行 : 403 Forbidden - 服务器已经理解请求,可是拒绝执行它 404 Not Found - 请求失败,请求所但愿获得的资源未被在服务器上发现。 5xx服务器错误——服务器在处理某个正确请求时发生错误
URLweb
1. 传送协议。 2. 层级URL标记符号(为[//],固定不变) 3. 访问资源须要的凭证信息(可省略) 4. 服务器。(一般为域名,有时为IP地址) 5. 端口号。(以数字方式表示,若为HTTP的默认值“:80”可省略) 6. 路径。(以“/”字符区别路径中的每个目录名称) 7. 查询。(GET模式的窗体参数,以“?”字符为起点,每一个参数以“&”隔开,再以“=”分开参数名称与数据,一般以UTF8的 URL编码,避开字符冲突的问题) 8. 片断。以“#”字符为起点
HTTP请求格式sql
请求方法 | 空格 | URL | 空格 | 协议版本 | 回车符 | 换行符 --→ 请求行 头部字段名 | : | 值 | 回车符 | 换行符 } ... } --→ 请求头部 头部字段名 | : | 值 | 回车符 | 换行符 } !@#$%^&* ... --→ 请求数据
HTTP相应格式数据库
协议版本 | 空格 | 状态码 | 空格 | 状态码描述 | 回车符 | 换行符 --→ 状态行 头部字段名 | : | 值 | 回车符 | 换行符 } ... } --→ 响应头部 头部字段名 | : | 值 | 回车符 | 换行符 } 请求方法 | 空格 | URL | 空格 | 协议版本 | 回车符 | 换行符 --→ 响应正文
mport socket # 建立一个socket对象 sk = socket.socket() # 绑定ip和端口 sk.bind(('127.0.0.1', 8848)) # 监听 sk.listen() def index(url): ret = '欢迎进入红浪漫! - {}'.format(url) return ret.encode('utf-8') def home(url): ret = '欢迎回家! - {}'.format(url) return ret.encode('utf-8') def help_me(url): ret = '再等30年,你又是条好汉! - {}'.format(url) return ret.encode('utf-8') list1 = [ ('/index', index), ('/home', home), ('/help_me', help_me), ] # 等待链接 while True: conn, addr = sk.accept() data = conn.recv(1024) url = data.decode('utf-8').split()[1] # 获取用户输入的路径 # for i in list1: # if url == i[0]: # ret = i[1](url) # break # else: # ret = '被查办了!'.encode('utf-8') func = None for i in list1: if url == i[0]: func = i[1] break if func: ret = func(url) else: ret = '被查办了!'.encode('utf-8') conn.send(b'HTTP/1.1 200 OK\r\ncontent-type: text/html; charset=utf-8\r\n\r\n') conn.send(ret) conn.close()
命令行下载安装django
pip3 install django - 下载安装的是最新版本 pip3 install django==1.11.23 -i https://pypi.tuna.tsinghua.edu.cn/simple - 选择版本,选择安装源
建立项目
1. 首先进入要建立项目的文件夹 2. SHIFT + 鼠标右键 打开命令行 3. 执行命令 : django-admin startproject 项目名
启动项目
python manage.py runserver # 默认127.0.0.1 : 80000 python manage.py runserver 80 # 修改 80端口 python manage.py runserver 0.0.0.0:80 # 修改地址和端口
pycharm
建立项目
1. New Project 2. Django - 选择项目目录 - 选python版本 - Create
启动项目
选中项目目录 - run(图标)
pycharm建立项目的一些说明
1. settings.py会在项目根目录下自动建立一个名字为 templates 用于放HTML等文件的文件夹 : 'DIRS': [os.path.join(BASE_DIR, 'templates')] 2. 导入模块 ( urls.py ): from django.shortcuts import HttpResponse,render def index(request): return HttpResponse('欢迎进入红浪漫!') # 返回字符串 def home(request): return render(request,'home.html') # 返回html页面 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^home/', home), url(r'^index/', index), ] 3. 修改ip和端口 : Run → Edit Configurations
**项目中settings.py
文件下 😗*
STATIC_URL = '/static/' STATICFILES_DIRS = [ #按照列表的顺序进行查找 os.path.join(BASE_DIR,'static'), os.path.join(BASE_DIR,'xxx') ] os.path.join(BASEDIR, 'static', 'css')是静态文件存放的实际路径,STATIC_URL='/static/'中的/statis/是这个路径的别名。二者是一个映射关系,若是要使用该静态文件,那么静态文件的URL中的"实际路径部分"就要使用别名来代替
settings.py
配置好后, 须要在项目下新建文件static
, 这个static
是存放 CSS, JavaScript, Images
等静态文件的一个根目录form表单
form表单中 action 填写提交表单的ip地址和端口 method 是提交请求方式 默认GET请求,html中要小写 <form class="form-signin" action = "" method="post">
<input class="form-control" id="inputEmail" autofocus="" required="" type="email" placeholder="Email address" > required="" 是表单的必填项,删除后,就能够了
<input class="form-control" id="inputEmail" autofocus="" required="" type="email" name="username" placeholder="Email address"> <input class="form-control" id="inputPassword" required="" type="password" name="password" placeholder="Password"> 设置name的键值对
关掉pycharm的校验请求功能 - csrf 中间件
在settings.py中 MIDDLEWARE = [ 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', # 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', ]
禁用前端校验
form表单中添加 novalidate <form class="form-signin" action = "" method="post" novalidate>
urls.py
中校验请求(用户名密码校验)
from django.shortcuts import HttpResponse, render, redirect def index(request): # 业务逻辑 return HttpResponse('欢迎进入红浪漫!') def home(request): return render(request, 'home.html') def login(request): if request.method == 'GET': # 返回登陆页面 return render(request, 'login.html') elif request.method == 'POST': # 获取提交的数据 request.POST username = request.POST.get('username') password = request.POST.get('password') # 对用户名和密码进行校验 if username == 'alex' and password == 'alexdsb': # 校验成功 跳转到首页(重定向) # return HttpResponse('欢迎进入红浪漫!') return redirect('/index/') else: # 校验失败 从新登录 return render(request, 'login.html')
咱们在项目中的urls中配置路由,在templates 里写HTML文件,若是项目很大,路由不少,HTML文件不少,那么就须要在项目的内部与与项目同名的同级建立APP应用,在APP应用里能够写本身的urls和views 这样主路由中的路由能够映射到APP中的子路由,这个时候就像一个树的根部到树叶扩散。
建立app
CMD建立 : 进入项目文件夹下,按住shift右键进入命令行 : python manage.py startapp app名称 pycharm中 : 在Teminal命令行中键入命令 : python manage.py startapp app名称 利用pycharm中的tools工具建立 : 1. 调出窗口 : tools → Run manage.py Task ... 2. 键入命令 : startapp app名
注册app
在settings中 : INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'app01', # 第一种方式 'app01.apps.App01Config', # 第二种方式 推荐写法 ]
app下的目录解释
admin.py django admin apps.py app的信息 models.py 模型 model 跟数据库有关 views.py 写函数(以前在urlspy中写的函数写在这里
**将urls.py
中的函数转移到建立的app
下的views.py
😗*
views.py下的全面内容
from django.shortcuts import render,redirect,HttpResponse def login(requset): if requset.method == 'GET': # 返回登陆页面 return render(requset,'login.html') elif requset.method == 'POST': # 获取提交的数据 (用户名和密码) username = requset.POST.get('username') password = requset.POST.get('password') # 对用户名和密码进行校验 if username == 'python' and password == '123': # 校验成功,跳转到设置页面(重定向) return redirect('http://donyz.s567.tw/') else: # 校验失败,从新登陆 return render(requset,'login.html')
将views.py
中的函数导入到urls.py
中
urls.py文件下 : from app01 import views # 导入 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^login/', views.login), # 引用 ]
对象关系映射(Object Relational Mapping,简称ORM)是经过使用描述对象和数据库之间映射的元数据,将面向对象语言程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另一种形式。 对应关系 类 -- 表 对象 -- 数据行 属性 -- 字段 * orm能够操做表,操做数据行
**1. CMD命令行建立数据库 : ** create database Day54
2. settings.py
的配置
# settings.py下 : DATABASES = { 'default': { 'ENGINE' : 'django.db.backends.mysql', # 数据库类型 'NAME' : 'Day54', # 数据库名 'HOST' : '127.0.0.1', # IP地址 'PORT' : 3306, # 数据库的端口 'USER' : 'root' # 数据库用户名 'PASSWORD' : '2108' # 密码 } }
3. 使用pymysql
模块链接mysql数据库 (__init__.py
)
在项目同名的文件夹下的__init__.py中 : 下面这两行代码也能够不在__init__.py中,只要能运行就能够 # 导入pymysql模块 import pymysql # 用pymysql模块替换掉mysqldb模块 由于默认使用的是mysldb模块,此模块仅支持python2, pymysql.install_as_MySQLdb()
**4. 写pymysql
模块与数据库的对应关系 **
在app下的models.py中写表结构 : from django.db import models class User(models.Model): # 建立类,继承Model类的功能 username = models.CharField(max_length=32) # 数据库中表的字段 类型为varchar(32) password = models.CharField(max_length=32) # 数据库中表的字段 类型为varchar(32)
5. 执行创数据库迁移的命令
pycharm的Teminal命令窗口下 : python manage.py makemigrations # 记录下models.py的变动记录并更新到 migrations 文件夹下的 001_inittal.py文件中 python manage.py migrate # 把变动记录同步到数据库中 这样上面的数据库表结构就写入数据库了
6. 利用pycharm
查看数据库
**最新版的pycharm在链接中遇到因为时区贰没法链接数据库的问题的解决办法 😗*
在链接数据库窗口: 在数据库路径后加 ?serverTimezone=GMT 便可
**注意 😗*
在pycharm中修改数据库后须要提交,修改才会生效
7. 利用数据库进行用户名密码校验
from django.shortcuts import render,redirect from app01 import models # 导入models.py中的User等类 def login(requset): if requset.method == 'GET': # 返回登陆页面 return render(requset,'login.html') elif requset.method == 'POST': # 获取提交的数据 (用户名和密码) user = requset.POST.get('username') pwd = requset.POST.get('password') # 对用户名和密码进行校验 ret = models.User.objects.filter(username=user,password=pwd) # filter - 过滤筛选 查不到为空(False)对象列表 # ret = models.User.objects.get(username=user,password=pwd) # get - 找不到会报错,找到多个也会报错 if ret: # 校验成功,跳转到设置页面(重定向) return redirect('http://donyz.s567.tw/') else: # 校验失败,从新登陆 return render(requset,'login.html')
出版社 | 图书 | 做者
具体流程
**a. 命令行建立数据库 😗*
create database day55_bookmanager
**b. 项目配置数据库 😗*
settings.py
下
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'day55_bookmanager', 'HOST': '127.0.0.1', "PORT": 3306, "USER": 'root', 'PASSWORD': '2108' } }
**c. 用pymysql替换MYSQLdb模块 😗*
**项目下 __init.py
文件 😗*
import pymysql pymysql.install_as_MySQLdb()
**d. app下建立表结构 😗*
**modes.py
文件下 😗*
from django.db import models class Publisher(models.Model): # AutoField -自增加类型,映射到数据库中是11位的整数,使用此字段时,必须传递primary_key=True, # 不然在生成迁移脚本文件时,就会报错 pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) def __str__(self): # 帮助打印对象中具体的属性值 return "{}{}".format(self.pid,self.name)
**e. 执行创数据库迁移的命令 😗*
pycharm的Teminal命令窗口下 : 1. python manage.py makemigrations # 记录下models.py的变动记录并更新到 migrations 文件夹下001_inittal.py文件中 2. python manage.py migrate # 把变动记录同步到数据库中 这样上面的数据库表结构就写入数据库了
给表添加一些数据
A.urls.py
写对应关系:
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), ]
**B.app
中views.py
写业务逻辑 😗*
from django.shortcuts import render from app01 import models def publisher_list(request): # 从数据库中查询全部的出版社 all_pubilshers = models.Publisher.objects.all() # 获取数据库所有数据,返回的是一个对象列表 # 返回一个页面 return render(request,'publisher_list.html',{'xxx':all_pubilshers}) # xxx为自定义的key,在前端页面用固定格式 :{{xxx}} 能够引用xxxkey的值all_pubilshers
C.publisher_list.html
图书管理网页
<table border="1"> <thead> <!-- 表头 --> <tr> <!-- 一行 --> <th>序号</th> <th>ID</th> <th>出版社名称</th> </tr> </thead> <tbody> <!-- 主体内容 --> {% for publisher in xxx%} <!-- 循环语句 xxx为后端数据库的全部数据--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 为for循环次数计数 对应序号--> <td>{{ publisher.pid }}</td> <!--pid等同于pk (primarykey)--> <td>{{ publisher.name }}</td> </tr> {% endfor %} <!-- 闭合语句 --> </tbody> </table>
**数据库修改惟一 😗*
from django.db import models class Publisher(models.Model): # AutoField -自增加类型,映射到数据库中是11位的整数,使用此字段时,必须传递primary_key=True, # 不然在生成迁移脚本文件时,就会报错 pid = models.AutoField(primary_key=True) name = models.CharField(max_length=32,unique=True) # 惟一 def __str__(self): #帮助打印对象中具体的属性值 return "{}{}".format(self.pid,self.name) 执行创数据库迁移的命令 : pycharm的Teminal命令窗口下 : 1. python manage.py makemigrations # 记录下models.py的变动记录并更新到 migrations 文件夹下001_inittal.py文件中 2. python manage.py migrate # 把变动记录同步到数据库中 这样上面的数据库表结构就写入数据库了
提交新增图书页面
<body> <form action="" method="post"> <p> 请输入新增出版社名称 : <input type="text" name="pub_name" value="{{ pub_name }}"> <span style="color: red">{{ error }}</span> </p> <button>提交</button> </form> </body>
展现页面
<body> <table border="1"> <thead> <!-- 表头 --> <tr> <!-- 一行 --> <th>序号</th> <th>ID</th> <th>出版社名称</th> </tr> </thead> <tbody> <!-- 主体内容 --> {% for publisher in xxx%} <!-- 循环语句 xxx为后端数据库的全部数据--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 为for循环次数计数 对应序号--> <td>{{ publisher.pid }}</td> <!--pid等同于pk (primarykey)--> <td>{{ publisher.name }}</td> </tr> {% endfor %} <!-- 闭合语句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> <!--<a href="/" ></a> 表示连接到网站根目录. <a href="/porducts/" ></a> 表示连接到根目录下的products目录.--> </body>
app
中views.py
写业务逻辑
def publisher_add(requset): pub_name,error = '', '' if requset.method == "POST": # 获取用户提交的信息 (出版社名字) pub_name = requset.POST.get('pub_name') if not pub_name: # 输入为空 error = "输入不能为空" elif models.Publisher.objects.filter(name=pub_name): # 数据已经存在 error = "数据已经存在" else: # 用户输入正确,数据写入数据库 # 方式一 : models.Publisher.objects.create(name=pub_name) # 方式二 : # obj = models.Publisher(name = pub_name) # 在内存中实例化对象 # obj.save() # 跳转到展现页面 return redirect('/publisher_list/') return render(requset,'publisher_add.html',{'pub_name':pub_name,'error':error})
urls.py
写对应关系
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), ]
在以前基础上须要修改的
展现界面添加操做相关按钮
<body> <table border="1"> <thead> <!-- 表头 --> <tr> <!-- 一行 --> <th>序号</th> <th>ID</th> <th>出版社名称</th> <th>操做</th> </tr> </thead> <tbody> <!-- 主体内容 --> {% for publisher in xxx%} <!-- 循环语句 xxx为后端数据库的全部数据--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 为for循环次数计数 对应序号--> <td>{{ publisher.pid }}</td> <!--pid等同于pk (primarykey)--> <td>{{ publisher.name }}</td> <td><a href="/publisher_del/?pk={{ publisher.pk }}"><button>删除</button></a></td> </tr> {% endfor %} <!-- 闭合语句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> </body>
urls.py
写对应关系
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), url(r'^publisher_del/', views.publisher_del), ]
views.py
增长定义函数,写业务逻辑代码
# 删除数据 def publisher_del(request): # 利用get请求拿到要删除的数据id pk = request.GET.get('pk') # 验证要删除的数据是否存在 query = models.Publisher.objects.filter(pid=pk) if not query : # 数据不存在返回一个字符串 return HttpResponse('要删除的数据不存在') # 经过queryset删除查到的全部数据 # 删除方式一 : query.delete() # # 删除方式二 删除一个对象: # query[0].delete() # 跳转到展现页面 return redirect('/publisher_list/')
编辑页面
<body> <form action="" method="post"> <p> 请输入编辑出版社的新名称 : <input type="text" name="pub_name" value="{{ obj.name }}"> <span style="color: red">{{ error }}</span> </p> <button>提交</button> </form> </body>
展现界面添加操做相关按钮
<body> <table border="1"> <thead> <!-- 表头 --> <tr> <!-- 一行 --> <th>序号</th> <th>ID</th> <th>出版社名称</th> <th>操做</th> </tr> </thead> <tbody> <!-- 主体内容 --> {% for publisher in xxx%} <!-- 循环语句 xxx为后端数据库的全部数据--> <tr> <td>{{ forloop.counter }}</td> <!--forloop.counter 为for循环次数计数 对应序号--> <td>{{ publisher.pid }}</td> <!--pid等同于pk (primarykey)--> <td>{{ publisher.name }}</td> <td><a href="/publisher_del/?pk={{ publisher.pk }}"><button>删除</button></a> <a href="/publisher_edit/?pk={{ publisher.pk }}"><button>编辑</button></a> </td> </tr> {% endfor %} <!-- 闭合语句 --> </tbody> </table> <a href="/publisher_add/"><button>添加</button></a> </body>
urls.py
写对应关系
from app01 import views urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^publisher_list/', views.publisher_list), url(r'^publisher_add/', views.publisher_add), url(r'^publisher_del/', views.publisher_del), url(r'^publisher_edit/', views.publisher_edit), ]
views.py
增长定义函数,写业务逻辑代码
# 编辑数据 def publisher_edit(request): error = '' # 获取要查询的ID pk = request.GET.get('pk') # 查询要编辑的对象 obj = models.Publisher.objects.filter(pk =pk).first() # 获取对象列表的第一个对象 if not obj: return HttpResponse('要编辑的对象不存在') if request.method == "POST": # 获取新提交的数据 pub_name = request.POST.get('pub_name') if not pub_name: # 输入为空 error = "输入不能为空" elif models.Publisher.objects.filter(name=pub_name): # 数据已经存在 error = "数据已经存在" else: # 编辑原始数据 obj.name = pub_name obj.save() # 跳转到展现页面 return redirect('/publisher_list/') return render(request,'publisher_edit.html',{'obj':obj,'error':error})
get : 发get请求的方式: 1. form表单 不指定method 2. 在地址栏中直接输入地址 回车 3. a标题 ?k1=v1&k2=v2 request.GET request.GET.get('k1') post : form表单 method='post' request.POST request.POST.get('k1')
面向对象和关系型数据库的一种映射 对应关系: 类 ——》 表 对象 ——》 记录 (数据行) 属性 ——》 字段 from app import models 查询: models.Publisher.objects.get(name='xxxxx') # 查询一个对象 有且惟一 差很少或者多个就报错 models.Publisher.objects.filter(name='xxxxx') # 查询知足条件全部对象 对象列表 queryset models.Publisher.objects.all() # 查询全部的数据 对象列表 queryset 新增: models.Publisher.objects.create(name='xxxxx') # 返回值 就是新建的对象 obj = models.Publisher(name='xxxxx') obj.save() 删除: models.Publisher.objects.filter(pk=1) .delete() obj = models.Publisher.objects.filter(pk=1) .first() obj.delete() 修改: obj = models.Publisher.objects.filter(pk=1) .first() obj.name = 'xxxxx' obj.save()
一对多的对应关系 - 外键建立在多的一方
class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher', on_delete=models.CASCADE) # 外键 Publisher为对应关联的表 # on_delete django2.0中 必填
on_delete参数的各个值的含义:
1. on_delete=None, # 删除关联表中的数据时,当前表与其关联的field的行为 2. on_delete=models.CASCADE, # 删除关联数据,与之关联也删除 - 级联删除 3. on_delete=models.DO_NOTHING, # 删除关联数据,什么也不作 4. on_delete=models.PROTECT, # 删除关联数据,引起错误ProtectedError models.ForeignKey('关联表', on_delete=models.SET_NULL, blank=True, null=True) 5. on_delete=models.SET_NULL, # 删除关联数据,与之关联的值设置为null(前提FK字段须要设置为可空,一对一同理) models.ForeignKey('关联表', on_delete=models.SET_DEFAULT, default='默认值') 6. on_delete=models.SET_DEFAULT, # 删除关联数据,与之关联的值设置为默认值(前提FK字段须要设置默认值,一对一同理) 7. on_delete=models.SET, # 删除关联数据, a. 与之关联的值设置为指定值,设置:models.SET(值) b. 与之关联的值设置为可执行对象的返回值,设置:models.SET(可执行对象)
查询:
all_books = models.Book.objects.all() print(all_books) for book in all_books: print(book) print(book.pk) print(book.title) print(book.pub,type(book.pub)) # book.pub为所关联的对象 print(book.pub_id,type(book.pub_id)) # 所关联的对象的pk
**新增 😗*
models.Book.objects.create(title=title,pub=models.Publisher.objects.get(pk=pub_id)) models.Book.objects.create(title=title, pub_id=pub_id)
**删除 😗*
pk = request.GET.get('pk') models.Book.objects.filter(pk=pk).delete()
**编辑 😗*
book_obj.title = title book_obj.pub_id = pub_id # book_obj.pub = models.Publisher.objects.get(pk=pub_id) book_obj.save()
class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) class Author(models.Model): name = models.CharField(max_length=32) book = models.ManyToManyField('Book') # 描述多对的关系 不生成此字段,而是生成Author-Book的关系表
all_authors = models.Author.objects.all().order_by('id') for author in all_authors: print(author.name) print(author.pk) print(author.books) # 关系管理对象 print(author.books.all()) # 所关联的全部对象
models.py : class Book(models.Model): title = models.CharField(max_length=32) pid = models.ForeignKey('Publisher',on_delete=models.CASCADE) def __repr__(self): return self.title __str__ = __repr__ class Author(models.Model): name = models.CharField(max_length=32) book = models.ManyToManyField('Book') # 描述多对的关系 不生成此字段,而是生成Author-Book的关系表
author.html页面 : <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td>{% for book in author.book.all %} {{ book }} {% endfor %}</td>
views.py 逻辑 def author_list(request): all_author = models.Author.objects.all() return render(request, 'author_list.html', {'all_author': all_author})
books = request.POST.getlist('books') # 获取多个元素 # 新建做者 author_obj = models.Author.objects.create(name=name) # 给做者和书籍绑定关系 author_obj.books.set(books) #
建立多对多的表的方法
django经过ManyToManyField自动建立第三张表
class Book(models.Model): title = models.CharField(max_length=32) pub = models.ForeignKey('Publisher', on_delete=models.CASCADE) # authors = models.ManyToManyField('Author') # 描述多对多的关系 不生成字段 生成关系表 def __repr__(self): return self.title __str__ = __repr__ class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField('Book') # 描述多对多的关系 不生成字段 生成关系表
本身手动建立
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
本身建立 + ManyToManyField
class Book(models.Model): title = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) books = models.ManyToManyField(Book, through='Book_Author') class Book_Author(models.Model): book = models.ForeignKey(Book, on_delete=models.CASCADE) author = models.ForeignKey(Author, on_delete=models.CASCADE) date = models.DateField()
nodels
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="{{ author_obj.name }}"> <span style="color: crimson">{{ error }}</span> 著做 :<select name="book_id" multiple> {% for book in all_books %} {% if book in author_obj.book.all %} <option selected value="{{ book.pk }}">{{ book.title }}</option> {% else %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
views
def author_list(request): all_author = models.Author.objects.all() return render(request, 'author_list.html', {'all_author': all_author})
html
<table class="table table-striped table table-hover"> <thead> <tr> <th>序号</th> <th>ID</th> <th>做者</th> <th>著做</th> <th>操做</th> </tr> </thead> <tbody> {% for author in all_author %} <tr> <td>{{ forloop.counter }}</td> <td>{{ author.pk }}</td> <td>{{ author.name }}</td> <td>{% for book in author.book.all %} 《{{ book }}》 {% endfor %}</td> <td><a href="/author_del/?pk={{ author.pk }}" class="btn btn-danger">删除</a> <a href="/author_edit/?pk={{ author.pk}}" class="btn btn-warning">编辑</a></td> </tr> {% endfor %} </tbody> </table>
views
def author_del(request): pk = request.GET.get('pk') obj_author = models.Author.objects.filter(pk=pk) obj_author.delete() return redirect('/author_list/')
views
def author_add(request): error = '' if request.method == "POST": author_name = request.POST.get('author_name') book = request.POST.getlist('list_book') if not author_name or not book: error = '输入或选择不能为空!' elif models.Author.objects.filter(name=author_name): error = '做者已存在!' else: author_obj = models.Author.objects.create(name=author_name) author_obj.book.set(book) return redirect('/author_list/') all_books = models.Book.objects.all() return render(request, 'author_add.html', {'all_books': all_books, 'error': error})
html
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="请填写做者"> <span style="color: crimson">{{ error }}</span> 著做: <select name="list_book" multiple> {% for book in all_books %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
views
def author_edit(request): error = '' pk = request.GET.get('pk') author_obj = models.Author.objects.filter(pk=pk).first() if not models.Author.objects.filter(pk=pk): return HttpResponse('数据不合法!') if request.method == "POST": author_name = request.POST.get('author_name') book_id = request.POST.getlist('book_id') if not author_name or not book_id: error = '输入或选择不能为空' elif models.Author.objects.filter(name=author_name): error = '做者已存在!' else: author_obj.name = author_name author_obj.save() author_obj.book.set(book_id) return redirect('/author_list/') all_books = models.Book.objects.all() return render(request, 'author_edit.html', {'all_books': all_books, 'error': error, 'author_obj': author_obj})
html
<form class="form-inline" method="post"> <div class="form-group"> <input type="text" class="form-control" id="exampleInputEmail3" name="author_name" placeholder="{{ author_obj.name }}"> <span style="color: crimson">{{ error }}</span> 著做 :<select name="book_id" multiple> {% for book in all_books %} {% if book in author_obj.book.all %} <option selected value="{{ book.pk }}">{{ book.title }}</option> {% else %} <option value="{{ book.pk }}">{{ book.title }}</option> {% endif %} {% endfor %} </select> </div> <button type="submit" class="btn btn-default">提交</button> </form>
MVC全名是Model View Controller,是模型(model)-视图(view)-控制器(controller)的缩写,一种软件设计典范,用一种业务逻辑、数据、界面显示分离的方法组织代码,将业务逻辑汇集到一个部件里面,在改进和个性化定制界面及用户交互的同时,不须要从新编写业务逻辑。具备耦合性低、重用性高、生命周期成本低等优势。
1. Model (模型): 核心的"数据层"(Model),也就是程序须要操做的数据或信息。 2. View (视图): 直接面向最终用户的"视图层"(View)。它是提供给用户的操做界面,是程序的外壳。 3. Controller (控制层) : 是"控制层"(Controller),它负责根据用户从"视图层"输入的指令,选取"数据层"中的数据,而后对其进行相应的操做,产生最终结果。
MTV 是Django定义的一种开发规范
Model(模型):负责业务对象与数据库的对象(ORM) Template(模版):负责如何把页面展现给用户 View(视图):负责业务逻辑,并在适当的时候调用Model和Template
{{ }}和 {% %} {{ }}表示变量,在模板渲染的时候替换成值,{% %}表示逻辑相关的操做。
{{ 变量名 }} 变量名由字母数字和下划线组成。 点(.)在模板语言中有特殊的含义,用来获取对象的相应属性值。
views.py中的数据: context = { "filter_list": ['西游记', '水浒传', '红楼梦', '三国演义'], "filter_dict": { 'name': "小猪佩奇", 'age': 3, 'hobby': "睡觉" } } 前端页面操做 : # 取filter_list中的第一个参数 {{ filter_list.0 }} # 西游记 # 取字典中key的值 {{ filter_dict.name }} # 小猪佩奇 {# 取对象的name属性 #} {{ person_list.name }} {# .操做只能调用不带参数的方法 #} {{ person_list.dream }}
注:当模板系统遇到一个(.)时,会按照以下的顺序去查询: 1. 在字典中查询 2. 属性或者方法 3. 数字索引
filters - 用来修饰变量的显示结果
语法: {{ value|filter_name:参数 }} ':'左右没有空格没有空格没有空格
{{ value|default:"nothing"}} 若是value值没传的话就显示nothing 注:TEMPLATES的OPTIONS能够增长一个选项:string_if_invalid:'找不到',能够替代default的的做用
将值格式化为一个 “人类可读的” 文件尺寸 (例如 '13 KB', '4.1 MB', '102 bytes', 等等)。
{{ value|filesizeformat }}
给前端变量加参数
{{ value|add:"2" }}
{{ first|add:second }}
若是first、second都是列表
如first=[1,2,3]
,second = [4,5,6]
, 那么结果是两个列表的合并 :[1,2,3,4,5,6]
{{ value|lower }}
{{ value|upper}}
{{ value|title }}
{{ value|length }}
- 返回的是value的长度
{{value|slice:"2:-1"}}
{{ value|first }}
{{ value|last }}
使用字符串拼接列表。同python的str.join(list)。 {{ value|join:" // " }}
truncatewords - 按照单词截断
若是字符串字符多于指定的字符数量,那么会被截断。截断的字符串将以可翻译的省略号序列(“...”)结尾。
参数:截断的字符数 {{ value|truncatechars:9}}
日期格式化 {{ value|date:"Y-m-d H:i:s"}}
views.py中 import datetime context{ 'now':datetime.datetime.now(), } {{ now|date:"Y-m-d H:i:s"}}
settings的配置: USE_L10N = False DATETIME_FORMAT = 'Y-m-d H:i:s' DATE_FORMAT = 'Y-m-d' TIME_FORMAT = 'H:i:s'
**在先后端传输变量数据的时候,前端引用的后端的多是一串前端代码,在默认的状况下,为了安全,前端会转义成字符串, 若是想要运行这串引用的代码,就须要加safe {{ value|safe}}**
在py后台中先解除不安全
from django.utils.safestring import mark_safe # 导入模块 'a':mark_safe('<a href="http://www.baidu.com">跳转</a>') # 定义数据的时候用mark_safe(数据)
1. 在app下建立名字必须为 templatetags 的python包 2. 在templatetags包内建立python文件 : from django import template # 导入模板 register = template.Library() # register 为固定写法,不能变 # 写过滤器 @register.filter # 必须加装饰器 def 过滤器名(value,arg=None): # 至多能够接收两个参数,一个是value变量,一个是过滤器的参数(:后面的参数) return value.upper() # 变成大写 3. 前端页面写法 {% load python文件 %} # 加载过滤器 {{ value|过滤器名 }}
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% endfor %} </ul>
<ul> {% for user in user_list %} <li>{{ user.name }}</li> {% empty %} <li>空的数据</li> {% endfor %} </ul> <!--若for循环取不到值,则会执行empty中的内容-->
{% num|divisibleby:2 %} <!-- 对num取2的余数-->
{% if age<18 %} 未成年 {% elif age<30 %} 青年人 {% else %} 中年人 {% endif %}
**if语句支持 and 、or、==、>、<、!=、<=、>=、in、not in、is、is not判断 **
且 if 不支持算数运算、不支持连续判断
定义中间变量 , 给变量起别名
方式一 : {% with 旧名字 as 新的名字 %} 这里就能够引用新的名字 {% endwith %} 方式二 : {% with 新的名字=旧名字 %} 这里就能够引用新的名字 {% endwith %}
这个标签用于跨站请求伪造保护。
在页面的form表单里面写上 {% csrf_token %}
下面的表格模拟html模板 ( 假设这个页面叫 " 模板.html " )
固定页面 | 固定页面 |
---|---|
固定页面 | '' 须要替换的页面 '' content 为这个模块的名称 content{% block content %} {% endblock %} |
{ % extends '模板.html'%} <!-- 导入模板--> { % block 模块名% } <!-- 这里的模块么要和模板的模块名一致--> 这里写本身的内容 { % endblock% }
若是子页面要单独用一个样式css 或js,
那么就能够单独的使用block块引用,避免其余子页面的时候也加载了没必要要的样式
在主界面须要插入小组件的地方如 导航栏等 写入代码{%include '组件名.html%}
组件名.html 中,不须要head,body等,能够直接写代码
动态获取static别名
**方式一 😗*
{% load stati %} 加载动态static别名 <!--这样不管配置中的static别名设置成什么,均可以用static动态获取到 --> <!--引用文件直接在{%staticc 'css/xxcss' %} --> 例 : <link rel="stylesheet" href="{% static 'css/dashboard.css' %}">
**方式二 😗*
{% load stati %} <!--获取动态文件前缀 { % get_static_prefix %} - 找到动态文件别名--> 例 : <link rel="stylesheet" href="{% get_static_prefix %}css/cssyangs.css">
在templatetags中的py文件中 from django import template register = template.Library() @register.simple_tag def join_str(*args, **kwargs): return '_'join(args) + "*".join(kwargs.values()) 前端页面引用 : {% load my_tags %} # my_tags 为 emplatetags 的py文件 {% join_str 'v1' 'v2' k3='k3' k4='v4' %} # 结果 : v1_v2k3*k4
在app中建立名字为templatetags
的python包
在templatetags中出建立python文件my_tags.py
在建立的python中写自定义函数
from django import template register = template.Library() @register.inclusion_tag('html模板.html') def page(num): return {'num':range(1,num+1)} # 返回的必须是个字典 会把num传到html模板.html
新建HTML,写分页模板
<nav aria-label="Page navigation"> <ul class="pagination"> <li> <a href="#" aria-label="Previous"> <span aria-hidden="true">«</span> </a> </li> {% for i in num %} <li><a href="#">{{i}}</a></li> {% endfor %} <li> <a href="#" aria-label="Next"> <span aria-hidden="true">»</span> </a> </li> </ul> </nav>
在须要分页的页面导入分页小组件
{% load my_tags %} # 加载自定义模块my_tags {% page 5 %} # 会把5这个参数传回到函数中,表示的是分5页