Django入门

软件开发架构

"""
1、c/s架构
    CS:(Client/Server,客户端/服务器模式),桌面级应用 响应速度快,安全性强,个性化能力强,响应数据较快

2、b/s架构
    BS:(Browser/Server,浏览器/服务器模式),web应用 可以实现跨平台,客户端零维护,但是个性化能力低,响应速度较慢。

# b/s本质也是c/s架构
"""

 

HTTP协议

规定了浏览器与服务端之间数据交互的格式

"""
HTTP协议            数据传输是明文
HTTPS协议           数据传输是密文
websocket协议       数据传输是密文
"""

 

四大特征

"""
 1.基于TCP、IP作用于应用层之上的协议
 2.基于请求响应
 3.无状态
     见你千百遍我都当你如初见
    ps:cookie、session、token...
4.无(短)连接
    ps:长连接:websocket
"""

 

数据格式

"""
请求数据格式
    请求首行(请求方法...)
    请求头(一大堆K:V键值对)
        
    请求体(并不是所有的请求方法都有  主要用来携带敏感性数据)
     
     
响应数据格式
    响应首行(响应状态码...)
    响应头(一大堆K:V键值对)
        
    响应体(展示给用户的数据)
"""

 

响应状态码

"""
用简单的数字来表示一串中文意思
    1XX:服务端已经接受到你的数据正在处理,你可以继续提交
    2XX:200 OK>>>:请求成功
    3XX:重定向(原本想访问A但是内部跳到B)
    4XX:403当前请求不符合条件 404请求资源不存在
    5XX:服务器内部错误


ps:除了上述统一的响应状态码之外,公司还可以自定义自己的状态码
"""

 

请求方法

"""
1.get请求
    朝别人索要数据
2.post请求
    朝别人提交数据
"""
上述两种请求都可以携带额外的参数
get请求
    url?username=jason&hobby=mn
post请求
    数据是放在请求体里面的
"""
"""

 

Django简介

"""
Django 是一个由 Python 编写的一个开放源代码的 Web 应用框架。

使用 Django,只要很少的代码,Python 的程序开发人员就可以轻松地完成一个正式网站所需要的大部分内容,并进一步开发出全功能的 Web 服务 Django 本身基于 MVC 模型,
即 Model(模型)+ View(视图)+ Controller(控制器)设计模式,MVC 模式使后续对程序的修改和扩展简化,并且使程序某一部分的重复利用成为可能。
"""

 

MVC优势

低耦合
开发快捷
部署方便
可重用性高
维护成本低

Python 加 Django 是快速开发、设计、部署网站的最佳组合。


PS:MVC与MTV模型简介详情参见:https://www.runoob.com/django/django-intro.html

 

django特点

"""
强大的数据库功能
自带强大的后台功能
优雅的网址
"""

 

web应用的组成

"""
Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览器。

需要强调的一点是:S端由server和application两大部分构成,如图所示:

我们无需开发浏览器(本质即套接字客户端),只需要开发S端即可,S端的本质就是用套接字实现的。
"""

 

 

 

纯手撸wsgiref模块

import socket

"""
请求首行
b'GET / HTTP/1.1\r\n  
请求头
Host: 127.0.0.1:8080\r\n
Connection: keep-alive\r\n
sec-ch-ua: "Google Chrome";v="89", "Chromium";v="89", ";Not A Brand";v="99"\r\n
sec-ch-ua-mobile: ?0\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/89.0.4389.82 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9\r\n
Sec-Fetch-Site: none\r\n
Sec-Fetch-Mode: navigate\r\n
Sec-Fetch-User: ?1\r\n
Sec-Fetch-Dest: document\r\n
Accept-Encoding: gzip, deflate, br\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
\r\n
请求体
'
"""


server = socket.socket()  # 默认就是TCP协议
server.bind(('127.0.0.1',8080))
server.listen(5)


