Django学习记录

花了2个星期学习了一下Django的基本使用,感觉就是python真的很牛逼,第三方库真是太丰富了,人生苦短我用python,这句话我是切切实实体会到了。用Django框架写服务端的代码,不知道比.net的效率高出多少倍。之前写.net的时候,为了把数据库映射到业务层花大力气了,又是用EF实体模型,又是用T4模板,从模型层上开始一个接口一个接口的写到业务层。如今用Django,都是集成的,根本不用管这些,甚至连SQL都不须要会使用,开发速度不知提升多少倍。javascript

这个是个人Django笔记,我听的老男孩的课,好像是第四期的,16年末的那个版本,两个大王老师讲的仍是很好的。知道了基本使用,接下来就是找个开源项目练一练,练熟了再看看源码。css

ps. 这是听得现场笔记,想着本身忘记了回头看能想起来就行,因此写的比较零碎。能想到的适合场景就是恰好你也想听这个课就能够拿着参考。若是你是想系统的看Django的教程,建议去alex,武沛齐这些大神的博客看,他们写的是真棒。html

day49

Http:无状态前端

请求协议的格式java

请求首行.python

Accept:告诉server我能接收的有哪些类型 q是权重的意思mysql

Accept-encoding:压缩格式,告诉服务器你回复的压缩格式jquery

Accept-Language:能接受的语言web

connection:keep-alive 服务器稍微等一下子(默认3000ms),这个也能够设置成当即断的模式面试

Host:我访问的域名,,主机地址

useragent:我这边的计算机信息啊,浏览器信息啊之类的信息,(发给服务器的)

url发送数据的格式:www.baidu.com?username=hhh&pwd=123 就是不安全 数据的数据通常在1k范围内

get没有请求体,post才有,由于get把数据放到后面去了

默认是get的请求方式 a标签和超连接也都是get请求

post请求

数据再也不地址栏中

数据大小没有上限

有请求体

若是存在中文,会使用URL编码

referer:你这个请求从哪里过来的


响应协议

这个就是server端告诉浏览器的一些事情

状态码

500 代码写错了

300 定向相关的内容

server:服务器版本信息


写一个最最简单的web框架

就是要求写一个server端,

wsgiref,python内部得服务器,作http解析的

1570799780701

注意那个return后面有个 b 由于要的是字节

1570800053852

environ:服务器打包好了放过来的第一个参数。是一个大的字典。

start_response:就是用来处理请求头的。

return 返回的就是浏览器真正要响应的响应体。

njix(音),真实生产中用这个服务器

1570801103057

根据路径来调换显示什么内容

1570801168682

这个fool是返回的 读取一个html的内容 注意要加列表的符号 否则会报splite的错误

1570801366306

经过字符串读的时候可能会有问题,这时候能够考虑先经过字节读出来,而后转成字符串。

1570802900739

Django 就是学这4部分的内容

控制器 --url的分发

model--

魔板渲染

view视图:一个url处理一个函数

MVC MTV

Quit the server with CTRL-BREAK.

model:操做数据库 ORM的方式

1570804050104

怎么经过python操做数据库

怎么把数据库的内容更加灵活的渲染到页面上

这两点是重点学的也是难点,另外两点很简单

经过命令行,建立一个diango项目

1570804682955

mysite2就是一个全局的,这个全局下面有不少的功能。

在这个项目里面 建一个子项目blog (就好似大的微信微信项目里有三个独立的小的功能(朋友圈、聊天..))

至关于把应用分层了,如今这边说blog博客的应用,那全部的这个功能都在这个里面了。

1570804929948

1570805069324

pycharm里面快速的新建一个Django项目

1570805836078

1.在urls里面 加一个路由 因为所在的文件夹不一样 因此须要导入地址

1570806300140

req服务器打包的信息对

return 必定是个httpresponse对象

1570806673898

运行Django的命令

1570806550817

Django的htm文件都往这个文件夹里面放 若是没有这个文件夹就本身建

1570806745937

render 函数的第一个必须传入 request(得对应起来就行) render的功能就是内部作了一个渲染,而后仍是返回httpresponse

1570806896382

setting里设置路径拼接

他能自动找到的缘由是在setting里面作了路径的自动拼接,因此能找到

1570807115670

Django每次修改自动重启,不须要再关闭了重启

1570807317828

1570807378849

放jqueery在static文件夹里,可是为了让这个文件夹的路径让Django知道,因此须要到setting里进行配置。

1570808265481

1570808494695

1570808997166

1571305721629

起别名就是为了之后方便改动,无外乎就是这个缘由

起了别名就不要用真实的了,用了也没用,必须用别名

添加Jquerry的方法2 推荐使用

这个方式注意须要在开头加一个东西。。无论哪一种方式,解析完都是同样的。

1570865683490

1570865831943

要使用static标签,首先须要{% load static %}


08:

若是把static那个文件放在blog里,事实上大点的项目都是这么玩的。

就该这么一个 十分方便就是由于有虚拟路径和实际路径的帮忙

1570866100429


无命名分组

1570870446216

1570870480183

1570870634977

1570870706500

只有分组的才会有参数更他对应,不加括号的确定没有参数和他对应


有名分组

?P<>起有名分组 ==这个是老版本的了,注意DJ2.0以后就不是这么玩的了==

