欢迎食用『主界面』~,这里是赵苦瓜的看板娘desu~

#
【点滴记录】Django框架的入门 - 第四篇(View层、GET、POST、反向解析)
首页 > 点滴记录    作者:赵苦瓜   2021年1月25日 15:57 星期一   热度:4211°   百度已收录  
时间:2021-1-25 15:57   热度:4211° 

上一篇主要讲了模板层的内容,戳链接:https://blog.jixiaob.cn/?post=40

——————————————————————————————————————————————

View层(视图)

用于接受外部请求,并作出相应。

大约分问两大类:①以json形式返回    ②以网页形式返回

视图的本质就算一个函数。

视图参数:1.一个HttpRequest的实例   2.通过正则表达式获得的参数


自定义错误页面:在模板文件夹新建如 404.html  ,重写对应错误码的页面,即可自定义


双R

服务器在接收到HTTP请求之后,会根据报文创建HttpRequest对象

视图中的第一个参数就算HttpResponse对象
request

response

属性:

path 请求完整路径   method 请求方法(get,post)encoding 编码方式 

GET 类似字典的参数,包含了get的所有参数。

POST类似字典的参数,包含了上传的文件。Files类似字典的参数,包含了上传的文件。

COOKIES:字典,包含了所有的COOKIE。session 类似字典,表示会话。  

方法:

is_ajax()判断是否为ajax()  通常用在移动端和js中

request.GET和POST都是类字典结构(key允许重复(对应多个值))

request.META 元信息    request.META.get('key')


那么如何获取到GET的数据呢?

比如我们请求这个网页:http://127.0.0.1:8000/Two/haverequest?hobby=coding&a=b&hobby=sleeping

def have_request(request):
    print(request.path, request.method, request.GET, request.POST)
    hobby = request.GET.get('hobby')
    print(hobby)  # 这样只能获得最后一个hobby  sleeping
    hobbies = request.GET.getlist('hobby')
    print(hobbies)  # 这样可以获取一个List   ['coding', 'sleeping']
    return HttpResponse('喵')

怎么实现POST请求呢?在HTML里面新建一个提交的页面:


<form action="{% url 'second:do_create_student' %}" method="post">
    <span>Username:</span> <input type="text" name="username" placeholder="请输入username">
    <button>提交</button>
</form>
然后进入网页,写内容提交。这时候你获得了一个403页面,这是Django的防跨站。


可以先在settings里面的MIDDLEWARE里面注释掉:

 # 'django.middleware.csrf.CsrfViewMiddleware',

然后写一个接受post的页面:

path(r'^docreatestudent', views.do_create_student, name='do_create_student')  # 这里用url会报错,还是Django版本问题
def do_create_student(request):
    print(request.method)
    username = request.POST.get('username')
    return HttpResponse(username)


HttpResponse:

服务器返回给客户端的数据,由程序员自己创建。

1.不使用模板,直接HttpResponse()

2.调用模板,进行渲染(先load模板再渲染或者直接render)

render(request, template_name, {context})

request  请求对象体   template_name  模板路径   context 字典参数,用来填坑

属性:

content 返回的内容       charset 编码格式       status_code 响应状态码    content-type MIME类型(类似于拓展名的作用)

响应状态码可以自定义,就算请求成功了也可以给它返回404(反爬虫)

def hello(request):
    response = HttpResponse()
    response.content = "德玛西亚"
    response.status_code = 404
    # 作用:一是真的显示404,二是防爬取
    return response
MIME:指定传输的数据使用哪种形式打开   格式:大类型/小类型     image/png    image/jpg



方法:

init 初始化  write()直接写出文本   flush()冲刷缓冲区   不管写(write)了多少都得刷

set_cookie(key,value='xxx',max_age=None,exprise=None)

delete_cookie(key)  设置cookie和删除cookie


子类:

HttpResponse子类:响应重定向,可以实现服务器内部跳转302

301:永久转移(不用了,不维护了HttpResponsePermanentRedirect)    302:临时转移

return HttpResponseRedict('/show/')

这里建议写反向解析的地址。 url = reverse('namespace:name')   # 导包导的是django.urls.reverse()

这个还有个缩写rediect()   # 在django.shortcuts包里面

HttpResponseBadRequest   400

HttpResponseNotFound    404

HttpResponseForbidden    403

HttpResponseNotAllowed    405    请求方法不被支持

HttpResponseServerError   500

Http404    Exception(引发异常)

raise 主动抛异常出来

JsonResponse子类:用于前后端分离或ajax请求服务器,做差量更新的时候(异步请求)

JsonResponse(dict)     也可以用__init__(self, data)设置数据,Convent-type是application/json

Json中有两种数据:JsonObjest(Json对象,key value)和JsonArray(Json数组,列表中可以是普通数据类型,可可以是JsonObject)二者可相互嵌套

什么时候用?移动端、Ajax


def get_info(request):
    data = {
        'status': 200,
        'msg': 'ok'
    }
    return JsonResponse(data=data)