while True:
    conn, addr = server.accept()  # 三次四次挥手
    data = conn.recv(1024)
    res = data.decode('utf8')
    conn.send(b'HTTP/1.1 200 OK\r\n\r\n')
    # 字符串切割获取地址
    path = res.split(' ')[1]
    # 判断地址
    if path == '/index':
        # conn.send(b'index')
        with open(r'fh.html','rb') as f:
            data = f.read()
            conn.send(data)
    elif path == '/login':
        conn.send(b'login')
    conn.close()
    

# 如何做到后缀的不同返回不同的内容
# 拿到用户输入的后缀 做判断
    
#  不足之处
    1、代码重复(服务端代码所有人都要重复写)
    2、手动处理http格式的数据 并且只能拿到url后缀 其他数据获取繁琐(数据格式一样 处理的代码其实也大致一样 重复写)
    3、并发的问题

 

借助于wsgiref模块

"""
urls.py     路由与视图函数对应关系
view.py     视图函数(后端业务逻辑)
templates文件夹    专门用来存储html文件
"""

# 按照功能的不同拆分之后  后续添加功能只需要在urls.py书写对应关系 然后去views.py书写业务逻辑即可


# 解决了上述两个问题
from wsgiref.simple_server import make_server


def run(request,response):
    """
    :param request:请求相关的所有数据
    :param response:响应相关的所有数据
    :return:
    """
    response('200 OK',[])
    current_path = request.get("PATH_INFO")
    if current_path == '/index':
        return [b'index']
    elif current_path == '/login':
        return [b'login']
    return [b'404 error']


if __name__ == '__main__':
    server = make_server('127.0.0.1',8080,run)  # 一旦被访问会全部交给run函数处理
    server.serve_forever()

 

问题

"""
* 网址很多的情况下如何匹配
* 网址多匹配如何解决
* 功能复杂代码块如何解决
"""

 

封装处理

"""
1.定义一个网址与功能函数的对应关系
    # 地址与功能的对应关系
    urls = [
        ('/index',index_func),
        ('/login',login_func),
        ('/reg',reg_func),
    ]
    
2.按照功能的不同划分成不同的py文件
    urls.py views.py 服务端.py
    
3.书写服务端代码
     func = None
    # for循环判断
    for url_tuple in urls:  # (),()
        if current_path == url_tuple[0]:
            # 将匹配到的函数名赋值给func变量
            func = url_tuple[1]
            break
    # 判断func是否有值
    if func:
        # 执行对应的函数
        res = func(request)
    else:
        res = errors(request)
    return [bytes(res,encoding='utf8')]
"""

 

动静态网页

"""
静态网页
    页面上的数据是直接写死的 万年不变

动态网页
    数据是实时获取的
    eg:
        1、后端获取当前时间展示到html页面上
        2、后端数据是从数据库获取的 展示到html页面上
"""


# 动态网页制作
后端获取当前时间展示到html页面上
import datetime
def gettime(env):
    current_time = datetime.datetime.now().strftime('%Y-%m-%d %X')
    # 如何将后端获取到的数据"传递"给html文件?
    with open(r'templates/03 mytime.html','r',encoding='utf-8') as f:
        data = f.read()
        # data就是一堆字符串
    data = data.replace('asdfg',current_time)  # 在后端将html页面处理好之后再返回给前端
    return data


