zoukankan      html  css  js  c++  java
  • 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')
  • 相关阅读:
    Oracle常用命令大全(很有用,做笔记)
    表格驱动编程在代码中的应用
    mac 利用svn下载远程代码出现Agreeing to the Xcode/iOS license requires admin privileges, please re-run as root via sudo.
    FAILURE: Build failed with an exception.
    There is an internal error in the React performance measurement code.Did not expect componentDidMount timer to start while render timer is still in progress for another instance
    react native TypeError network request failed
    Android向系统相册中插入图片,相册中会出现两张 一样的图片(只是图片大小不一致)
    react-native Unrecognized font family ‘Lonicons’;
    react-native SyntaxError xxxxx/xx.js:Unexpected token (23:24)
    Application MyTest has not been registered. This is either due to a require() error during initialization or failure to call AppRegistry.registerComponent.
  • 原文地址:https://www.cnblogs.com/niejinmei/p/7106828.html
Copyright © 2011-2022 走看看