1570871061897

1570887244243

人家在前端起好什么名字,你这边就得叫什么名字

1570871133157

1570871196644

1570871293814


提交注册

首先经过url进入regist

1570872383302

而后写完后,点击提交,这个前端访问一个连接,这个连接仍是指向了regist

1570872515193

能够经过一个视图作两件事,只要他们的方式不一样就行

1570872648547

同源的概念

1570873014959

url部分别名的一个概念

==这个reg对应上能够这么理解:在html里写的时候就是在找 这个表单的信息给服务器的哪一个函数去执行呢(这个函数确定往前就是对应的一个连接了),,而后后端path(URL)那边气的别名,就是指示那个去执行表单提交过来的信息的函数==

1570873299123

1570873446835


09 URL的分发

URL如今都在全局的一个项目里面了,若是项目多了就很差使了。没有一个很好的解耦。

但愿全局作一个分发,发到我的。

1570873610597

1570873824700

1570873860376


day50

01 视图函数的介绍 view

1570929275271

​ 推荐使用render问题少。。了解下面那个方法,由于其余人用

1570929632540


把局部变量转换成键值对的locals,

request也是局部变量,因此也能够传过去,还能够用里面的属性

1570929933963

1570930098207


跳转函数:redirect

从一个视图里作完了须要去另外一个页面,就用这个

1570930534195

跳转和直接render的区别:

1570931553669


03 Django魔板之变量

模板的组成:HRML代码+逻辑控制代码

逻辑控制代码的组成

pycharm里面搞到shell的方法

1570934006642


这个render到底隐藏了哪些?

日后面传不必定是字符串,列表啊 字典啊 类啊 均可以滴 万能句点符号

1570933908055

1570934864213

1570934994409


04 魔板之过滤器

内置函数 处理字符串方便一些

1570935697914

1570935919214


05 魔板控制语句的使用

1570937062601

计数器

1570937395356

各类计数器

1570937741470

1570937851908

遍历到某个元素若是是空的时候作出什么处理

1570939088538


06.标签tag补充

1570941729179

Django第一次post是禁止的,除非带着身份验证的token数据。

这个流程就是用浏览器访问的时候会把这个秘钥发过来,,而后post提交的时候会带着秘钥一块儿去

1570941942355


07 莫模板之自定义filter和simple_tag

1570942597020

1570943005965

这个整完了得重启一下,好像是路径不能自动的更新

这个传的变量的个数,就是一个,若是要多个,那就弄个列表

1570943436002

1570943136741

1570943378583

自定义标签的参数不限制,能够有多个

1570944145144

1570944213099

1570944308632

1571308294549


08 模板之继承标签 就是不停的写盒子

建一个新的Django

1571023561104

先搭出一个这样的框架

先写一个基础了html,里面分块,这个块就是能够修改的。

1571023632076

1571024742422

字版的第一句话就是集继承过来

1571024934515

1571025020546

1571025328319

include添加

1571030204119

1571030257641

day51 数据库

01 数据库表与表之间一对多多对多的关系

多对多的关系用三张表

1571055431197

一对一,两张表怎么弄

1571055800223

其实数据库只是提供了一对多的关系,多对多的关系个一对一的关系都是从一对多的关系上改过来的。

02 Django的ORM概念

ORM 对象关系映射表

经过python的类对数据路的表进行操做

1571057118544

==建立数据库的两个语句==

makemigrations 和 migrate

D:\Python37\python37.exe manage.py makemigrations (这一步只是建立了一个脚本,并无和数据库打交道,在blog下的migration文件夹里建立的脚本)

D:\Python37\python37.exe manage.py migrate

1571057611870

1571057729689

默认是链接sqlite数据库,若是是要链接mysql数据库,须要在设置里作一些修改

1571058184778

1571058651897

链接mysql是修改修改成pymysql引擎

1571058526719


03 ORM中的增删改查操做

改动一下表的字段

1571060022876

1571060143222

1571060430508


方式一:

1571060983078

方拾二:

1571061645096

1571061745398


法一 :这种方法是能够同时改多个的 。这种update的方法效率高,单对单,就改一个。

1571062887808

法二 :这种方法只能改一个 save效率低,由于没有改动的也会给更新一下

1571063632244

经过设置,打印出ORM执行时所使用的sql语句的日志

1571063905090

1571063956886


删除

1571064030382


04 ORM查询API

1571064667810

1571064887376

1571065036632

1571065131768

1571065864783

1571110972153

1571112798279

1571112860273

1571112489708

双下划线的特殊功能,模糊查询

1571113118015

day52 ORM多表操做

外键关联时的2.0版本新注意点

一个2.0版本的新要求,视频的版本没有这个

1571140551660

02 多表操做之一对多查询之对象查询

1571114129453

一对多的直接点出来确定是一个对象

1571114181667


涉及到外键的一些查询

方法一: 有点麻烦

1571115001198

方法二

publish找book表关联的内容

1571133437404

1571134035850

==这个后面接04 03是补充的,有些错乱==

03 一对多增长记录

publish加上引号就是按照映射关系去找,也就是加载完去找,因此能够publish这个类放在book这个类的哪里都行。可是若是publish不加上引号,那就是按照变量关系去找的了,那么publish这个类就得放在book这个类的上面。