# 将一个字典传递给html文件  并且可以在文件上方便快捷的操作字典数据
from jinja2 import Template
def get_dict(env):
    user_dic = {'username':'jason','age':18,'hobby':'read'}
    with open(r'templates/04 get_dict.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user = user_dic)
    # 给get_dict.html传递了一个值 页面上通过变量名user就能够拿到user_dict
    return res


# 后端获取数据库中的数据 展示到前端页面
import pymysql
def get_user(env):
    # 要去数据库获取数据 传递给html页面 借助于模板语法 发送给浏览器
    conn = pymysql.connect(
        host='127.0.0.1',
        port=3306,
        user='root',
        password='123456',
        database='day59',
        charset='utf8',
        autocommit=True
    )
    cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
    sql = 'select * from userinfo'
    affect_rows = cursor.execute(sql)
    data_list = cursor.fetchall()  # [{},{},{}]
    # print(data_list)
    # 将获取到的数据传递给html文件
    with open(r'templates/05 get_data.html','r',encoding='utf-8') as f:
        data = f.read()
    tmp = Template(data)
    res = tmp.render(user_list = data_list)
    # 给get_dict.html传递了一个值 页面上通过变量名user就能够拿到user_dict
    return res


 
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <h1 class="text-center">用户数据</h1>
            <table class="table table-hover table-striped">
                <thead>
                    <th>ID</th>
                    <th>username</th>
                    <th>password</th>
                    <th>hobby</th>
                </thead>
                <tbody>
                    {% for user_dict in user_list%}
                        <tr>
                            <td>{{user_dict.id}}</td>
                            <td>{{user_dict.username}}</td>
                            <td>{{user_dict.password}}</td>
                            <td>{{user_dict.hobby}}</td>
                        </tr>
                    {% endfor%}

                </tbody>
            </table>

        </div>
    </div>
</div>

 

模板语法之jinja2模板

pip3 install jinja2
"""模板语法是在后端起作用的"""

# 模板语法(非常贴近python语法)
{{user}}
{{user.get('username')}}
{{user.age}}
{{user['hobby']}}

for循环
{% for user_dict in user_list%}
    <tr>
        <td>{{user_dict.id}}</td>
        <td>{{user_dict.username}}</td>
        <td>{{user_dict.password}}</td>
        <td>{{user_dict.hobby}}</td>
    </tr>
{% endfor%}

 

总结

"""
1.纯手撸web框架
2.wsgiref模块
        1.封装了socket代码
        2.处理了http数据格式
3.根据功能的不同拆分成不同的文件夹
    urls.py    路由与视图函数对应关系
    views.py  视图函数
    templates  模板文件夹
   # 1.第一步添加路由与视图函数的对应关系
   # 2.去views中书写功能代码
   # 3.如果需要使用到html则去模板文件夹中操作
4.jinja2模板语法
    {{}}
    {%%}
5.简易版本web框架流程图
"""

 

自定义简易版本web框架请求流程图

 

 

"""
wsgiref模块
    1、请求来的时候解析http格式的数据 封装成大字典
    2、响应走的时候给数据打包成符合http格式 再返回给浏览器
"""

 

python三大主流web框架

django

"""
    特点:大而全 自带的功能特别特别特别的多 类似于航空母舰
    不足之处:
        有时候过于笨重
"""

 

flask

"""
    特点:小而精 自带的功能特别特别特别少 类似于游骑兵
    第三方的模块特别特别特别的多,如果将flask的模块加起来完全可以盖过django
    并且也越来越像django
    不足之处:
        比较依赖于第三方的开发者
"""

 

tornado

"""
    特点:异步非阻塞 支持高并发
         牛逼到甚至可以开发游戏服务器
    不足之处:
        暂时你不会
"""

 

A:socket部分
B:路由与视图函数对应关系(路由匹配)
C:模板语法
    
django
    A用的是别人的  wsgiref模块
    B用的是自己的
    C用的是自己的(没有jinja2好用 但是也很方便)

flask
    A用的是别人的  werkzeug(内部还是wsgiref模块)
    B自己写的
    C用的别人的(jinja2)
    
tornado
    A,B,C都是自己写的

 

注意事项

# 如何让你的计算机能够正常的启动django项目
    1、计算机的名称不能有中文
        右键计算机 点击属性
        cmd 在窗口输入命令"hostname",即可得到本机的计算机名.
    2、一个pycharm窗口只开一个项目
    3、项目里面所有的文件也尽量不要出现中文
    4、python解释器尽量使用3.4-3.6之间的版本
        (如果你的项目报错 你点击最后一个报错信息
        去源码中把逗号删掉)
        
# django版本问题
    1.x   2.x   3.x(直接忽略)
    1.x和2.x本身差距也不大 讲解主要以1.x为例 会讲解2.x的区别
    
# django安装
    pip3 install django==1.11.11

    验证是否安装成功的方式1
        终端输入django-admin看看有没有反应    

 

django基本操作(必会命令)

# 命令行操作
    # 1、创建django项目
        """你可以先切换到对应的盘 然后再创建"""
        django-admin startproject 项目名(例如mysite)
        
        mysite文件夹
            manage.py
            mysite文件夹
                __init__.py
                settings.py
                urls.py
                wsgi.py    
    # 2、启动django项目
    报错解决:https://www.cnblogs.com/yanlin-10/p/9714793.html
        """
            一定要先切换到项目目录下面
                cd /mysite
        """
        python3 manage.py runserver
        # http://127.0.0.1:8000/
    # 3、创建应用
    """
    Next, start your first app by running python manage.py startapp [app_label].
    """
    python manage.py startapp 应用名(例:app01)
    python3 manage.py startapp app01
        应用名应该做到见面知意
            user
            order
            web 
            ...
            但是我们教学统一就用app01/02/03
       有很多文件
        
        
#  pycharm操作
    # 1、new project 选择左侧第二个django即可
    # 2、启动
        1 还是用命令行启动
        2 点击绿色小箭头即可
        报错解决:https://blog.csdn.net/u010021014/article/details/110449782
    # 3、创建应用
        1 pycharm提供的终端直接输入完整命令(最下方Terminal)
           python3 manage.py startapp app01
        2 pycharm 
            tools    
            run manage.py Task...提示
    # 修改端口号以及创建server
        edit confi...         如有问题,详情参见Day59-12

 

app(应用)

"""
django是一款专门用来开发app的web框架

django框架就类似是一所大学(类似于一个空壳子,提供环境的)
app就类似于大学里面各个学院(具体功能的APP)
    比如开发淘宝
        订单功能
        用户相关
        投诉相关
        创建不同的app对应不同的功能
        
    比如选课功能
        学生功能
        老师功能
一个app就是一个独立的功能模块
"""

************************************创建的应用一定要去配置文件中注册*******************************
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01.apps.App01Config',  # 全写
    'app01'  # 简写
]
# 创建出来的应用第一步先去配置文件中注册 其他的先不要给我干
ps:你在用pycharm创建项目的时候 pycharm可以帮你创建一个app并且自动注册
***************************************************

 

