• Python Web(一)


     Infi-chu:

    http://www.cnblogs.com/Infi-chu/

    一、Web框架

    1.socket网络编程

    • 架构:C/S
    • 协议:TCP/UDP
    • 传输层

    2.Web应用

    • 架构:B/S
    • 协议:HTTP
    • 应用层

    二、HTTP协议

    1.请求、响应

    • 请求头
    • 请求体
    • 响应头
    • 响应体

    2.请求头中的相关参数

    • 浏览器支持的内容
      • Accept:客户端接收什么类型的响应
      • Accept-Charset:浏览器可以接收的字符集
      • Accept-Encoding:浏览器能够进行解码的数据编码方式
      • Accept-Language:浏览器希望的语言种类
    • 重要的交互参数
      • Cookie:客户端的Cookie就是通过这个报文头属性传给服务端的后台
      • Referer:请求的来源URL
      • Host:初始URL中的IP和PORT
      • Cache-control:对缓存进行控制
      • User-Agent:发起请求来源
    • 其他参数
      • If-Modified-Since:If-Modified-Since:只有当所请求的内容在指定的日期之后又经过修改才返回它,否则返回304“Not Modified”应答
      • Pragma:指定“no-cache”值表示服务器必须返回一个刷新后的文档,即使它是代理服务器而且已经有了页面的本地拷贝
      • UA-Pixels,UA-Color,UA-OS,UA-CPU:由某些版本的IE浏览器所发送的非标准的请求头,表示屏幕大小、颜色深度、操作系统和CPU类型
      • Authorization:授权信息,通常出现在对服务器发送的WWW-Authenticate头的应答中
      • Connection:表示是否需要持久连接。如果Servlet看到这里的值为“Keep-Alive”,或者看到请求使用的是HTTP 1.1(HTTP 1.1默认进行持久连接),它就可以利用持久连接的优点,当页面包含多个元素时(例如Applet,图片),显著地减少下载所需要的时间。要实现这一点,Servlet需要在应答中发送一个Content-Length头,最简单的实现方法是:先把内容写入ByteArrayOutputStream,然后在正式写出内容之前计算它的大小
      • Content-Length:表示请求消息正文的长度

    3.响应头中的相关参数

    Header解释示例
    Accept-Ranges 表明服务器是否支持指定范围请求及哪种类型的分段请求 Accept-Ranges: bytes
    Age 从原始服务器到代理缓存形成的估算时间(以秒计,非负) Age: 12
    Allow 对某网络资源的有效的请求行为,不允许则返回405 Allow: GET, HEAD
    Cache-Control 告诉所有的缓存机制是否可以缓存及哪种类型 Cache-Control: no-cache
    Content-Encoding web服务器支持的返回内容压缩编码类型。 Content-Encoding: gzip
    Content-Language 响应体的语言 Content-Language: en,zh
    Content-Length 响应体的长度 Content-Length: 348
    Content-Location 请求资源可替代的备用的另一地址 Content-Location: /index.htm
    Content-MD5 返回资源的MD5校验值 Content-MD5: Q2hlY2sgSW50ZWdyaXR5IQ==
    Content-Range 在整个返回体中本部分的字节位置 Content-Range: bytes 21010-47021/47022
    Content-Type 返回内容的MIME类型 Content-Type: text/html; charset=utf-8
    Date 原始服务器消息发出的时间 Date: Tue, 15 Nov 2010 08:12:31 GMT
    ETag 请求变量的实体标签的当前值 ETag: “737060cd8c284d8af7ad3082f209582d”
    Expires 响应过期的日期和时间 Expires: Thu, 01 Dec 2010 16:00:00 GMT
    Last-Modified 请求资源的最后修改时间 Last-Modified: Tue, 15 Nov 2010 12:45:26 GMT
    Location 用来重定向接收方到非请求URL的位置来完成请求或标识新的资源 Location: http://www.zcmhi.com/archives/94.html
    Pragma 包括实现特定的指令,它可应用到响应链上的任何接收方 Pragma: no-cache
    Proxy-Authenticate 它指出认证方案和可应用到代理的该URL上的参数 Proxy-Authenticate: Basic
    refresh 应用于重定向或一个新的资源被创造,在5秒之后重定向(由网景提出,被大部分浏览器支持) Refresh: 5; url=http://www.atool.org/httptest.php
    Retry-After 如果实体暂时不可取,通知客户端在指定时间之后再次尝试 Retry-After: 120
    Server web服务器软件名称 Server: Apache/1.3.27 (Unix) (Red-Hat/Linux)
    Set-Cookie 设置Http Cookie Set-Cookie: UserID=JohnDoe; Max-Age=3600; Version=1
    Trailer 指出头域在分块传输编码的尾部存在 Trailer: Max-Forwards
    Transfer-Encoding 文件传输编码 Transfer-Encoding:chunked
    Vary 告诉下游代理是使用缓存响应还是从原始服务器请求 Vary: *
    Via 告知代理客户端响应是通过哪里发送的 Via: 1.0 fred, 1.1 nowhere.com (Apache/1.1)
    Warning 警告实体可能存在的问题 Warning: 199 Miscellaneous warning
    WWW-Authenticate 表明客户端请求实体应该使用的授权方案 WWW-Authenticate: Basic
    X-Powered-By 由语言解析器或者应用程序框架输出的,这个值的意义用于告知网站是用何种语言或框架编写的 X-Powered-By: ASP.NET

    4.响应行书写

    版本协议+响应码+附加信息 响应体

    eg.

    HTTP/1.1 200 OK 响应体

    响应码:

    • 1xx:提示信息,表示请求已接收
    • 2XX:响应成功
    • 3xx:响应需要定向(重新记载链接第三方链接)
    • 4xx:客户端错误
    • 5xx:服务器端错误

    常用响应码

    • 200:成功
    • 404;请求内容不存在
    • 401:没有访问权限
    • 500:服务器未知错误
    • 503: 服务器暂时无法执行

    三、Django

    1.安装

    pip3 install django==版本号
    

     2.创建

    • 命令行创建工程:
      django-admin startproject 项目名称
      
    • pycharm直接创建Django项目

    3.目录结构

    • project名的文件夹:
      • settings.py:配置文件主要设置一些路径
      • urls.py:路由映射关系,主要进行一些逻辑和网站的相关显示
      • wsgi.py:socket服务端文件
    • manage.py:管理文件
    • templates:主要用来放HTML模板的地方
    • static:css、js等相关文件

    4.设置:

    加载css、js相关文件配置:

    创建static文件夹,将css、js等文件放入

    STATIC_URL = '/static/'
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR, 'static'),
    )
    #如果,少了加载css会报500的错误,如果么有配置STATICFILES_DIRS会报404的错误
    

    模块加载:

    MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
    ]
    

    读取HTML文件配置:

    'DIRS': [os.path.join(BASE_DIR, 'templates')]
    

    非本机访问:

    ALLOWED_HOSTS = ['指定ip1','指定ip2']
    ALLOWED_HOSTS = ['*'] #全部ip
    

    4.启动

    命令行:

    python manage.py runserver ip:port

    pycharm中:

    修改Edit Configuration

    5.Django模板

    块定义:

    {% block 名字定义 %}
    {% endblock %}
    

     导入模板

    {% extends '模板的文件名称' %}
    {% block 名字定义 %}
    模板内添加的内容
    {% endblock %}
    

     6.Cookies

    用于验证登录等信息

    相关参数:

    • key:cookie的key值

    • value:cookie的value值

    • max_age: 超时时间就是在浏览器缓存中保留多少时间 单位是s 例子:10s

    • expires:作用于max_age类似如果值输入一个数字代表几天,如果输入具体时间格式为2019-9-12代表这天失效

    • path /代表全部生效 ,/aa/表示只在aa所在的域生效

    • domain: 域名表示cookie只在某个域名生效

    • secure: 对于cookies里面数据进行加密,默认为 flase为http协议,加密为ture为https协议

    • httponly: true 代表不能使用js获取cookie 通过JS获得cookies我们可以在f12里输入document.cookie获得

    Django设置Cookies

    • obj.set_cookie(key, value)
    • set_signed_cookie(key, val, salt)

    7.Django APP分组

    创建APP:

    python manage.py startapp app名
    

    app内文件:

    • migrations:模型操作的迁移文件
    • admin.py:django admin的时候会用
    • apps.py:注册文件
    • models.py:写表生成的代码
    • tests.py:测试文件
    • views.py:视图文件,一般业务逻辑会写在其中
    • urls.py:格式与主urls.py一样复制过来即可

    主urls.py:

    from django.conf.urls import url, include
    urlpatterns = [
        url(r'^test1/', include("test1.urls")),
        url(r'^test2/', include("test2.urls")),
        url(r'^test3/', include("test3.urls")),
    ]
    

    分urls.py:

    from django.conf.urls import url
    from test1 import views
    urlpatterns = [
        url(r'^get_test1/', views.get_test1) #其域名为/test1/get_test1/,而不是/get_test1/
    ]
    

     路由分发:

    urls.py

    url(r'^test/(w+)/(w+)/', views.test),
    url(r'^test1/(?P<id>w+)/(?P<name>w+)/', views.test1),
    

    views.py

    def test(request, name, id):
        print(id, name)
        return HttpResponse('test')
    
    def test1(request, name, id):
        print(id, name)
        return HttpResponse('test')
    

     【注】

    • 如果没有?P的约束, 传参的时候, 会根据顺序来获取参数对应的值
    • 而如果有约束的话, 传参的时候, 会固定的将获取的值传给所对应的的约束

    定制404 页面:

    urls.py

    url(r'^', views.notfound),
    

    views.py

    def notfound(request);
        return render(request, "404.html")
    

     利用正则表达式以及name关键字反向路由

    urls.py

    url(r'^login.*?/', views.login, name='xxx'),
    

    login.html

    form action="{% url "xxx" %}" method="post">
    <input type="text">
    </form>
    

     【注】

    当我们输入url 为loginXXXXXXXXXXXXXX的时候网页上form表单的url会自动变成login
    如果url(r'^login11', views.login, name='xxx'),上form表单的url会自动变成login11

    8.FBV&CBV

    • FBV(function based views):使用函数来处理业务逻辑
    • CBV(class bassed views):使用类来处理业务逻辑

    eg.

    urls.py

    url(r'^login/', views.Login.as_view()), #类名.as_view()
    

    views.py

    from django.views import View
    class Login(View):
        def get(self, request):    #方法里必须有request来接受传过来的值不然会报错
            return render(request, "login.html") 
    
        def post(self, request):
            pass
    

    当请求过来时,会优先判断请求方法,如果是GET就使用get函数,如果是POST就是用post函数

    继承View类的时候,会自动对传来的参数进行判断

    【注】

    • form表单的方式, 只支持GET/POST
    • ajax的方式, 全部支持

    9.ORM

    • 创建项目
    • settings.py配置
      • 在install_app中配置连接的app
        INSTALLED_APPS = [
            'django.contrib.admin',
            'django.contrib.auth',
            'django.contrib.contenttypes',
            'django.contrib.sessions',
            'django.contrib.messages',
            'django.contrib.staticfiles',
            'app_mysql.apps.AppMysqlConfig', #这个是我们pycharm创建时候自动帮我们注册的就是app配置
            'app_mysql', #如果有新的或者命令行创建的app我们只要这这里面把app名称写上去即可
        ]
        
      • 在database中配置数据库信息
        DATABASES = {
            'default': {
                'ENGINE': 'django.db.backends.mysql',
                'NAME':'库名',
                'USER':'mysql账号名称',
                'PASSWORD':'mysql密码',
                'HOST':'127.0.0.1',
            }
        }
        
    • __init__.py配置
      import pymysql
      pymysql.install_as_MySQLdb()
      
    • models.py配置
      from django.db import models
      
      # Create your models here.
      class test1(models.Model):
          ### 主键自增id不用写, 默认会加上
          name = models.CharField(max_length=30,null=True)
      
      class test2(models.Model):
          name = models.CharField(max_length=30, null=True)
          bigsb = models.ForeignKey('sb',id) 
      
      
      class test3(models.Model):
          name = models.CharField(max_length=30,null=True)
      
    • 生成表单语句
      python manage.py makemigrations
      python manmge.py migrate
      
      • 单条数据
        方法一:models.表名.objects.create(字段1=值1,字段2=值2........)
        方法二:dict = {'字段1':值,'字段2':值.........};models.表名.objects.create(**dict)
        
      • 多条数据
        info = [
             models.UserInfo(name='root1', age=34, ut_id=1),
             models.UserInfo(name='root2', age=35, ut_id=2),
             models.UserInfo(name='root3', age=36, ut_id=1),
             models.UserInfo(name='root4', age=37, ut_id=3),
             models.UserInfo(name='root5', age=32, ut_id=1),
        ]
        models.UserInfo.objects.bulk_create(info)
        
    • models.表名.objects.filter(满足的条件).delete()
      
    • models.表名.objects.filter(满足的条件).update(name='lll', age=23)
      
    • models.UserType.objects.all().values()
      

    有子键关系的查询:

    • 正向:
      # 方法1
      models.A.objects.all().values('ud__id')
      # 方法2
      res = models.A.objects.all()
      for a in res:
          print(a.ud.id)
      
    • 反向:
      # 方法1
      models.B.objects.all().values('A__id')
      # 方法2
      res = models.B.objects.all()
      for b in res:
          print(b.a_set.id) #### 表名小写_set
      

    高级查询:

    • 字段名过滤
      '''
      filter满足条件的
      exclude不满足条件
      '''
      #id等于3的
      models.表名.objects.filter(id=3).values()
      #id不等于3的
      models.表名.objects.exclude(id=3).values()
      
      '''
      关于filter与exclude里面填写的参数
          等于:字段名=值
          大于:字段名__gt=值
          大于等于:字段名__gte=值
          小于:字段名__lt=值
          小于等于:字段名__lte=值
      '''
      
    • 成员 in not in
      res = models.表名.objects.filter(字段名__in=[2,4,5]) # where id in (2,4,5)
      res = models.表名.objects.exclude(字段名__in=[1,2]) # where id not in (1,2)
      
    • 区间 between...and
      # where id between 4 and 8   [4,8]
      res = models.表名.objects.filter(字段名__range=[4,8])
      
    • 模糊查询 like
      # where name like 'a%'
      res = models.表名.objects.filter(字段名__startswith="a")
      res = models.表名.objects.filter(字段名__istartswith="a") #忽略大小写
      
      # where name like '%a'
      res = models.表名.objects.filter(字段名__endswith="a")
      res = models.表名.objects.filter(字段名__iendswith="a") #忽略大小写
      
      # where name like '%a%'
      res = models.表名.objects.filter(字段名__contains="a")
      res = models.表名.objects.filter(字段名__icontains="a") #忽略大小写
      
    • 数据条数 count
      # select count(*) from userinfo where id>3;
      # select count(id) from userinfo where id>3;
      #用sql语句查询数据条数尽量不要查count(*)查主键会快很多
      res = models.UserInfo.objects.filter(id__gt=3).count()
      
    • 排序 order by
      #升序
      res = models.表名.objects.order_by('字段名称')
      
      #降序
      res = models.表名.objects.order_by('-字段名称')
      
      #多个条件进行排序
      res = models.表名.objects.order_by('字段1','字段2') #当字段1相同是会更具字段2进行排序
      
    • 分组 group by
      # select id, sum(age) as s, username from userinfo group by username
      from django.db.models import Count, Min, Max, Sum
      res = models.UserInfo.objects.values("name").annotate(s=Sum('age'))
      
      # select id, sum(age) as s, username from userinfo group by username having s > 50;
      res = models.UserInfo.objects.values("name").annotate(s=Sum('age')).filter(s__gt=50)
      
    • 分页 limit
      # limit 1, 3 分页
      res = models.UserInfo.objects.all()[1:4]
      #因为获取对象是列表所有切片即可
      
    • last/first
      # 第一条:
      res = models.表名.objects.first()
      # 最后一条:
      res = models.表名.objects.last()
      
    • only/defer
      '''
      只查某个字段:only('字段名称')
      
      除某个字段以外的所有字段:defer('字段名')
      
      注意:主键id不管怎么样都会查
      '''
      
    • and/or
      # 只有and
      #id等于3and名字等于a
      models.表名.objects.filter(id=3,and name='a').values()
      # 只有or
      # Q
      from django.db.models import Q
      res = models.UserInfo.objects.filter(Q(id__gt=3) | Q(name='zekai')) #or用|链接
      # 有and和or
      # Q
      from django.db.models import Q
      res = models.UserInfo.objects.filter( Q(Q(id__gt=3) | Q(name='zekai')) & Q(age=23) ) and用&链接
      
    • F
      from django.db.models import F
      models.UserInfo.objects.update(name=F('name')+1) #字段名称都加1
      
    • 原生SQL 类似pycharm
      from django.db import connection, connections
      cursor = connection.cursor()  # cursor = connections['default'].cursor()
      cursor.execute("""SELECT * from auth_user where id = %s""", [1])
      row = cursor.fetchone()
      print(row)
      
    • 去重 distinct
      models.UserInfo.objects.values("name", 'age').distinct() #前面values有多少个就对多少个值进行去除
      

    【注】

    print(res.query) 查看上述代码生成的sql语句
    
  • 相关阅读:
    使用vagrant一键部署本地php开发环境(一)
    产品化机器学习的一些思考
    突破、进化,腾讯云数据库2018全年盘点
    WebGL 纹理颜色原理
    如何定制Linux外围文件系统?
    一文了解腾讯云数据库SaaS服务
    如何正确的选择云数据库?
    Node.js 进程平滑离场剖析
    Git合并不同url的项目
    mariadb 内存占用优化
  • 原文地址:https://www.cnblogs.com/Infi-chu/p/11384613.html
Copyright © 2020-2023  润新知