1571144538222

1571144969531

1571145675768

1571146262982

04 ORM多表操做之基于双下划线查询

上承接02,多表查询的任务(找符合外键条件的一个任务)

1571147394346

1571147659689

1571147808891

1571148118742

05 多对多添加记录

推荐自动带的那个方式 manytomany

多对多前提是有两张多对多的表

1571150744030

1571151188820

1571152371210

1571152756334

1571152835168

1571153516409

==上述第三个表(本身写的那个表)的方法不经常使用,这个多是一家之言,主要是以为麻烦==

1571153681831

06 多表操做之多对多聚合查询

1571208661470


聚合函数

1571209053077

1571209134233

1571209414526


分组

能够理解为:先分组,而后sum是对每一个组进行操做

1571210030016

1571210508567

07 ORM多表操做之F查询与Q查询

1571211414655

1571211592172

1571213270379

1571213181791

08 ORM的querySet集合对象的特性

1571213711949

1571214258243

1571214591329

生成器的做用就是:节省内存

数据量很少还反复要用的话,缓存就行。

若是数据量万级别以上,仍是建议用迭代器

1571215101871

day53 admin,cookies,session

01 admin的介绍

Django牛逼的组件

url

views

models

templates

admin

1571217241501

1571218005897在、

注册->建立超级用户->在页面里看

03 自定义admin样式

admin关于数据库的后台管理

如今想在原来的上面横着显示一堆字样 ,,须要先写已给类,,而后告诉admin

1571225329198

1571225488966

1571225496395


1.让框子变的可修改

2.listdisable里不能加多对多的关系

1571225772183


1571226268653

1571226386813


1571227063578

1571227152749


1571227317110

1571227505595


1571229415727

显示字段的时候换个别名

1571229574265

按照某个字段排序

1571231917235

1571232068670

1571232283266

05 cookie介绍

1571238923614

1571239109105

06 cookie和session的配合使用

cookie和session都有默认放在某个表里的,因此若是要用这个你就须要把这个表给初始化出来。(用migrate的那些指令)

若是只有一个cookie的话,全部信息都放在客户端,不安全,容易被窃取。

cookie就像是客户端的钱包

session就像是服务端的钱包

session在Django里会默认存到数据库里

若是排除安全和你不嫌弃来回传输慢的化,cookies也是能够本身完成这些功能的,事实上人们一开始也是这么作的,后来拿session来解决cookies遇到的问题的。 我把钥匙(cookies)给你你下次带着钥匙来,用户的哪些资料(session对应的东西)我都放在数据库里面。拿着钥匙打开了数据库的内容。

1571295707891

1571288069245

1571288219542

1571288402664

1571296198353

1571296363496

1571296573927

1571296703290

登陆的时候若是用户名和密码对应上了,那就把两个关键字(islogin和user)存到session里。每次登陆index页面的时候都去看一下session里(按照islogin键去找)的islogin是否是为true,若是是true就继续往下走,若是不是true那就返回登陆界面,让用户登陆。

def login(request):
    print("cookies",request.COOKIES)
    print("sessions",request.session)

    if request.method=="POST":
        name=request.POST.get("user")
        pwd=request.POST.get("pwd")
        print("name=======",name)
        print("pwd==========",pwd)
        if name=="yuan" and pwd=="123":#这边在假设若是登陆成功了
            #若是登陆成功了,就给这两个保存起来
            #session会自动把这个存到数据库里面。
            request.session["is_login"]=True
            request.session["user"]=name
            return redirect("/index")
    return render(request,"login.html")#若是没有登陆成功,就是还返回其login的界面

def index(request):
    if request.session.get("is_login",None):
        name=request.session.get("user",None)
        print("!!!!!!!!!!!!!!!!!!!!!!!!!!!",name)
        return render(request,"index.html",{"name":name})
    else:
        return redirect("/login")

day54 Django请求生命周期

04 复习以前的内容

在pycharm里给Django再建一个app

05 请求生命周期之Http请求

1571312491189

1571312753730

Django的请求的生命周期是什么?

生命周期指的是用户在浏览器上一点,在你的浏览器上都发生了什么。---

这个是简单的流程

1571319376862

06 CBV的写法

路由分发里是个类CBV式的编程

1571317285625

1571315754722

07 CBV扩展

找到类后,不会首先执行get或post方法,而是执行继承的view里的那个dispatch方法,dispatch方法帮助咱们反射找到要执行的get仍是post方法。

渲染完的页面返回的时候,也是先返回给dispatch而后再返回给用户。1571316563126

1571317199032

08 瞎扯淡

09 响应内容

加响应头

1571319283910

10 响应内容二

完整的建一个Django文件

1571319799864

1571319741136

1571319731040

11 学管-数据库设计

1571320915119

1571321204500

12 班级管理 单表操做

1571322702712

1571322816303

1571323082383

1571323018802

1571323269330

1571323506332

1571323635412

1571323691344

1571323951178

1571324455513

1571324388751

1571324572682

1571324734998

1571324822159

1571324845057

1571325044508

1571325125646

这边还得加一个token钥匙,否则post不过去

1571325277314

1571381957453

13 学员管理,多表操做

1571385582998

1571386097918

day55 Django学员管理示例1

01 复习ORM基本操做概要