django目录结构

-mysite项目文件夹
    --mysite文件夹
        ---settings.py  配置文件
        ---urls.py  路由与视图函数对应关系(路由层)
        ---wsgi.py  wsgiref模块(不考虑)
    --manage.py  django的入口文件
    --db.sqlite3  django自带的sqlite3数据库(小型数据库 功能不是很多 还有bug)
    --app01文件夹
        ---admin.py  django后台管理
        ---apps.py  注册使用
        ---migrations文件夹  数据库迁移记录
        ---modles.py  数据库相关的 模型类(ORM)
        ---tests.py  测试文件
        ---views.py  视图函数(视图层)

 

命令行与Pycharm创建的区别

# 1 命令行创建不会自动有tempalew文件夹 需要你自己手动创建而pycharm会自动帮你创建并且还会自动在配置文件中配置对应的路径
# pycharm创建的
TEMPLATES = [
    {
        'BACKEND':'django.template.backends.django.DjangoTemplates',
        'DIRS': [str.format(BASE_DIR, '/templates')]
]

# 命令行创建的
TEMPLATES = [
    {   
        'BACKEND':'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
]
        
"""
也就意味着你在用命令创建django项目的时候不单单需要创建templates文件夹还需要去配置文件中配置路径
'DIRS': [str.format(BASE_DIR, '/templates')]

这是一个列表  列表    列表!!!!!!!!!!!!!!!!!!!!
"""

 

django小白必会三板斧

"""
HttpReaopnse
    返回字符串类型

render
    返回html文件

redirect
    重定向
"""

# render传值的两种方式
"""
def ab_render(request):
    # 视图函数必须要接收一个形参request
    user_dict = {'username':'jason','age':18}
    # 第一种传值方式:更加的精确 节省资源
    # return render(request,'01 ab_render.html',{'data':user_dict,'date':123})

    # 第二种传值方式:当你要传的数据特别多的时候
    """locals会将所在的名称空间中所有的名字全部传递给html页面"""
    return render(request,'01 ab_render.html',locals())
    

return redirect(url)
"""

 

启动检查清除浏览器缓存

 

 

模板语法注释

"""
{#    #}
"""

 

静态文件配置

# 登录功能

"""
我们将html文件都默认放在templates文件夹下
我们将网站所使用的静态文件默认都放在static文件夹下

静态文件
    前端已经写好了的  能够直接调用使用的文件
        网站写好的js文件
        网站写好的css文件
        网站用到的图片文件
        第三方框架
        ...
        拿来就可以直接使用的
"""
# django默认是不会自动帮你创建static文件夹 需要你自己手动创建
一般情况下我们在static文件夹内还会做进一步划分处理
    -static
        --js
        --css
        --img
        其他第三方文件

"""
在浏览器中输入url能够看到对应的资源
是因为后端提前开设了该资源的接口
如果访问不到资源 说明后端没有开设该资源的接口
"""




"""
***************************************************************
当你在写django项目的时候 可能会出现后端代码修改了但是前端页面没有变化的情况
    1、你在同一个端口开了好几个django项目
        一直在跑的其实是第一个django项目
    2、浏览器缓存的问题
        在浏览器 检查 settings
            netWork
                dissable cache 勾选
                ***************************************************************
"""


# 静态文件配置
STATIC_URL = '/static/'  # 类似于访问静态文件的令牌
                            接口前缀
"""如果你想要访问静态文件  你就必须以static开头"""
"""
/static/bootstrap-3.3.7-dist/js/bootstrap.min.js

/static/令牌
去列表里面从上往下依次查找
    bootstrap-3.3.7-dist/js/bootstrap.min.js
    都没有才会报错

"""
# 静态文件配置
STATICFILES_DIRS = [
    os.path.join(BASE_DIR,'static')
]


# 静态文件动态解析
    {% load static %}
    <link rel="stylesheet" href="{% static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>
   


# form表单默认是get请求数据
http://127.0.0.1:8000/login/?username=jason&password=123
"""
from表单action参数    
    1、不写  默认当前所在的url提交数据
    2、全写  指名道姓
    3、只写后缀 /login/
"""


# 在前期我们使用django提交post请求的时候  需要去配置文件中注释掉一行代码
MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    # 'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

 

form表单回顾

"""
form表单默认使用的是get请求
        action
        控制后端提交的路径
            1.不写:默认朝当前页面地址提交数据
           2.后缀:/index/
           3.全写:https://www.mzitu.com
        method
            get
              post
"""

 

request对象方法初识

request.method  # 返回请求方式  并且是全大写的字符串形式 <class 'str'>


request.POST  # 获取用户post请求提交的普通数据不包含文件
    request.POST.get()  # 只获取列表最后一个元素
    request.POST.getlist()  # 直接将列表取出
   

request.GET  # 获取用户提交的get请求数据
    request.GET.get()  # 只获取列表最后一个元素
    request.GET.getlist()  # 直接将列表取出
    
    
request.FILES  # 直接看成是字典即可
        获取用户上传的文件数据
        '''form表单如果需要携带文件数据 那么要添加参数
        <form action="" method="post" enctype="multipart/form-data">
        '''
       get()  # 获取列表最后一个元素
       getlist()  # 获取整个列表
    
"""
get请求携带的数据是有大小限制的 大概好像只有4kb左右
而post请求没有限制
"""
    


def login(request):
    # 返回一个登录界面
    """
    get请求和post请求应该有不同的处理机制
    :param request:  请求相关的数据对象  里面有很多简易的方法
    :return:
    """
    # print(request.method)  # 返回请求方式  并且是全大写的字符串形式 <class 'str'>

    # if request.method == 'GET':
    #     print('来了 老弟')
    #     return render(request,'02 login.html')
    # elif request.method == 'POST':
    #     return HttpResponse('收到了!!!')

    if request.method == 'POST':
        return HttpResponse('收到了!!!')
    return render(request,'02 login.html')


"""
视图函数书写格式
    def login(request):
        if request.method == 'POST':
            return HttpResponse("我很气愤")
        return render(request,'login.html')
"""

 

posted @ 2021-06-10 21:27  Palpitate~  阅读(33)  评论(0编辑  收藏  举报