django知识回顾

一、web框架

1、web框架本质

众所周知,对于所有的web应用,本质上其实就是一个socket服务端,用户的浏览器其实就是一个socket客户端

1、浏览器(socket客户端)
2、发送IP和端口:http://www.baidu.com:80/index/
3、请求方式:
    GET:请求头:  如:http1.1 /index?p=123
        请求体:  无内容

    POSt:请求头   http1.1 /index?p=123
          请求体  

4、接收响应
普通响应:页面直接显示 
重定向响应:再起一次Http请求


服务器(socket服务端)
1、启动并监听ip和端口,等待用户连接
接收请求进行处理,并返回
普通返回:
响应头:
        Access-Control-Allow-Origin:*
        Cache-Control:max-age=600
        Date:Mon, 19 Jun 2017 00:57:43 GMT
        Expires:Mon, 19 Jun 2017 01:07:43 GMT
        Last-Modified:Wed, 24 May 2017 01:51:55 GMT
        Server:GitHub.com
        X-GitHub-Request-Id:C495:5EBC:8739EF:B817EE:59472187

响应体:
        <html>
        ....
        </html>

重定向返回:
    响应头:
            LOCATION: 'http://www.baidu.com'
            Access-Control-Allow-Origin:*
            Cache-Control:max-age=600
            Date:Mon, 19 Jun 2017 00:57:43 GMT
            Expires:Mon, 19 Jun 2017 01:07:43 GMT
            Last-Modified:Wed, 24 May 2017 01:51:55 GMT
            Server:GitHub.com
            X-GitHub-Request-Id:C495:5EBC:8739EF:B817EE:59472187
View Code

WSGI(Web Sever Gateway Interface)是一种规范,它定义了使用python编写的web app与web server之间接口格式,
实现web app与web server间的解耦

2、自定义Web框架

通过python标准库提供的wsgiref模块开发一个自己的Web框架

from wsgiref.simple_server import make_server
 
def index():
    return 'index'
 
def login():
    return 'login'
 
def routers():
     
    urlpatterns = (
        ('/index/',index),
        ('/login/',login),
    )
     
    return urlpatterns
 
def RunServer(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']
    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == url:
            func = item[1]
            break
    if func:
        return func()
    else:
        return '404 not found'
     
if __name__ == '__main__':
    httpd = make_server('', 8000, RunServer)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()
Views
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>Index</h1>

</body>
</html>

HTML:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <form>
        <input type="text" />
        <input type="text" />
        <input type="submit" />
    </form>
</body>
</html>
html

对于上述代码,虽然可以返回给用户html的内容以实现复杂的页面,但是还是存在问题:如果给用户返回动态内容
自定义一套特殊的语法,进行替换
使用开源jinja2,遵循其指定语法

from wsgiref.simple_server import make_server
from jinja2 import Template
 
 
def index():
    # return 'index'
 
    # template = Template('Hello {{ name }}!')
    # result = template.render(name='John Doe')
 
    f = open('index.html')
    result = f.read()
    template = Template(result)
    data = template.render(name='John Doe', user_list=['alex', 'eric'])
    return data.encode('utf-8')
 
 
def login():
    # return 'login'
    f = open('login.html')
    data = f.read()
    return data
 
 
def routers():
 
    urlpatterns = (
        ('/index/', index),
        ('/login/', login),
    )
 
    return urlpatterns
 
 
def run_server(environ, start_response):
    start_response('200 OK', [('Content-Type', 'text/html')])
    url = environ['PATH_INFO']
    urlpatterns = routers()
    func = None
    for item in urlpatterns:
        if item[0] == url:
            func = item[1]
            break
    if func:
        return func()
    else:
        return '404 not found'
 
 
if __name__ == '__main__':
    httpd = make_server('', 8000, run_server)
    print "Serving HTTP on port 8000..."
    httpd.serve_forever()
    
Views
HTML:
<!DOCTYPE html>
<html>
<head lang="en">
    <meta charset="UTF-8">
    <title></title>
</head>
<body>
    <h1>{{name}}</h1>

    <ul>
        {% for item in user_list %}
        <li>{{item}}</li>
        {% endfor %}
    </ul>

</body>
</html>
html

遵循jinja2的语法规则,其内部会对指定的语法进行相应的替换,
从而达到动态的返回内容。

 

二、DjangoWeb框架

1、介绍Django

django:是一个由python写成的开放源代码的Web应用框架。

1、django
    #安装: pip3 install django
      添加环境变量

    创建project 
       命令:django-admin startproject mysite
       ---mysite

          ---settings.py
          ---url.py
          ---wsgi.py
      ---- manage.py(启动文件)
      
      
     创建APP       
      python mannage.py startapp  app01
      project
            - app01
                - admin   Django自带后台管理相关配置
                - modal   写类,根据类创建数据库表
                - test    单元测试
                - views   业务处理

   
2、配置文件

a: 静态文件:
在settings里修改添加,放css,js,image等文件
创建static文件夹

STATIC_URL = '/static/'  # 相当于别名
STATICFILES_DIRS = [
        os.path.join(BASE_DIR,'static'), #切记一定加逗号
]

b:模板:
在settings里修改,放HTML文件
 TEMPLATE_DIRS = (
        os.path.join(BASE_DIR,'templates')
    )  
   
   
c:数据库:
# django支持sqlite,mysql, oracle,postgresql数据库
# django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3
# 由于Django内部连接MySQL时使用的是MySQLdb模块,而python3中还无此模块,所以需要使用pymysql来代替
# 设置放置的与project同名的配置的 __init__.py文件中
 
__init__.py 导入
 
import pymysql
pymysql.install_as_MySQLdb() 


# 在settings 中修改DATABASES

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',
        'NAME': 'dbname',   # 数据库名称
        'USER': 'root',     # 用户名
        'PASSWORD': 'xxx',  # 密码
        'HOST': '',         # IP,留空默认localhost
        'PORT': '',         # 端口
    }
}  