单表的CRUD

1571403181811

一对多的CRUD

1571404543386

filter和values的跨表都是经过双下划线来实现的

1571404393885

多对多

1571405604373

1571405715130

1571405887200

1571406004790

1571406454516

02 一对多补充

找学生属于哪一个校区,,跨多个表

1571410385350

1571411599184

03 一对多补充二

反向查找默认是字段_set_这种形式,是能够改的。

1571560465377

1571560699919

1571561015604

1571561141211

04 编辑学生

这集没啥特别的重点,一个是一对多表的CRUD,还有一个就是模板语言里怎么将下拉列表的框框变成默认的,就是怎么checked。

05 多对多补充 CRUD

1571564944106

1571565102028

若是定义了related_name,就经过related_name对它进行反向操做

1571565275082

1571566104048

总结一下

1571566182488

06 多对多补充二 跨表

感受不到第三张表的存在,这就是manytomany的魅力。

多对多的反向必须加上relatedname,,不加就不能反向查了。

1571566893147

1571567033523

加了value就是数字了,就不能再点了

1571567258743

07 为班级分配老师

1571573032928

1571573244153

1571573718339

1571573828273

1571574398790

1571657975050

1571574872983

1571575002984

1571575091602

08 Ajax的简单应用

1571575859125

1571576054932

1571576131133

1571576706398

1571577354021

1571577806339c

09 Ajax删除学生

1571660626875

1571661081703

1571661178052

day56

03 bootstrap和fontawesome制做界面

bootstrap

对static里面的内容分个类

1571661659767

1571662030434

1571662119019

1571662218022

1571663627202

1571663746198

1571664115888

http://fontawesome.dashgame.com/ 专业图标 注意下面的使用方法

1571669100053

1571669466977

经过写ID绑定触发的方式把按钮和模态关联起来。

1571711797881

选两个标签的时候注意这个写法啊,一个引号里面写逗号

1571726271408

1571726276134

1571726427458

无心中调试出的一个知识点

1571737247454

1571733375745

1571726699277

1571733633264

1571727276487

1571728345841

1571728427161

06 建立学生信息二

1571743437024

1571744650017

须要值得注意的是:可能会出现,刚开始加页面时给全部的控件都绑定了事件,而后再ajax添加新的表单行后忘记给行里面的控件添加新的事件(57-bug修复)

解决方法,用事件委托来解决,何时点击,何时绑定。

1571752857221

1571747376833

1571753749329

1571747400623

day57

01 复习

1571746091268

1571746413185

02 学生管理系统编辑学生信息以前端功能

方式一:

1571748035785

1571748343061

方式1的缺点就是,和格子的对于关系太严格了。要是再增长一列就完犊子了。


方法二:

1571750300653

1571817701534

方法二的思想就是经过给每个td上增长一个属性,而后经过js对各个表格进行精准的操做。这样的好处就是即便外面的再增长或者删除或调换一列,这个js代码都不须要大换。

<div class="container">
    <table class="table table-bordered table table-striped" id="tb">
        <thead>
        <th>姓名</th>
        <th>性别</th>
        <th>年龄</th>  
        <th>班级</th>
        <th>操做</th>
        </thead>
        <tbody id="tb">
        {% for row in stu_list %}
            <tr nid="{{ row.id }}">
                <td na="user">{{ row.username }}</td>
                <td na="gender">{{ row.gender }}</td>
                <td na="age">{{ row.age }}</td>
                <td na="cls_id" cid="{{ row.cs_id }}">{{ row.cs.title }}</td>
                <td>
                    <a href="del_students.html?nid={{ row.id }}">删除</a>
                    |
                    <a class="edit-row">编辑</a>
                </td>

            </tr>
        {% endfor %}
        </tbody>
    </table>
