博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

Django基础 - 10请求与响应

Posted on 2023-04-16 20:49  Kingdomer  阅读(34)  评论(0编辑  收藏  举报

 

环境准备

# 1. 开启一个新的项目 advanceDjango
(venv) E:\PythonLearn\djangoDemo>django-admin startproject advanceDjango # 2. 配置项目同名APP下的settings.py, advanceDjango/advanceDjango/settings.py ALLOWED_HOSTS = ['*'] TEMPLATES = [
'DIRS': [ os.path.join(BASE_DIR, 'templates') # 配置模板目录 ], # 配置数据库, 更换Sqlite3为MySQL DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_advance', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'dbman', 'PASSWORD': 'xxxxxx', 'CHARSET': 'utf8' } } # 3. 安装数据库驱动 pymysql, 默认是mysqlclient (venv) E:\PythonLearn\djangoDemo>pip install pymysql # 创建数据库django_advance mysql> create database django_advance default character set 'utf8'; Query OK, 1 row affected, 1 warning (0.01 sec) # 在 advanceDjango/advanceDjango/__init__.py 引入MySQL 初始化 import pymysql pymysql.install_as_MySQLdb()

  

一、 请求与响应之Request

1.1 Request对象

1.1.1 Request 请求对象类; 在视图函数的第一个参数上; 请求是由Django框架生成的

1.1.2 请求对象中的普通信息

  • path:         请求路径
  • method:       请求方法; GET/POST/PUT/DELETE
  • content_type: 数据类型, 如请求头的Context-Type: text/html;charset=utf-8
  • encoding:     编码方式, 如utf-8
  • body:         字节码数据,一般接收上传的json数据

1.1.3 请求对象中的QueryDict属性, QueryDict自动进行url的中文编码处理

  • GET:     查询参数, 包含get请求的所有参数
  • POST:    表单参数, 包含post/put两个请求方法的参数;PUT上传的数据用body来获取
  • COOKIES: 客户端中的当前domain的所有Cookie信息
  • FILES:   上传的表单参数中所有的文件对象
  • session: 会话中存储的数据(可以跨多个请求)
  • META:    客户端的元信息(服务器环境信息、客户端请求信息) REMOTE_ADDR 客户端IP地址
    •     PATH_INFO  REQUEST_METHOD   QUERY_STRING  CONTENT_TYPE

1.1.4 GET/POST 参数

  • 类字典结构; key-value存储数据; key可以重复; 
  • 获取值: GET.get(),获取不到返回None;  GET[key] 获取不到抛出异常;
  • 获取所有值: GET.getlist("")

 

1.2 user应用测试

1.2.1 基础准备, 新增user应用

(venv) E:\PythonLearn\djangoDemo>cd advanceDjango
(venv) E:\PythonLearn\djangoDemo\advanceDjango>django-admin startapp user

1.2.2 定义视图函数

def register(request, user_id=None):
    return render(request, 'register.html', locals())

1.2.3 定义路由

# 定义总路由, 在settings.py 注册应用
    path('user/', include('user.urls', namespace='user')),

 

# 定义子路由
app_name = 'user'
urlpatterns = [ path('register/', views.register, name='register1'), path('register/<user_id>/', views.register, name='register2') ]

1.2.4 编写 templates/register.html

    <p>
        请求路径: {{ request.path }}
        <br/>
        请求URI: {{ request.get_raw_uri }}
        <pre>
            URL: 统一资源定位符, 资源的网络地址
            URI: 统一资源标识符, 用于Restful规范中
        </pre>
    </p>
    <p>
        请求方法: {{ request.method }}
        <br>
        content_type: {{ request.content_type }}
        <br>
        encoding: {{ request.encoding }}
        <br>
        content_params: {{ request.content_params }}
    </p>

 

1.2.5 访问结果 

   

 

1.2.6 访问 http://127.0.0.1:8000/user/register/11a

[10/Apr/2023 22:41:48] "GET /user/register/11a HTTP/1.1" 301 0
[10/Apr/2023 22:41:48] "GET /user/register/11a/ HTTP/1.1" 200 924

 

1.3 GET请求参数

<p>
    <form method="get" enctype="application/x-www-form-urlencoded">
        <input name="name" placeholder="请输入用户名">
        <br>
        <input name="phone" placeholder="手机号">
        <br>
        爱好:
        {% for love in loves %}
            <input type="checkbox"
                   {% if forloop.first or forloop.last %}  # 默认选中第一项和 最后一项
                       checked
                   {% endif %}
                   name="love" value="{{ love }}">{{ love }}
        {% endfor %}
        <br>
        <button>提交</button>
    </form>
</p>

<p>
    GET请求的查询参数
    <ul>
        {% for key, value in request.GET.items %}
            {% ifnotequal key 'love' %}
                <li>{{ key }}:{{ value }}</li>
            {% endifnotequal %}
        {% endfor %}
        <li>
            爱好:
            {% for item in select_loves %}
                {{ item }},
            {% endfor %}
        </li>
    </ul>
</p>

  

def register(request, user_id=None):
    loves = ['H5', 'Python', 'Java', 'GO', 'Linux']
# 获取参数名相同(love)的多个参数值 select_loves = request.GET.getlist('love') return render(request, 'register2.html', locals())

  

访问 /user/register , 输入数据后,点击提交 

1.4 POST请求参数 

from django.views.decorators.csrf import csrf_exempt
@csrf_exempt def register3(request, user_id=None): print(request.POST) print(request.body) return render(request, 'register3.html', locals())

  

<form method="post" enctype="application/x-www-form-urlencoded">
    <input name="name" placeholder="请输入用户名" value="{{ name }}">
    <br>
    <input name="phone" placeholder="手机号" value="{{ phone }}">
    <br>
    <button>提交</button>
</form>
<p>
    POST请求的查询参数
<ul>
    {% for key, value in request.POST.items %}
        <li>{{ key }}:{{ value }}</li>
    {% endfor %}
</ul>
</p>

 

POST返回结果 

<QueryDict: {'name': ['Tom'], 'phone': ['15566665555']}>
b'name=Tom&phone=15566665555'

 

POST请求参数格式

#  es6-form  格式化: key=value&key=value 格式化的字符串
fetch('', {
                method: 'POST',
                body: 'name=' + data.name+'&phone='+data.phone,

 

 

1.5 PUT请求参数 

1.5.1 PUT请求传递json数据

<p>
    <button onclick="up_ajax()">ajax发起PUT请求</button>
    <script>
        function up_ajax() {
            data = {
                name: 'TangSan',
                phone: '15500008753',
                loves: ['数学', 'Python', 'Java', '语文', 'Linux']
            };
            var formdata = document.forms[0]
            formdata.append('name', data.name);
            formdata.append('phone', data.phone)
            fetch('', {
                method: 'PUT',
                body: JSON.stringify(data),
                headers: {
                    'Content-Type': 'application/json;charset=utf-8'
                }
            }).then(response => response.text()).then(html => {
                document.write(html)
            });
        }
    </script>
</p>

<p>
    请求方法: {{ request.method }}   <br>
    PUT请求的参数(body): {{ request.body }} <br>
    content_type: {{ request.content_type }} <br>
    encoding: {{ request.encoding }} <br>
</p>

 

 

1.5.2 PUT请求传输form表单数据

                body: document.forms[0].serialize,
                headers: {
                    {#'Content-Type': 'application/json;charset=utf-8'#}
                    'Content-Type': 'application/x-www-form-urlencoded'
                }

  

1.6 上传文件

<form method="post" enctype="multipart/form-data">
    <input name="name" placeholder="用户名"><br>
    <input name="phone" placeholder="手机号"><br>
    <input type="file" name="img"><br>
    <button>提交</button><br>
</form>

 

from django.core.files.uploadedfile import InMemoryUploadedFile

@csrf_exempt
def register4(request, user_id=None):
    print(request.method)
    print(request.POST)
    print(request.FILES)

    name = request.POST.get('name')
    phone = request.POST.get('phone')
    upload_file: InMemoryUploadedFile = request.FILES.get('img')
    if upload_file:
        print(upload_file.name)
        print(upload_file.content_type)
        print(upload_file.size)
        print(upload_file.charset)
        # print(request.body)
        if all((
                upload_file.content_type.startswith('image/'),
                upload_file.size < 120 * 1024
        )):
            print(request.META.get('REMOTE_ADDR'))
            file_name = name + os.path.splitext(upload_file.name)[-1]
            # images 目录必须存在, advanceDjango项目目录下
            with open('images/' + file_name, 'wb') as f:
                for chunk in upload_file.chunks():
                    f.write(chunk)
                f.flush()
            return HttpResponse('上传文件成功')
        return HttpResponse('请上传小于120KB的图片')
    return render(request, 'register4.html', locals())

  

POST
<QueryDict: {'name': ['Jack'], 'phone': ['15566667777']}>
<MultiValueDict: {'img': [<InMemoryUploadedFile: Django目录结构.png (image/png)>]}>

 

Django目录结构.png
image/png
54811
None

 

当保存图片等文件时,目录不存在会报错

 

二、 请求与响应之Response

2.1 response对象

响应对象是视图函数返回的对象。需自行创建,可由render()/redirect()快速生成response响应对象。

常用的响应类: HttpResponse、 HttpResponseRedirect、 JsonResponse

常用属性与方法:
  • content: 响应内容,必须是bytes类型的数据       charset: 编码格式
  • status: 响应状态码(200, 3xx, 404, 5xx)      content_type: MIME类型
  • init(): 初始化内容    write(): 直接写出文本  flush(): 刷新缓冲区
增加响应头:
  • 响应对象中存在着 _headers 私有的字典对象 HttpResponseBase类。
  • 在Django中, response对象具有dict的特性。 response['Content-Type'] = value

2.2 返回JSON格式数据

def register5(request):
    # 返回字符串格式的文本
    resp1 = HttpResponse(content='您好'.encode('utf-8'), status=200, content_type='text/html;charset=utf-8')

    # 返回图片
    with open('images/Jack.png', 'rb') as f:
        png_data = f.read()
    resp2 = HttpResponse(content=png_data, content_type='image/png')
    resp2.setdefault('Content-Length', len(png_data))

    # 返回Json格式的数据
    json_data = {'name': 'Jackson', 'age': 20}
    resp3 = HttpResponse(content=json.dumps(json_data), content_type='application/json')

    # 使用JsonResponse返回Json数据
    resp4 = JsonResponse(json_data)
    return resp4

 

返回图片