d:新增app
   INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',
    'app02',
]
   
  


3、路由关系
    from app01 import views
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index.html$', views.index),
]
    

    
4、视图函数
def index(request):
     request.method
     request.GET
     request.POST
                        
    return HttpResponse('字符串')
    return redirect('URL')
    return render(request,'模板路径',{})
    # 1. 获取模板+数据,渲染
    # 2. HttpReponse(...)
    
5、模板渲染
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>模板标记学习</h1>
<p>{{ name }}</p>
<p>{{ users.0 }}</p>   //索引取值
<p>{{ users.1 }}</p>   //索引取值
<p>{{ user_dict.k1 }}</p>
<p>{{ user_dict.k2 }}</p>

例子:

urlpatterns = [
           url(r'^login/', login),  #后面配函数
           url(r'^index/', index),
           ]

def login(request):
    """
    处理用户请求,并返回内容
    :param request: 用户请求相关的所有信息(对象)
    :return:
    """
     #字符串
    # return HttpResponse("这个世界很美好".encode("utf8"))  #第一种返回字符串类型

    #自动找到模板路径下的login.html文件,读取内容并返回给用户
    #模板路径的配置 render
    if request.method=="GET":
        return render(request,'login.html')

    else:
         #用户POST提交的数据(请求体)
          u=request.POST.get("user")
          p=request.POST.get("pwd")
          if u=="root" and  p=="123123":
              #登录成功
              return redirect("http:www.oldboyde.com")    #重定向
          else:
              #登录失败
              return render(request,"login.html",{'msg':'用户名或密码错误'})
        # return render(request,'login.html')  #参数是什么,就传什么参数,后面也可以加参数

    
login.html
        <!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link rel="stylesheet" href="/static/commons.css">
</head>
<body>
<h1>用户登录</h1>
<form method="POST" action="/login/">
    <input type="text" name="user" />
    <input type="password" name="pwd" />
    <input type="submit" value="登录" />
    {{ msg }}
</form>
</body>
例子

2、 Ajax:

jQuery其实就是一个JavaScript的类库,其将复杂的功能做了上层封装,使得开发者可以在其基础上写更少的代码实现更多的功能。

jQuery 不是生产者,而是大自然搬运工。
jQuery Ajax本质 XMLHttpRequest 或 ActiveXObject