</div>
function bindEditStudent() {
        $("#tb").on("click",".edit-row",function () {
            {# 首先把那个增长的模态页面给打开 #}
            $("#editstudentmodal").modal("show");
            {# 打开后就要在这个上面去显示选中的那一行的值 #}
            {# 取出那一行每一个小个子td里面的值 #}
            $(this).parent().prevAll().each(function () {
                {#对那一行里的每个元素进行轮询#}
                var v=$(this).text();
                var n=$(this).attr("na");
                console.log(v)
                if (n=="cls_id")#特殊的特殊处理吧,这个须要拿到的是对于班级的id。。
                {
                    //为了这个特殊处理,在html里给这个增长了cid属性
                    var cid=$(this).attr("cid");{#拿到了这个学生对应的班级的id#}
                    $('#editmodel select[name="cls_id"]').val(cid);
                } else if(n=="gender"){ 
                    //性别也特殊,是单选按钮,经过
                    if (v==true){
                        $("#editmodel :radio[value='0']").prop("checked",true);
                    }else {
                        $("#editmodel :radio[value='1']").prop("checked",true);
                    }
                }else {
                    //n=age
                    //v=12
                    $("#editmodel input[name='"+n+"']").val(v);
                }

            })
        });
    }

这张图的cid没有赋值,看下一张

1571751213108

1571751260902

05小总结

增长,编辑的时候建议使用普通的刷新页面的方式,删除的时候建议使用ajax的方式

1571818703788

6 ajax功能之dataType和traditional

1571819162204

1571819504464

1571819251631

1571819329039

若是非要发字典,把字典用json变成字符串日后发

1571819402853

day58

1571827052411

04 分页的基础知识

1571828183403

05 内置分页的用法

1571828471865

1571829878251

1571828982250

1571829772947

1571829963837

def index(request):
    userList=[]
    for i in range(1,1000):
        temp={"name":"root"+str(i),"age":i}
        userList.append(temp)
    current_Page=request.GET.get("p")#当前想要获取哪一页
    paginator=Paginator(userList,10)#传入总共的个数,和一页显示多少个
    try:
        posts=paginator.page(current_Page)
    except PageNotAnInteger:
        posts=paginator.page(1)
    except EmptyPage:#当向page()提供一个有效值,可是那个页面上没有任何对象时抛出
        posts=paginator.page(paginator.num_pages)
    return render(request,"neizhifenye.html",{"posts":posts})
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    {#把后端传过来的列表循环的显示出来#}
    {% for item in posts.object_list %}
      <li>{{ item.name }}-{{ item.age }}</li>
    {% endfor %}

    {% if posts.has_previous %}
        <a href="neizhifenye?p={{ posts.previous_page_number }}">上一页</a>
    {% endif %}
    {% if posts.has_next %}
        <a href="neizhifenye?p={{ posts.next_page_number }}">下一页</a>
    {% endif %}


</head>

06 扩展内置分页的一些功能

1571832693201

1571832797460

对Django自带的分页功能进行扩展后,前端和后端部分关键代码

这个可使用include形式,就是在前端页面把页码选择的那一行数据放到一个include的文件夹里,须要用的时候调出来用。。这样增长前端代码的复用率。

{% for item in posts.object_list %}
      <li>{{ item.name }}-{{ item.age }}</li>
    {% endfor %}

    {% if posts.has_previous %}
        <a href="neizhifenye?p={{ posts.previous_page_number }}">上一页</a>
    {% endif %}

    {% for i in posts.paginator.paper_num_range %}  //这边注意先.出paginator 再paper_num..
        {% if i == posts.number %}  {# 到了当前页的给大写一下 #}
            <a style="font-size: 30px;" href="neizhifenye?p={{ i }}">{{ i }}</a>
        {% else %}
            <a href="neizhifenye?p={{ i }}">{{ i }}</a>
        {% endif %}
    {% endfor %}

    {% if posts.has_next %}
        <a href="neizhifenye?p={{ posts.next_page_number }}">下一页</a>
    {% endif %}
#扩展内置分页的一些功能
class CustomPaginator(Paginator):#继承于原理的paginator类
    def __init__(self,current_page,per_pager_num,*args,**kwargs):
        self.current_page=int(current_page)#当前页
        self.per_pager_num=int(per_pager_num)#一页显示多少条
        super(CustomPaginator,self).__init__(*args,**kwargs)
    def paper_num_range(self):#这个就是扩展的那个功能
        #self.num_pages 总共的页数  这个参数是从父类那里继承过来的
        #self.current_page  当前页(就是浏览器申请访问的那个页面)
        #self.per_paper_num  最多显示页码的数量
        if self.num_pages<self.per_pager_num: #若是总共须要的页数还比下面显示出来的页数少
            return range(1,self.num_pages+1)   #那就把总共的页数都显示出来
        #若是总共须要的页数特别多
        part=int(self.per_pager_num/2)  #拿到下面一共要显示多少栏的一半的值
                                        #好比下面要显示11个  那就取通常5个

        if self.current_page<=part:   #若是当前要显示的页码 比通常要写
            return range(1,self.per_pager_num+1) #这种状况就是  你如今要第2页,下面显示11个跳转页面的按钮
                                                  #那就应该显示1--11

        if (self.current_page+part)>self.num_pages:#这种状况就是最后那几个  当前要的页面 已经很接近最后那几个了,这时候就显示倒数后面几个就行
            return range(self.num_pages-self.per_pager_num+1,self.num_pages+1)

        #若是上面的if都没有能经过,那就是最最普通的通常状况了
        return range(self.current_page-part,self.current_page+part+1)

def index1(request):
    userList=[]#模拟要显示的东西
    for i in range(1,1000):
        temp={"name":"root"+str(i),"age":i}
        userList.append(temp)

    cuurent_page=request.GET.get("p")
    paginator=CustomPaginator(cuurent_page,7,userList,10)
    try:
        posts=paginator.page(cuurent_page)
    except PageNotAnInteger:
        posts=paginator.page(1)    #若是取到的不是整数,那就默认显示第一页
    except EmptyPage:#若是是空页面 说明过界了 那就显示最后一页
        posts=paginator.page(paginator.num_pages)
    return render(request,"neizhifenye.html",{"posts":posts})

08 Django的form组件

这个里面的名字(user pwd)必须和前端提交过来的同样(也就是required.post)里面存储的同样才行。这样Django才会有办法自动识别去找了比较。

1571833718045

1571834729543

1571835091662

1571835183467

1571914135781

代码:

后端代码

from django.shortcuts import render ,redirect,HttpResponse
from django import forms
from django.forms import fields
class F1Form(forms.Form):
    #对form表单里的数据类型进行限定
    #注意这个名字不能瞎写,须要和前端传过来的那个同样
    user=fields.CharField(max_length=18,
                          min_length=3,
                          required=True,
                          error_messages={"required":"用户名不能为空",
                                          "max_length":"太长了",
                                          "min_length":"过短了",
                                          "invalid":"..",#全部的格式错误关键字都是invalid
                                          }
                          )
    pwd=fields.CharField(min_length=6,required=True)
    age=fields.IntegerField(required=True)
    email=fields.EmailField(required=True)
def form(request):
    if request.method=="GET":
        obj=F1Form
        return render(request,"form.html",{"obj":obj})#这个地方传过去是由于能够利用这个本身生成#                                                      #HTML
    if request.method=="POST":
        obj=F1Form(request.POST)#这个地方特别注意是request.POST而不是request否则会报isvalid的错误
        #是否所有验证成功
        if obj.is_valid():
            #print("验证成功",obj.cleaned_data)
            return redirect("http://www.baidu.com")
        else:
            print("验证失败",obj.errors)
            return render(request, "form.html", {"obj": obj})

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    <form id="fm" action="formtest" method="post">
         {#前端利用了传来的form对象自动生成HTML#}
        <p>姓名{{ obj.user }}{{ obj.errors.user.0 }}</p>
        <p>密码{{ obj.pwd }}{{ obj.errors.pwd.0 }}</p>
        <p>年龄{{ obj.age }}{{ obj.errors.age.0 }}</p>
        <p>e-mail{{ obj.email }}{{ obj.errors.email.0 }}</p>
        <input type="submit" value="提交">
    </form>
</body>
</html>

day59

当天的课上笔记

参考博客:                
http://www.cnblogs.com/wupeiqi/articles/6144178.html

Form
    1. 验证
    2. 生成HTML(保留上次输入内容)
    3. 初始化默认是

Form重点:
    - 字段
        用于保存正则表达式
        ChoiceField *****
        MultipleChoiceField
        CharField
        IntegerField
        DecimalField
        DateField
        DateTimeField
        EmailField
        GenericIPAddressField
        FileField
        
        RegexField
    - HTML插件
        用于生成HTML标签
        
    - 特殊的单选或多选时,数据源是否能实时更新?????*****
        from app01 import models
        class LoveForm(forms.Form):
            price = fields.IntegerField()
            user_id = fields.IntegerField(
                # widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),])
                widget=widgets.Select()
            )

            def __init__(self,*args,**kwargs):
                super(LoveForm,self).__init__(*args,**kwargs)
                self.fields['user_id'].widget.choices = models.UserInfo.objects.values_list('id','username')
                
        from django.forms.models import ModelChoiceField
        from django.forms.models import ModelChoiceField
        class LoveForm(forms.Form):
            price = fields.IntegerField()

            user_id2 = ModelChoiceField(
                queryset=models.UserInfo.objects.all(),
                to_field_name='id'
            )
        
        注意:依赖models中的str方法

01 form组件

取数据和保存到数据库的方式

cleand_data就是获取传过来的数据

更加简洁的方式往数据库里存储数据

1571914358875

1571914798312

get请求后在userform里面设置默认值,这样返回到页面渲染后,控件就是有默认值的了

1571915210011

02 form组件之字段

经过用这个组件,能够定制更多的HTML标签

1571919111554

1571916212179

这个select就是多选的下拉框

1571916465133

1571916730087


两种设置控件默认值(也就是这个控件在页面上显示什么值)的方法

  • 一种是建立form对象的时候传,这个时候能够初始化全部的控件值

  • 一种是建立控件的时候传,这个时候只能初始化所在的这个控件的值

1571916969553


一句话生成全部控件的方法,不推荐这儿作,由于虽然方便,可是调整样式的时候就麻烦了。

1571917618070


form表单传输文件的时候须要加上这句话,否则文件传输不过来的

1571919442652

1571919608275


单选框和多选框给默认的初值

1571919958561

1571920342623

1571920459939


用的不算太多,不知道用在什么场合

1571921046102

1571921032630

1571921454403


1571922083652

这些本质就是帮咱们作了正则表达式的封装

04 form组件字段详解3

每个field里面都封装了一个正则表达式 + 一个默认插件。。这个默认插件就是在_str里,_str就是调用的时候输出的那个文本。

1571925101008


额外插的一个知识点:后端往前端传输一个字符串,怎么就能让前端知道这个字符串的意思不是普通的字符串,而是表明的HTML标签呢。

1571925325273

1571925515095

1571925944140

1571926431646

1571926532826

1571928905796

1571929996072

day60

复习:简单的扩展就是若是自带的正则表达式已经不能知足你的需求了,那么如何扩展或者是说本身定义正则表达式,有多是多个正则表达式来验证。

复杂的扩展就是对内容进行一些判断了,若是内容已经有了,那怎么弄。

课上笔记

1.简单扩展
        利用Form组件自带的正则扩展:
            a. 方式一
                from django.forms import Form
                from django.forms import widgets
                from django.forms import fields
                from django.core.validators import RegexValidator
                 
                class MyForm(Form):
                    user = fields.CharField(
                        error_messages={'invalid': '...'},
                        validators=[RegexValidator(r'^[0-9]+$', '请输入数字'), RegexValidator(r'^159[0-9]+$', '数字必须以159开头')],
                    )
            b. 方式二
                from django.forms import Form
                from django.forms import widgets
                from django.forms import fields
                from django.core.validators import RegexValidator
                 
                class MyForm(Form):
                    user = fields.RegexField(r'^[0-9]+$',error_messages={'invalid': '...'})
                    
    2.基于源码流程
        a. 单字段
            from django.core.exceptions import NON_FIELD_ERRORS, ValidationError
            class AjaxForm(forms.Form):
                username = fields.CharField()
                user_id = fields.IntegerField(
                    widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),])
                )
            # 自定义方法 clean_字段名
            # 必须返回值self.cleaned_data['username']
            # 若是出错:raise ValidationError('用户名已存在')
            def clean_username(self):
                v = self.cleaned_data['username']
                if models.UserInfo.objects.filter(username=v).count():
                    # 总体错了
                    # 本身详细错误信息
                    raise ValidationError('用户名已存在')
                return v
            def clean_user_id(self):
                return self.cleaned_data['user_id']
                    
                 
        b. 总体错误验证
            class AjaxForm(forms.Form):
                username = fields.CharField()
                user_id = fields.IntegerField(
                    widget=widgets.Select(choices=[(0,'alex'),(1,'刘皓宸'),(2,'杨建'),])
                )
                # 自定义方法 clean_字段名
                # 必须返回值self.cleaned_data['username']
                # 若是出错:raise ValidationError('用户名已存在')
                def clean_username(self):
                    v = self.cleaned_data['username']
                    if models.UserInfo.objects.filter(username=v).count():
                        # 总体错了
                        # 本身详细错误信息
                        raise ValidationError('用户名已存在')
                    return v
                def clean_user_id(self):
                    return self.cleaned_data['user_id']

                def clean(self):
                    value_dict = self.cleaned_data
                    v1 = value_dict.get('username')
                    v2 = value_dict.get('user_id')
                    if v1 == 'root' and v2==1:
                        raise ValidationError('总体错误信息')
                    return self.cleaned_data
                    
                    
        PS: _post_clean

01 form表单的回顾

如何把一个表单序列化,而后用ajax的方式传输出去

image-20191026160159424

image-20191026161159400

image-20191026161442605


是什么致使了这个不是python内部的数据类型却可以转换成json,是由于他继承于dic

image-20191026163429709


02 在form里自定义方法

规则:自定义方法clean_字段名,必须返回值self。cleaned_data[“username”],若是出错:raise validationerror(“用户名已经存在”)

这个本身写clean函数须要有返回值,由于源码里是拿到返回值从新赋值给data。。

本身的感受:这两步的意思就是先检查格式,再检查内容。检查格式的人家已经给写好了正则表达式,

检查内容内容的须要本身去写,本身去写的过程当中注意去知足别人的格式。

image-20191026172843245

image-20191026172957910

image-20191026175128208 导入validation的命名空间

image-20191026174700082

image-20191026175052829

03 全局校验的钩子

有时候进行验证须要用到不少的前面传过来的数据,这个时候放在单一的那个变量里显然显得十分的不合适,

这个时候就须要咱们在全部的单一的执行完了以后,再有一个能够执行全局的校验的函数。

image-20191026182031247

image-20191026182037704

05Django的序列化

把某种东西可以保存在文件里的过程,叫作序列化

这种[ob,obj...]的只能经过Django给的那种方式进行序列化

image-20191026202925313

这个里面的data数据至关于被序列化了两次,那么前端也要解两次。 success回调的那个arg至关于已经帮忙解开一次了,里面只要再解开一次就行。

image-20191026203336008

经过values获取的时候怎么转换成json的格式

image-20191026204148150

总结来讲,返回的是对象的时候采用内置的序列化方法,而后前端也要反序列化两次

Django序列化
    a.对象    ----用内部的
    b.字典
    c.元祖
    
序列化:在JavaScript里用的是:JSON.parse() ,JSON.stringfy()
Django里 json.dumps()和json.load() 这种python内置的序列化只能处理python内置的数据类型。为了解决
这个问题,用Django给提供的序列化一下,而后再总体序列化一下。意思就是那个不是数据类型的地方序列化的2次,因此前端那边也反序列化2次。
        Django:
            json.dumps()
            json.loads()
            问题:
                serilize:  model.TB.objects.all()
                
                json:  list(model.TB.objects.values())
                json:  list(model.TB.objects.values_list())

day61 ==听的不在状态==

01 回顾

  • ajax的日后台传时value不能是字典,若是非要传字典,能够先把这个字典转化为字符串再传输过去。
  • serilize就是将ajax的表单序列化,传给后台,这样比较方便

image-20191028144052294

内容回顾:
    1.ajax参数  
        url:
        type:
        data:
            1. value不能是字典 {k1:'v1',k2:[1,2,3,],k3: JSON.stringify({})}
            2. $('').serilizer()
        dataType:"JSON",# text,html,xml
        单词太长了 traditional:
        success:function(arg){
            # arg=>obj
        },
        error:function(){        
        }
    2. 序列化
        JavaScript:
            JSON.parse()
            JSON.stringify()   
        Django:
            json.dumps()
            json.loads()
            问题:
                serilize:  model.TB.objects.all()
                
                json:  list(model.TB.objects.values())
                json:  list(model.TB.objects.values_list())    
    3. Form
        做用:用于验证+(生成HTML+保存上次提交的数据)
        使用:
            1.建立类
            2.建立字段()
            3. 验证用户输入:
                obj = Form(request.POST,request.FILES)
                if obj.is_valid():
                    obj.cleaned_data
                else:
                    obj.errors
            4. clean_字段
            5. clean()  _post_clean()
         
            PS: __all__              
    4. 分页组件
        a. 内置
        b. 扩展
        c. 自定义
    5. XSS攻击
        跨站脚本攻击:
            
        防止:
            - 其余人输入的内容     不用safe
            - 本身输入的内容       可用safe
        
        
        <script>
            for(var i=0;i<9999;i++){
                alert(i)
            }
        </script>
        
         
        <script>
            获取本地cookie,发送到另一个网站
        </script>
        
        
今日内容:

    - 文件上传
        - 普通上传
        - 自定义页面上传按钮
        - 基于Form作上传
        - Ajax上传文件?????
        
    - Django Model操做补充
        参考博客:http://www.cnblogs.com/wupeiqi/articles/6216618.html
        1. 建立类
            class UserInfo(model.Model):
                
                age = CharFiled(是否为空,类型,长度,列名,索引=True||||错误提示,自定义验证规则)
                ..
                ..
                
                ### 一对多
                ### 一对一
                    - 
                
                
                ### 多对多
                    - 第三张表:a.自动建立;b.手动建立; c. 手动+自动
                
                    ### 自关联:互粉 ###
                    
            a. 索引
            b. 一对多: on_delete
            c. 一对一和一对可能是什么关系? unique=true
            d. 多对多:
                - a.自动建立;b.手动建立; c. 手动+自动
                - ### 自关联:互粉 ###
                
            PS:related_name
            
        2. 操做类
            obj = UserInfo.objects.all().all().all()

02 上传文件 image-20191028151445170

image-20191028151758778

image-20191028152139850

image-20191028152419956

上传的图标的制做

image-20191028155054229

image-20191028155423984

image-20191028160007564

08 数据库拾遗

image-20191028170231001


三种索引

  • 一种是只能加速查找
  • 一种是除了加速查找 还能保证惟一
  • 一种是除了加速查找保证惟一以外 还不能为空

image-20191028172530292

image-20191028172614838


对admin进行一些操做

image-20191028173405451

image-20191028173518783


对外键删除的时候作一些设置 就是你删除关联的时候其余人会怎么反应

image-20191028175954636

image-20191028181233107

image-20191029103831084

image-20191029104118847

联合惟一,就是好比给一我的打标签 一种标签只能打一次对一我的

image-20191029105146508

这样写就能够经过m对这个操做了。本身定义第三张表,m的add和set就不能用了,filter还能够用。

这样容易乱,不是很推荐

image-20191029113111867

11 强插的面试题

image-20191029110701804

image-20191029111752441

image-20191029115639068

必须的要会的

image-20191029144658379

ps:推荐写relatedname


image-20191029150214193

image-20191029150345043

下面可能会出现跨表操做的时候就加上related,加一个或者加两个都是能够的。

image-20191029150826455


image-20191029151206940

image-20191029151330171

image-20191029151550294

using指定链接哪一个库

image-20191029154249972


两个js面试题

image-20191029155610002

题1:代码在执行前做用域已经建立,执行的时候按照做用域去找值就对了

返回inner函数没有拿到外面来,不拿,人家在编译的过程当中做用域就已经生成了。result是代指inner函数,inner函数有本身的做用域

image-20191029160928439

因此第一个题目的答案是456

第二题:
js里没有类,通常用函数来充当类,函数充当类的时候,通常默认把函数名的首字母大写。

image-20191029165531467

image-20191029170011779

==后面关于数据库的很对操做没有看,有点复杂,用过一段时间后再回来看==

这个建议去武沛齐的博客上看

day62

02 发送ajax的jQuery方式和自带的方式

image-20191029180018566

image-20191029193802373

image-20191029194418371

这样发过去会有一个问题,Django的后台不知道这个究竟是get仍是post,没法解析出这个body里面的数据

因此就会发现post和get里面没有数据,可是body里面有数据。

image-20191029195059608

image-20191029200825525

03 伪发送ajax的方式

image-20191029201955546

基于ireame和form表单实现的伪造ajax

form提供数据 irame提供通道 把数据发过去

image-20191029202451459

image-20191029202751275

irame的兼容性是最好的

不用动态绑定会出现的一个问题就是,重上到下进行刷新的时候可能会出现上面的用到下面的函数,可是尚未刷新到下面的函数的状况。

image-20191029203555439

image-20191029205035515

image-20191029205542170

在标签上绑定的时候那个this为window,动态绑定this不要传递,由于内部的那个就是当前标签

image-20191029214651658

image-20191029214725247

image-20191029215028673

image-20191029220204995

11 jsonp跨域

jsonp是一种方式,添加到scrapt块里,而后在再删除掉。从而实现跨域的请求。

jsonp是一个规则,远程传过来时函数包裹着数据

image-20191030093524897

jsonp只能用get,即便你用post,内部也会用get

image-20191030094110020

image-20191030094808713

相关文章
相关标签/搜索