需要注意的是,如果返回的信息包含中文的话,会默认转换为ascii码的形式表示。

比如

    data = {
        'msg': 'success',
        'context': request.path_info,
        '信息': '正常'
    }
会被表示为:{"msg": "success", "context": "/get_data", "\u4fe1\u606f": "\u6b63\u5e38"}

如何让他直接显示中文的返回呢?只需在JsonResponse后面加上这样一条参数:

return JsonResponse(data, json_dumps_params={'ensure_ascii': False})

就能正常返回中文了,就像这样:{"msg": "success", "context": "/get_data", "信息": "正常"}

另外,如果你发现返回的json是字符串,而且有很多转义字符(斜杠)

这个解决方案是先把字符串转化为json对象json.loads('字符串'),然后再进行JsonResponse

浏览器上方便的Json格式化插件:JsonFomatter、JsonView



url正则匹配是按照列表书写顺序从上到下进行遍历,没有最优匹配的概念,匹配到就不会继续往后查找了。

我们通常直接指定以^开头,在结尾处直接添加反斜线。如果需要固定匹配,结尾需要加上$


获取URL路径上的参数

url的组成:

协议(schema):HTTP、HTTPS、FTP、RTMP

域名(domain):ip:port  HTTP没有书写端口默认80端口。HTTPS 443。

路径(path):相对于主机的绝对路径

参数(QueryString):GET请求参数

锚点:#footer 用于页面定位


获取路径上的参数和URL有关系,后面的参数就没关系了。

正则获取数据:用括号()

url(r'^student/(\d+)/', views.student),      这里获取的是一串数字


在这里多写一个圆括号,views里面对应的函数就要多一个参数,个数对应必须一致不加会引起服务器错误。

def student(request, s_id):
    return HttpResponse('获取一个学生信息成功')
收到的信息类型变为字符串。


rander()里面可以写context=locals(),内置函数,将局部变量使用字典的方式打包,key是变量名,value是数据。


如点击班级列表的链接,获取该班级里面的学生信息:

# views里面 

def get_grade(request):
    gread_list = Grade.objects.all()
    return render(request, 'gradelist.html', locals())


def get_students(request, g_id):
    grade = Grade.objects.get(pk=g_id)
    students = grade.student_set.all()
    context = {
        "students": students
    }
    return render(request, 'students.html', context=context)

#  urls里面
    url('getgrade/', views.get_grade),
    url('getstudents/(\d+)/', views.get_students),


# gradelist.html    这里面的<a></a>是超链接
<ul>
    {% for greads in gread_list %}
    <li><a href="/app/getstudents/{{ greads.id }}/">{{greads.g_name}}</a></li>
    {% endfor %}

    <li></li>
</ul>
多个参数:


 url(r'^gettime/(\d+)/(\d+)/(\d+)', views.get_time),

def get_time(request, hour, minute, second):
    return HttpResponse('传入时间 %s:%s:%s' % (hour, minute, second))
路径参数默认是位置参数,按照书写顺序进行匹配。


当然也可以写关键字参数

url(r'^getdate/(?P<year>\d+)/(?P<month>\d+)/(?P<day>\d+)', views.get_date),


def get_date(request, day, month, year):
    return HttpResponse('日期:%s-%s-%s' % (year, month, day))

URL反向解析

需要先在跟路由上加一个参数

url('Two/', include('Two.urls', namespace='second')),

子路由添加一个name
url(r'^learn/', views.learn, name='learn'),

这样就可以根据namespace和name找到了


然后你运行的时候又会获得一个报错:

'Specifying a namespace in include() without providing an app_name '
django.core.exceptions.ImproperlyConfigured: Specifying a namespace in include() without providing an app_name is not supported. Set the app_name attribute in the included module, or pass a 2-tuple containing the list of patterns and app_name instead.

这是django1和django2的区别导致的,有两种解决方法:

1.在include中传入第二个参数——app的名字     url('Two/', include(('Two.urls', 'Two'), namespace='second')),

2.在每一个app的urls里面添加app_name变量   app_name = 'Two'

详见这篇博客:https://blog.csdn.net/Martin_Yan/article/details/84982056


怎么找呢?在HTML模板里面这样写:


<a href="{% url 'second:learn' %}">去学习</a>
second是namespace,learn是name,这样可以动态获取链接


有位置参数的直接在后面写就行
<a href="{% url 'second:get_time' 15 31 48 %}">Time</a>
关键字直接写 变量名=值 就行




本文作者:赵苦瓜      文章标题: 【点滴记录】Django框架的入门 - 第四篇(View层、GET、POST、反向解析)
本文地址:https://blog.jixiaob.cn/?post=41
版权声明:若无注明,本文皆为“赵苦瓜のBlog~”原创,转载请保留文章出处。

返回顶部    首页    后花园  
版权所有:赵苦瓜のBlog~    站长: 赵苦瓜    程序:emlog   鲁ICP备20030743号-1   鲁公网安备37048102006726 萌ICP备20222268号    sitemap