jQuery.ajax(...)

                部分参数:
                        url:请求地址
                       type:请求方式,GET、POST(1.9.0之后用method)
                    headers:请求头
                       data:要发送的数据
                contentType:即将发送信息至服务器的内容编码类型(默认: "application/x-www-form-urlencoded; charset=UTF-8")
                      async:是否异步
                    timeout:设置请求超时时间(毫秒)

                 beforeSend:发送请求前执行的函数(全局)
                   complete:完成之后执行的回调函数(全局)
                    success:成功之后执行的回调函数(全局)
                      error:失败之后执行的回调函数(全局)
                

                    accepts:通过请求头发送给服务器,告诉服务器当前客户端课接受的数据类型
                   dataType:将服务器端返回的数据转换成指定类型
                                   "xml": 将服务器端返回的内容转换成xml格式
                                  "text": 将服务器端返回的内容转换成普通文本格式
                                  "html": 将服务器端返回的内容转换成普通文本格式,在插入DOM中时,如果包含JavaScript标签,则会尝试去执行。
                                "script": 尝试将返回值当作JavaScript去执行,然后再将服务器端返回的内容转换成普通文本格式
                                  "json": 将服务器端返回的内容转换成相应的JavaScript对象
                                 "jsonp": JSONP 格式
                                          使用 JSONP 形式调用函数时,如 "myurl?callback=?" jQuery 将自动替换 ? 为正确的函数名,以执行回调函数

                                  如果不指定,jQuery 将自动根据HTTP包MIME信息返回相应类型(an XML MIME type will yield XML, in 1.4 JSON will yield a JavaScript object, in 1.4 script will execute the script, and anything else will be returned as a string
ajax
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        .btn{
            display: inline-block;
            padding: 5px 10px;
            background-color: coral;
            color: white;
        }
    </style>
</head>
<body>
    <h1>jQuery Ajax</h1>
    <h3>GET请求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit1();">点我</a>
    </div>
    <h3>POST请求</h3>
    <div>
        <a class="btn" onclick="AjaxSubmit3();">点我</a>
    </div>
    <script>
        function  AjaxSubmit1() {
            $.ajax({
                url: '/ajax1.html',
                type:'GET',
                data: {'p':123},
                success:function (arg) {

                }
            })
        }        
View Code
1、 ajax参数
    url:
    type:
    data:
    1、value不能是字典 {k1:'v1',k2:[1,2,3,],k3; JSON.string}
    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: model.TB.objects.value()
            json: model.TB.objects.value_list()

 3、路由系统

URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;
你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

a:单一路由对应	
url(r'^index$', views.index),
b:基于正则的路由
url(r'^index/(\d*)', views.index),
url(r'^manage/(?P<name>\w*)/(?P<id>\d*)', views.manage),
c:添加额外的参数
url(r'^manage/(?P<name>\w*)', views.manage,{'id':333}),
d:为路由映射设置名称(反向生成url)
url(r'^home', views.home, name='h1'),
url(r'^index/(\d*)', views.index, name='h2'),

urls:
	url(r'^index/(\d+)/',views.index,name="n1"),
	url(r'^index/(?P<a1>\d+)/',views.index,name="n1"),

views:
	from django.urls import reverse    #根据名字反转成url
	def index(request,a1):    #一一对应关系
		user_list=[
			"alex","eric","tony"
    ]
    v=reverse("n1",args=(1,))    #args= 数字自己规定 写的是1 url也会体现出来
    and
	v=reverse("n1",kwargs={'a1':11111}) 
	print(v)
    return render(request,'index.html',{"user_list":user_list})

在html里写
	url(r'^login/',views.login,name='m1'),
    <form method="POST" action="{% url "m1" %}">    /* 根据名称也可以反生url*/
	url(r'^edit/(\w+)/', views.edit,name='n2')
	<li>{{ i }}<a href="{% url 'n2' i %}">| 编辑</a></li>    跳转的时候也可以做,不用写url
e:路由分发
如果映射url太多,全写一个在  urlpatterns 显得繁琐,so 路由分发应用而生

urls.py
	url(r'^app01/',include('app01.urls')),

总路由:
	url(r'^',default), url不存在的话 可以默认写 or 跳转到index 的路径下
	url(r'^',views.index),  #路由默认不写 或者路由错误 直接执行index的函数
app01.urls.py
	url(r'^index.html$',views.index),
额外:
终止符:^edits$
伪静态:url(r’^edit/(\w+).html$’,views.edit),

4、视图函数(CBV & FBV)

CBV:
	# from django.views import View     #导入一个 View 以便类继承

	# class Login(View): #继承一个特殊的类  View
	#     """
	#     提交方法
	#     get  查
	#     post  创建
	#     put   更新
	#     delete  删除
	#     """
	#
	#     def get(self,request):    #get请求取值
	#         return render(request,'login.html')
	#
	#     def post(self,request):   #post请求取值
	#         print(request.POST.get("user"))
	#         return HttpResponse("Login.post")


	urlpatterns = [
		url(r'^admin/', admin.site.urls),
		url(r'^test.html$',views.test),   #url对应函数
		url(r'^login.html$',views.Login.as_view()),   #url对应类
	]


	<!DOCTYPE html>
	<html lang="en">
	<head>
		<meta charset="UTF-8">
		<title>Title</title>
	</head>
	<body>
	<form method="POST" action="/login.html">
		<input type="text" name="user"/>
		<input type="submit" value="提交"/>
	</form>
	</body>
	</html>

5、ORM操作:

a.创建表
	from django.db import models


	class User_type(models.Model):
		uid = models.BigAutoField(primary_key=True)
		title = models.CharField(max_length=32)

	class User_info(models.Model):
		name = models.CharField(max_length=32)
		age = models.CharField(max_length=32)
		ut = models.ForeignKey("User_type")


	python manage.py makemigrations

	python manage.py migrate
---------------------其它---------------------

	class part(models.Model):
		cid = models.BigAutoField(primary_key=True)
		title = models.CharField(max_length=32,null=False)


	class student(models.Model):
		sid = models.BigAutoField(primary_key=True)
		name = models.CharField(max_length=32,null=False)
		pub_data=models.DateField()
		age = models.IntegerField(default=18)
		# 新增加的列 如果原先表里有值,写default
		ug = models.ForeignKey("part",null=True) #如果新增加外键,加null=True
	
	
b:ORM操作:
	基本操作:
	#增
	# models.User_type.objects.create(title="黑金用户")
		
	# obj = models.User_type(title="小白用户")
	# obj.save()

	#删
	#models.User_type.objects.filter(title="小白用户").delete()  # 删除指定条件的数据

	#改
	#models.User_type.objects.filter(title="黑金用户").update(title="黑卡用户")    # 修改指定条件的数据

	#查
	# models.User_type.objects.get(title="大白用户")      # 获取单条数据,不存在则报错(不建议)
	# models.User_type.objects.all()                     # 获取全部
	# models.User_type.objects.filter(title="小白用户")   # 获取指定条件的数据
	# models.User_type.objects.exclude(title="黄金用户")     # 排除指定条件的数据	

Django--ORM基本操作 请看我的另一篇博客:http://www.cnblogs.com/niejinmei/p/7089719.html

c:多对多操作 

    方法一:
        通过外键创建第三张表
    class Boy(models.Model):
        name = models.CharField(max_length=32)
     
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
     
    class Love(models.Model):
        b = models.ForeignKey("Boy")
        g = models.ForeignKey("Girl")
         
        class Meta:
            unique_together = [
                ("b","g"),
            ]

    #表里插入数据

    objs = [
            models.Boy(name='方少伟'),
            models.Boy(name='游勤斌'),
            models.Boy(name='于浩'),
            models.Boy(name='陈涛'),
    ]
    models.Boy.objects.bulk_create(objs,4)

    result = [
        models.Girl(nick='于浩姐姐'),
        models.Girl(nick='景甜'),
        models.Girl(nick='刘亦非'),
        models.Girl(nick='苍老师'),
    ]
    models.Girl.objects.bulk_create(result, 4)

    models.Love.objects.create(b_id=1,g_id=1)
    models.Love.objects.create(b_id=1,g_id=2)
    models.Love.objects.create(b_id=1,g_id=3)
    models.Love.objects.create(b_id=2,g_id=4)


    ###################   查找和我有关系的女孩  四种方式 ################


    obj = models.Boy.objects.filter(name="方少伟").first()
    love_list = obj.love_set.all()
    for row in love_list:
       print(row.g.nick)

    love_list = models.Love.objects.filter(b__name="方少伟")
    for row in love_list:
        print(row.g.nick)


    #下面两个效果好

    love_list = models.Love.objects.filter(b__name="方少伟").values("g__nick")
    for item in love_list:
        print(item["g__nick"])   
        


    love_list = models.Love.objects.filter(b__name="方少伟").select_related("g")
    for obj in love_list:
        print(obj.g.nick)        
方法一
通过 ManyToManyField 创建第三张表
    class Boy(models.Model):
        name = models.CharField(max_length=32)
        m = models.ManyToManyField("Girl")
     
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
    obj = models.Boy.objects.filter(name="方少伟").first()
        # print(obj.id,obj.name)

        # obj.m.add(2)
        # obj.m.add(1,3)
        # obj.m.add(*[4,])

        # obj.m.remove(2)
        # obj.m.remove(1,3)
        # obj.m.remove(*[4,])

        # obj.m.set([1,4,])


        # girl_list = obj.m.all()
        # girl_list = obj.m.filter(nick="苍老师")


        # obj.m.clear()

    obj = models.Girl.objects.filter(nick="苍老师").first()
    v = obj.boy_set.all()            
方法二
方式三:通过 外键 和 ManyToManyField 创建
    class Boy(models.Model):
        name = models.CharField(max_length=32)
        m = models.ManyToManyField("Girl",through="Love",through_fields=("b","g",))
     
    class Girl(models.Model):
        nick = models.CharField(max_length=32)
     
    class Love(models.Model):
        b = models.ForeignKey("Boy")
        g = models.ForeignKey("Girl")
     
        class Meta:
            unique_together = [
                ("b","g"),
            ]
    obj = models.Boy.objects.filter(name="方少伟").first()

    #只可以查或清空
    obj.m.clear()

    obj.m.all()
方法三

d:一对多 

正向:
    filter() values,values_list() -> 跨表  fk__xxx
        objs = all()
        for obj in objs:
            obj.fk.


    反向:
    filter() values,values_list() -> 跨表  表名称__xxx
        objs = all()
        for obj in objs:
            obj.表名称_set.all()  
1、连表操作演示

    urlpatterns = [
     
        url(r'^test/', views.test),

    ]

    class User_type(models.Model):
        uid = models.BigAutoField(primary_key=True)
        title = models.CharField(max_length=32)

    class User_info(models.Model):
        name = models.CharField(max_length=32)
        age = models.CharField(max_length=32)
        ut = models.ForeignKey("User_type")
        
    def test(request):
        models.User_type.objects.create(title="普通用户")
        models.User_type.objects.create(title="白金用户")
        models.User_type.objects.create(title="黄金用户")


        models.User_info.objects.create(name="小鸡",age=18,ut_id=1)
        models.User_info.objects.create(name="小狗",age=18,ut_id=2)
        models.User_info.objects.create(name="小猫",age=18,ut_id=2)
        models.User_info.objects.create(name="小雨",age=18,ut_id=3)
        models.User_info.objects.create(name="大雨",age=18,ut_id=1)

        for i  in range(300):
            name = "root" + str(i)
            models.User_info.objects.create(name=name, age=18, ut_id=1)

        #正向操作
        obj = models.User_info.objects.all().first()
        print(obj.name,obj.age,obj.ut.title)

        #反向操作   obj.表名小写_set.all()
        obj = models.User_type.objects.all().first()
        for row in obj.user_info_set.all():
            print(row.name,row.age)

        result = models.User_type.objects.all()
        for item in result:
            print(item.title,item.user_info_set.all())
            print(item.user_info_set.filter(name="小雨"))


        #字典格式
        result = models.User_info.objects.all().values("id","name")
        for row in result:
            print(row)

        #字典格式查的时候跨表
        result = models.User_info.objects.all().values("id","name","ut__title")
        for row in result:
            print(row["id"],row["name"],row["ut__title"])





    # 元组格式
    # result = models.User_info.objects.all().values_list("id","name")
    # for row in result:
    #     print(row)

    return HttpResponse(".....")    
View Code

e:分页

 自带分页  

自带分页(适合与上一页、下一页)
    urlpatterns = [
        url(r'^admin/', admin.site.urls),
        url(r'^test.html$',views.test),   #url对应函数
        url(r'^index.html$',views.index),    


    def index(request):
    """
    分页
    :param request:
    :return:
    """
    # for i in range(300) :    #向数据库增加数据
    #     name="root"+str(i)
    #     models.UserInfo.objects.create(name=name,age=18,ut_id=1)

    # current_page=request.GET.get("page")   #获取当前页
    # user_list=models.UserInfo.objects.all()  #获取用户所有的信息
    # paginator=Paginator(user_list,10)        #  分页处理,每页显示十条数据
    #per_page:每页显示条目数量
    #count:数据总个数
    #num_总页数
    #page_range:总页数的索引范围,如:(1,10),(1,200)
    #page:page对象
    # try:
    #     posts=paginator.page(current_page)     #posts是一个对象
    # except PageNotAnInteger as e:
    #     posts=paginator.page(1)
    # except EmptyPage as e:
    #     posts=paginator.page(1)

    #has_next                是否有下一页
    #next_page_number       下一页页码
    #has_previous          是否有上一页
    #previous_page_number  上一页页码
    #object_list           分页之后的数据列表
    #number                当前页
    #paginator             paginator对象

    # return render(request,'index.html',{"posts":posts})
    
    
    
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <h1>用户列表</h1>

    <ul>
      {% for row in posts.object_list %}
        <li>{{ row.name }}</li>
      {% endfor %}
    </ul>
    <div>
        {% if posts.has_previous %}
            <a href="/index.html?page={{ posts.previous_page_number }}">上一页</a>
        {% endif %}

        {% if posts.has_next %}
            <a href="/index.html?page={{ posts.next_page_number }}">下一页</a>
        {% endif %}
    </div>
    </body>
    </html>
自带分页

 自定义分页

自定义分页:
         class PageInfo(object):
#     def __init__(self,current_page,all_count,per_page,base_url,show_page=11):  #show_page=1:10的数
#         """
#
#         :param current_page:  当前页
#         :param all_count:    数据库总行数
#         :param per_page:      每页显示行数
#         """
#
#         try:
#             self.current_page=int(current_page)   #当前页转成int类型
#         except Exception as e:
#             self.current_page=1  #当前页显示为1
#         self.per_page=per_page
#
#         a,b= divmod(all_count,per_page)  #总行数除每页显示行数
#         if b:
#             a=a+1
#         self.all_pager=a
#         self.show_page=show_page
#         self.base_url=base_url
#
#     def start(self):
#         return (self.current_page-1)*self.per_page
#
#     def end(self):
#         return self.current_page *self.per_page
#
#     def pager(self):
#         page_list=[]
#         half=int((self.show_page-1)/2)  #取前五个的值
#
#         #如果数据总页数<11
#         if self.all_pager <self.show_page:
#             begin=1
#             stop=self.all_pager+1
#
#         #如果总页数>11
#         else:
#             #如果当前页 <=5, 永远显示1,11
#             if self.current_page <=half:
#                 begin=1
#                 stop=self.show_page+1
#             else:
#                 if self.current_page+half > self.all_pager:
#                     begin=self.all_pager-self.show_page+1
#                     stop=self.all_pager+1
#                 else:
#                     begin=self.current_page - half
#                     stop=self.current_page + half +1
#         if self.current_page <=1:
#             prev="<li><a href='#'>上一页</a></li>"
#         else:
#             prev="<li><a href='%s?page=%s'>上一页</a></li>" %(self.base_url,self.current_page-1,)
#         page_list.append(prev)
#
#         for i in range(begin,stop):
#             if i == self.current_page:
#                 temp = "<li class='active'><a href='%s?page=%s'>%s</a></li>" %(self.base_url,i,i,)
#
#             else:
#                temp= "<li><a href='%s?page=%s'>%s</a></li>" % (self.base_url, i, i,)
#             page_list.append(temp)
#
#         if self.current_page >=self.all_pager:
#             nex="<li><a href='#'>下一页</a></li>"
#         else:
#             nex = "<li><a href='%s?page=%s'>下一页</a></li>" % (self.base_url, self.current_page + 1,)
#         page_list.append(nex)
#
#         return "".join(page_list)  #将列表拼接成字符串
#
#
# def custom(request):
#     # 表示用户当前想要访问的页码:
#     all_count=models.UserInfo.objects.all().count()   #取数据库总个数
#     page_info=PageInfo(request.GET.get("page"),all_count,10,'/custom.html',11) #用户传值   #加入用户传一个非数字的类型  可以捕捉异常
#      #产生一个对象
#     user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]  #对象.方法调用
#     return render(request, 'custom.html', {"user_list": user_list,'page_info':page_info})
#

ps:自定义的分页的功能写好放在文档里面,以后谁用可以直接导入过来使用
    from utils.pager import PageInfo
     def custom(request):
      # 表示用户当前想要访问的页码:
     all_count=models.UserInfo.objects.all().count()   #取数据库总个数
     page_info=PageInfo(request.GET.get("page"),all_count,10,'/custom.html',11) #用户传值   #加入用户传一个非数字的类型  可以捕捉异常
     #产生一个对象
     user_list = models.UserInfo.objects.all()[page_info.start():page_info.end()]  #对象.方法调用
     return render(request, 'custom.html', {"user_list": user_list,'page_info':page_info})
自定义分页

6:COOKIE:

 Cookie是存储在用户浏览器上的一个键值对 

 A、获取cookie 

request.COOKIES['key']
    request.get_signed_cookie(key, default=RAISE_ERROR, salt='', max_age=None)
    request.COOKIES.get(...)
    参数:
        default: 默认值
           salt: 加密盐
        max_age: 后台控制过期时间(超时时间)

   B、设置Cookies

obj=HttpResponse(....)
    obj=render(request,......)
    obj.set_cookie(key,value,.....)
    cookie签名:
    obj.set_signed_cookie(key,value,salt="加盐" 'ticket',"123123",salt='jjjjjj')
 
    rep.set_cookie(key,value,...)
    rep.set_signed_cookie(key,value,salt='加密盐',...)
    参数:
        key,              键
        value='',         值
        max_age=None,     超时时间
        expires=None,     超时时间(IE requires expires, so set it if hasn't been already.)
        path='/',         Cookie生效的路径,/ 表示根路径,特殊的:跟路径的cookie可以被任何url的页面访问
        domain=None,      Cookie生效的域名
        secure=False,     https传输
        httponly=False    只能http协议传输,无法被JavaScript获取(不是绝对,底层抓包可以获取到也可以被覆盖)
def cookie(request):
    # 获取 Cookie
        # request.COOKIES        获取所有的COOKIES            # 客户端发来的所有Cookie
        # request.COOKIES['username111']       # 这个Cookie,就是字典
        request.COOKIES.get('username111')

    # 设置 Cookie
        res = render(request,'index.html')
        res = redirect('/index/')

        res.set_cookie('key',"value")  # 设置cookie,关闭浏览器失效
        res.set_cookie('key',"value",max_age=10)  # 设置cookie, N秒后失效

        # expires:设置cookie, 截止时间后失效
        import datetime
        current_date = datetime.datetime.utcnow()
        current_date = current_date + datetime.timedelta(seconds=5)
        res.set_cookie('key',"value",expires=current_date)
    # cookie 加密盐
        obj = HttpResponse('s')
        obj.set_signed_cookie('username',"kangbazi",salt="asdfasdf") # 加密盐
        request.get_signed_cookie('username',salt="asdfasdf")  # 加密盐获取
        

 C、cookie认证:

 def classes(request,*args,**kwargs):
            #去请求的cookie中找凭证
            tk=request.COOKIES.get("ticket")    #去COOKIES取值
            if not tk:   #判断没有值 表示没有登录
            return redirect("/login/")   #跳转到login页面从新登录
            
         def login(request):
            if  request.method=="GET":
                return render(request,'login.html')
            else:
                user=request.POST.get("username")
                pwd=request.POST.get("password")
                if user=="alex" and pwd=="123":
                    obj=redirect("/classes/")    #登录成功跳转到classes页面
                    obj.set_cookie('ticket',"hahahahaha")     #登录成功的话 为浏览器回写cookie
                    return obj
                else:
                    return render(request,'login.html')   #如果不成功的跳转到登录页面

7、session:  

  Session是存储在服务器的一组键值对,且它依赖于Cookie,且安全系数比Cookie高

  Django中默认支持Session,其内部提供了5种类型的Session供开发者使用:

  数据库(默认)
  缓存
  文件
  缓存+数据库
  加密cookie

 数据库session

  Django默认支持Session,并且默认是将Session数据存储在数据库中,即:django_session 表中。

  a. 配置 settings.py  

SESSION_ENGINE = 'django.contrib.sessions.backends.db'   # 引擎(默认)
         
        SESSION_COOKIE_NAME = "sessionid"                       # Session的cookie保存在浏览器上时的key,即:sessionid=随机字符串(默认)
        SESSION_COOKIE_PATH = "/"                               # Session的cookie保存的路径(默认)
        SESSION_COOKIE_DOMAIN = None                             # Session的cookie保存的域名(默认)
        SESSION_COOKIE_SECURE = False                            # 是否Https传输cookie(默认)
        SESSION_COOKIE_HTTPONLY = True                           # 是否Session的cookie只支持http传输(默认)
        SESSION_COOKIE_AGE = 1209600                             # Session的cookie失效日期(2周)(默认)
        SESSION_EXPIRE_AT_BROWSER_CLOSE = False                  # 是否关闭浏览器使得Session过期(默认)
        SESSION_SAVE_EVERY_REQUEST = False                       # 是否每次请求都保存Session,默认修改之后才保存(默认)

         def index(request):
        # 获取、设置、删除Session中数据
        request.session['k1']
        request.session.get('k1',None)
        request.session['k1'] = 123
        request.session.setdefault('k1',123) # 存在则不设置
        del request.session['k1']
 
        # 所有 键、值、键值对
        request.session.keys()
        request.session.values()
        request.session.items()
        request.session.iterkeys()
        request.session.itervalues()
        request.session.iteritems()
 
 
        # 用户session的随机字符串
        request.session.session_key
 
        # 将所有Session失效日期小于当前日期的数据删除
        request.session.clear_expired()
 
        # 检查 用户session的随机字符串 在数据库中是否
        request.session.exists("session_key")
 
        # 删除当前用户的所有Session数据
        request.session.delete("session_key")
 
        request.session.set_expiry(value)
            * 如果value是个整数,session会在些秒数后失效。
            * 如果value是个datatime或timedelta,session就会在这个时间后失效。
            * 如果value是0,用户关闭浏览器session就会失效。
            * 如果value是None,session会依赖全局session失效策略。

 b:session认证: 

def login(request):
         if request.method=="GET":
            return render(request,'login.html')
        else:
            u=request.POST.get("user")
            p=request.POST.get("pwd")
            if u == 'alex' and  p == '123':
                #1.生成随机的字符串
                #2.通过cookie发送给客户端
                #3.服务端保存
                request.session["username"]='alex'
                request.session["email"]="alex3714qq.com"
                return redirect('/index/')
            else:
                return render(request,'login.html',{'msg':"用户名或密码错误"})

            def index(request):
                #1.获取客户端cookie中的随机字符串
                #2.去session中查找有没有随机字符串
                #3.去session中查看对应的key的value中是否有username
                v=request.session.get("username")
                if v:
                    return HttpResponse('登录成功:%s' %v)
                else:
                    return redirect('/login/')

8、xss跨站脚本攻击

XSS又叫CSS (Cross Site Script) ,跨站脚本攻击。它指的是恶意攻击者往web页面里插入恶意的html代码,
当用户浏览该页之时,嵌入其中web里面的html代码会被执行,从而达到恶意用户的特殊目的。
- 慎用 safe和mark_safe
- 非要用,一定要过滤关键字

9、csrf跨站伪装请求

原理:当访问你需要访问的网址,然后被访问的网址会随机生成一个随机字符串返回给用户。
使用:在FBV情况下使用

    from django.views.decorators.csrf import csrf_exempt,csrf_protect 导入模块
        1、    settings.py 里面的csrf开启
        需要在Form表单里面加上{% csrf_token %} 产生随机字符串并生成input框,加上验证。
        ** 如果写成{{csrf_token}} 会产生随机字符串  但不会生成input框 ** 目前使用不上 作为了解

        2、    全部禁用就直接注释掉
        # 'django.middleware.csrf.CsrfViewMiddleware',

        3、    局部禁用
        前提是在全部使用的情况下才能局部禁用
        django.middleware.csrf.CsrfViewMiddleware',

        单独在某个函数上面加上装饰器 @csrf_exempt
        @csrf_exempt
        def csrf1(request):
            if request.method=="GET":
                return render(request, "csrf1.html")

            else:
             return HttpResponse("OK")

        4、    局部使用
        前提是全部禁用的情况下
        # 'django.middleware.csrf.CsrfViewMiddleware',

        单独在某个函数上面加上装饰器@csrf_protect
        @csrf_protect   #局部使用
        def csrf1(request):
            if request.method=="GET":
                return render(request, "csrf1.html")

            else:
             return HttpResponse("OK")
      在CBV情况下验证使用
                from django.utils.decorators import method_decorator
        #CBV应用装饰器
        def wrapper(func):
            def inner(*args,**kwargs):
                func(*args,**kwargs)
            return inner

        #1.指定方法上面加装饰器
        # class Foo(View):
        #     @method_decorator(wrapper)
        #     def get(self):
        #         pass
        #
        #     def post(self):
        #         pass

        #2.在类上面加装饰器
        # @method_decorator(wrapper,name='dispatch')
        # class Foo(View):
        #
        #     def get(self):
        #         pass
        #
        #     def post(self):
        #         pass

        #csrf必须加在类上
        # @method_decorator(csrf_protect,name='dispatch')
        # class Foo(View):
        #
        #     def get(self):
        #         pass
        #
        #     def post(self):
        #         pass
    ############# Ajax提交数据时候,携带CSRF: ###########
            1、放置在data中携带
        <form method="POST" action="csrf1.html">
              {% csrf_token %}
             <input id="user" type="text" name="user">
             <input type="submit" value="提交">
             <a onclick="submitForm();">Ajax提交</a>
             </form>
            <script src="/static/jquery-3.2.1.js"></script>

            <script>
            function submitForm() {
           var csrf=$('input[name="csrfmiddlewaretoken"]').val(); //取字符串的值
           var user=$('#user').val();   //取user的值
          $.ajax({
            url:"/csrf1.html",
            tpye:"POST",
            data:{"user":user,"csrfmiddlewaretoken":csrf},
            success:function (arg) {
                console.log(arg);
                    }
                })
            }
            </script>
        
        2、通过请求头 headers 携带数据
             
        function submitForm() {
               var token=$.cookie("csrftoken");   //获取cookie值
              var user=$("#user").val();   //获取用户值
             $.ajax({
             url:"/csrf1.html",
             type:"POST",
             headers:{"X-CSRFToken":token},    //请求头把数据带过去
             data:{"user":user},
             success:function (arg) {
                console.log(arg)
            }
        })
    }

10、模板语言:

{{ item }}
{% for item in item_list %} <a>{{ item }}</a> {% endfor %}
  forloop.counter
  forloop.first
  forloop.last
{% if ordered_warranty %} {% else %} {% endif %}
母板:{%block css%}
   {% block title %}{% endblock %}
   {%block js%}
子板:{% extends "base.html" %}
   {% block title %}{% endblock %}

模板自定义函数simple_tag:

a、在app中创建templatetags模块

b、创建任意 .py 文件,如:xx.py	
	from django import template
	from django.utils.safestring import mark_safe
	   
	register = template.Library()
	   
	@register.simple_tag
	def my_simple_time(v1,v2,v3):
		return  v1 + v2 + v3
	   
	@register.simple_tag
	def my_input(id,arg):
		result = "<input type='text' id='%s' class='%s' />" %(id,arg,)
		return mark_safe(result)

c、在使用自定义simple_tag的html文件中导入之前创建的 xx.py 文件名
	{% load xx %}	

d、使用simple_tag
	{% my_simple_time 1 2 3%}
	{% my_input 'id_username' 'hide'%}	
	
-simple_filter

            -最多两个参数,方式:{{ 第一参数|函数名称:”第二个参数”}}
                -可以做条件判断
-simple_tag
            -无限制:{%函数名 参数 参数 %}
include:引用小组件随时能使用,导入小组件使用,可以导入多个
            {%include 模板名称%}

11、自关联

 a:自关联,通过名字大概就知道是一张表要关联它自己本身,如果按照以前学的知识创表时肯定不能成功,这就要运用到今天新学的知识点。

 

related_name

 

b:想想,咱们以前关联表时都是在创建一个关系表里边设置外键,自关联也一样。

class UserInfo(models.Model):
    nickname = models.CharField(max_length=32)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    gender_list=(
        (1,'男'),
        (2,'女'),
    )
    gender = models.IntegerField(choices=gender_list)
 
class UtU(models.Model):
    g=models.ForeignKey('UserInfo',null=True,related_name='boy')
    b=models.ForeignKey('UserInfo',null=True,related_name='grily')
    
    重点在于related_name 这样就相当于给他们设置了别名,数据库就不会分不清谁是谁的关联

c:重点来了,表已经创好了,数据也存在怎么查看相关联的信息啊?   

 def indexs(request):
     tt= models.UserInfo.objects.filter(id=2).first()
    print(tt)
     # 获取Boy表中id等于2的obj对象(Boy的obj对象)
     xx =tt.grily.all()
     # 获取UTU表中的所有和Boy对象相关的所有对象
    print(xx)
    for i in xx:
        print(i.g.nickname)
     # 循环获取UTU对象g外键对应的名称
    return HttpResponse('ok')
def indexss(request):
   tt=models.UserINfo.objects.filter(id=2).first()
   xx = tt.userinfo_set.all()
 ## 反向查看关系自关联的表
 for i in xx:
 print(i.nickname)
 return HttpResponse('ok')

d:我们在通过ManyToManyField自动创建一个自关联的关系表。

class UserINfo(models.Model):
    nickname = models.CharField(max_length=32)
    username = models.CharField(max_length=32)
    password = models.CharField(max_length=32)
    gender_list=(
        (1,'男'),
        (2,'女'),
    )
    gender = models.IntegerField(choices=gender_list)
    m = models.ManyToManyField('UserINfo')
def indexsz(request):
    tt = models.UserINfo.objects.filter(id=2).first()
 # 正向查看自关联表的内容
 xx =tt.m.all()
 # 获取到和UserINfo相关的UserINfo对象
 for i in xx:
 print(i.nickname)
 return HttpResponse('ok')
正向查看自关联信息
def indexs(request):
     tt =models.UserINfo.objects.filter(id=2).first()
     ss=tt.userinfo_set.all()
     print(ss)
     for i in ss:
         print(i.nickname)
反向查看自关联信息

12、FK(外键关联)

外键关联就是表(本身)设置一个外键,这个外键要关联的列是这个表(本身)的自增id

class User(models.Model):
    new_id=models.IntegerField(null=True)
    new_tabe= models.CharField(max_length=32)
    new_content =models.CharField(max_length=64)
    new_root = models.CharField(max_length=32)
    content = models.ForeignKey('User',null=True,blank=True,related_name='xxx')
def indexss(request):
     xx =models.User.objects.filter(id=1).first()
     xs =models.User.objects.filter(id=2).first()
      tt =xx.xxx.all()
      ts =xs.xxx.all()
       for i in tt:
        print(i.new_content)
        for i in ts:
       print(i.new_content)
        return HttpResponse('ok')

 

posted @ 2017-07-02 19:06  karina梅梅  阅读(268)  评论(0编辑  收藏  举报