django路由

1.2 urlpatterns
一个url实例的对象,全在根配置搞定,内部由url组成
在django2.0以下的版本中定义url组成:
    url(r‘^learn/’, views.learn)
在django2.0以上版本中定义path和re_path:
    from django.urls import path, re_path
    path(‘learn/’, views.learn)
    或
    re_path(‘learn/’, views.learn)  # re_path中定义的路由地址可以写正则表达式

1.3 路由分发
在工程目录的urls.py中编写配置规则,分别引入各各应用中创建的urls.py 文件
在django2.0以下版本中定义路由分发:
    from django.conf.urls import include
    urlpatterns = [
        url(r’^xxx/’, include(‘app.urls’))
    ]
在django2.0以上版本中定义路由分发:
    from django.urls import path, include
    urlpatterns = [
        path('xxx/', include('app.urls'))
        或
        path('xxx/', include(('应用名.urls', '应用名')))
    ]

注意:
    路由配置规则注意事项:
        路由匹配时从上到下进行遍历,匹配到就不会继续向后查找了
        匹配的路由前方不需要加反斜杠

2. 获取url路径的参数

2.1 url传递一个参数
2.1.1 Django2.0以下版本路由匹配一个参数的规则
如果需要从url中获取一个值,需要对正则加小括号
url(r‘^grade/(\d+)$’, views.getStudent)
注意,url匹配中添加了()取参,在请求调用的函数中必须接收 def getStudent(request, classid)
image.png
2.1.2 django2.0以上版本路由匹配一个参数的规则

​ django2.0以上版本中定义路由时,可以使用path方式和re_path两种方式,如下定义以path形式定义路由。path方式中定义接收参数时,可以指定接受参数的类型:

定义接收参数的语法为: <转换器: 参数名>

定义接受参数的常用转换器为: int,str,uuid,path

例子如下:

定义接收整形的参数:path('params/<int: id>/', views.params)

定义接收字符串的参数:path('params/<str: name/', views.params)

定义接收uuid类型的参数:path('params/<uuid: uid>/', views.params)

定义接收路径path的参数:path('params/<path: path>/', views.params)

注意:使用<转换器:参数名>的形式进行定义接受参数时,接受的类型由转换器指定,参数的值由指定参数名接受。

2.2 url传递多个参数
2.2.1 Django2.0以下版本路由匹配多个参数规则
  1. 使用正在匹配路由中的参数
如果需要获取url路径中的多个参数,那就添加多个括号,默认按照顺序匹配路径名字,参数顺序必须固定
定义url中传递三个参数的地址:
    url(r‘^news/(\d{4})/(\d)+/(\d+)$’, views.getNews)
    实现方法:匹配年月日 def getNews(requests, year, month, day)
image.png

2.使用关键词获取参数
参数也可以使用关键字参数形式,参数顺序可以任意 url(r’news/(?P\d{4})/(?P\d)+/(?P\d+)$’, views.getNews)


image.png

注意:定义路由时定义接受第一个参数的变量为year,接受第二个参数的变量为month,接受第三个参数的变量为day,因此在视图函数中定义接收参数的变量的顺序可以随意的定义。

2.2.2 Django2.0以上版本路由匹配多个参数的规则

定义url中传递三个参数的地址:

path(‘params/<int: year>/<int: month>/<int: day>/’, views.params)
或者
re_path(’params/(?P<year>\d{4})/(?P<month>\d)+/(?P<day>\d+)$’, views.getNews)
或者
re_path(‘params/(\d{4})/(\d+)/(\d+)$’, views.params)
实现方法:匹配年月日 def params(requests, year, month, day)

注意:定义路由时定义接受第一个参数的变量为year,接受第二个参数的变量为month,接受第三个参数的变量为day,因此在视图函数中定义接收参数的变量的顺序可以随意的定义。

3. 反向解析

3.1 在模板中进行反解析

关键字参数{% url namespace:name key=value key1=value1 %}

在Django2.0以下版本中定义包含url的include语法::
在根urls中定义:
    url(r’^apps/’, include(‘App.urls’, namespace=’app’))
在子urls中定义:
    url(r’^hello/(\d+)’, views.hello, name=’sayhello’)

在Django2.0以上版本中定义包含url的include语法:
在根urls中定义:
path(’apps/’, include((‘app.urls’, 'app'), namespace=’app’))
在应用app的子urls中定义:
path(’hello/<int:id>/’, views.hello, name=’sayhello’)

在模板中使用: ​ <a href=’{% url ‘app:sayhello’ grade_id%}’> ​ 其中grade_id是参数,其中参数可以使用位置参数,也可以使用关键词参数,和配置urls一样


image.png

3.2 在views中使用反向解析
使用反向解析优点 如果在视图中,模板中使用硬编码连接,在url配置发生改变时,需要变更的代码会非常多,这样导致我们的代码结构不是很容易维护,使用反向解析可以提高我们代码的扩展性和可维护性

HttpResponseRedirect(reverse(namespace:name, kwargs = {key1 : value1, key2 : value2}))
kwargs 是字典


image.png

4. 视图

4.1 错误视图

位置:通常在应用下的views.py中定义 错误视图: ​
404视图(页面没有被找到 page not found) ​
400视图(客户端操作错误 bad request) ​
403视图(权限错误 403 forbidden ) ​
500视图(服务器内部错误 server error)

5.请求与响应

5.1 HttpRequest定义
服务器在接收到http请求后,会根据报文创建HttpRequest对象
视图中第一个参数就是HttpRequest对象
Django框架会进行自己的包装,之后传递给视图
属性:
request.FILES 获取图片, 文件信息
request.path 获取路由地址
request.COOKIES 获取cookie内容,字典,包含了所有的COOKIES
request.session 获取服务器中保存的session数据  类似字典,表示会话
request.GET('key') 获取get请求传递的参数 没有key会报错, 
可以加.get('key')没有key也不会报错
request.POST('key') 获取post请求传递的参数 没有key会报错, 
可以加.get('key')没有key也不会报错
django没有put, patch, delete这些, 但django有另一个处理方式
方法: is_ajax()   判断是否是ajax(),通常在移动端和js中

5.2 响应QueryDict类型

1)类似字典的结构数据,与字典的区别,可以存在相同的键
2)GET和POST都是QueryDict对象
3)QueryDict中数据获取方式
    dict[‘name’] 或者dict.get(‘name’)
    获取指定key对应的所有值
    dict.getlist(‘name’)
image.png

如下,获取重复提交数据的方法:


image.png

5.3 响应

1)可以直接返回一个HttpResponse对象:
    服务器返回给客户端的数据,HttpResponse由程序员自己创建
    不使用模板,直接HttpResponse()
2)可以返回模板
调用模板,进行渲染,直接使用render一步到位
返回表达式:
    render(request, template_name, context)
        request  请求体对象
        template_name  模板路径
        context  字典参数,用来填坑

3)属性
    Content   返回的内容
    Charset   编码格式
    status_code  响应状态码(200,4xx,5xx)
        4xx 客户端的错误
        5xx 服务端的错误
    content_type   MIME类型,定义传输类型的,比如有xml,html,png等等,比如content_type=’image/jpg’
4)方法
    init    初始化内容
    write(xxx) 直接写到文本
    flush 冲刷缓冲区
    set_cookie(key, value=’’, max_age=None, exprise=None)
    delete_cookie(key)   删除cookie,上面是设置
4)重定向
    HttpResponseRedirect响应重定向:可以实现服务器内部的跳转
    Return HttpResponseRedirect(‘/xxx/xxx’)
    使用的时候推荐使用反向解析
    JsonResponse
    使用json数据的请求,通常用在异步请求上JsonResponse(dict)
    content_type是application/json

========页面截图==========

一,我们不能将所有包的路由都放在一个路由文件中,

app包的路由就要放在app包里的urls.py文件中,
uesr包的路由就要放在user包里的urls.py文件中,
所以我们要拆分 - 路由分发

1.在主目录的urls.py文件中,要导入
from django.urls import include
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    # 路由分发  include里面的'user'就是路由的user/
    path('user/', include(('user.urls', 'user'), namespace='user')),
    # 定义namespace参数  namespace='a'是代替app/  现在app/这个前缀都无所谓
    path('app/', include(('app.urls', 'app'), namespace='a')),
]

path('app/', include(('应用名.urls', '应用名'), namespace='a'))

2.在app/urls.py文件中
from django.urls import path, re_path
from app.views import *

urlpatterns = [
    path('index/', index),
    # 访问index 跳转redirect_stu
    path('redirect_stu/', redirect_stu, name='red'),
    path('redirect_params/<int:id>/', redirect_params, name='rep'),
    # 用正则时一定要在path前加re  - re_path
    re_path('redirect_params_re/(\d+)/', redirect_params_re, name='reb'),
    path('req/', req, name='req'),
    path('res/', res, name='res'),
]

然后写相应的views,

3.views.py文件中写对应的urls的函数
from django.http import HttpResponse, HttpResponseRedirect, JsonResponse
from django.shortcuts import render
# HttpResponseRedirect实现跳转功能的

from django.urls import reverse


def index(request):
    if request.method == 'GET':
        # 跳转到另外一个路由地址上

        # 无参的情况下进行跳转
        # 第一种跳转: 使用硬编码url
        # return HttpResponseRedirect('/app/redirect_stu/')  # 不加/app 会报错, 没有写name时
        # 第二种跳转: 使用反向解析 reverse('namespace:name')
        # return HttpResponseRedirect(reverse('a:red'))  # 反向解析'a:red'就是namespace:name

        # 有参的情况下跳转
        # return HttpResponseRedirect('/app/redirect_params/16/')
        # return HttpResponseRedirect(reverse('a:rep', kwargs={'id': 18}))
        # return HttpResponseRedirect(reverse('a:reb', args=(20,)))
        return render(request, 'index.html')


def redirect_stu(request):
    if request.method == 'GET':
        # 跳转到另外一个路由地址上 在index.html中<a href="{% url 'a:red' %}">无参跳转
        return HttpResponse('我是跳转方法')


def redirect_params(request, id):
    if request.method == 'GET':
        # 跳转到另外一个路由地址上,在index.html中{% url 'a:rep' 20 %}
        return HttpResponse('带参的跳转, 参数: %s' % id)


def redirect_params_re(request, id):
    if request.method == 'GET':
        # 跳转到另外一个路由地址上,在index.html中{% url 'a:reb' 20 %}
        return HttpResponse('带参的跳转2, 参数: %s' % id)


def req(request):
    if request.method == 'GET':
        return HttpResponse('请求')


def res(request):
    if request.method == 'GET':

        # 下面几个都是响应
        # return HttpResponse('响应')
        # return HttpResponseRedirect('跳转')
        # return render()
        # return JsonResponse({'code': 200})
        response = HttpResponseRedirect('/app/index/')
        response.set_cookie('token', 123456)
        return response

2.另一个user包的路由

(装饰器修饰等)

1.在user/urls.py中
from django.contrib.auth.decorators import login_required
from django.urls import path
from user.views import *
from utils.functions import is_login

# django自带的登录注册的实现
urlpatterns = [
    path('register/', register, name='register'),
    path('login/', login, name='login'),
    # 给index加装饰器登录才让访问不登陆不让访问
    # path('index/', login_required(index), name='index'), # django自带的
    path('index/', is_login(index), name='index'),
    path('logout/', login_required(logout), name='logout'),

    # 使用session实现登录注册注销功能
    path('my_register/', my_register, name='my_register'),
    path('my_login/', my_login, name='my_login'),
    # session操作语法
    path('sess/', sess_operate, name='sess_operate')

]
2./user/views.py中
from django.contrib import auth
from django.contrib.auth.hashers import make_password, check_password
from django.contrib.auth.models import User
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse

from user.models import MyUser


def register(request):
    if request.method == 'GET':
        return render(request, 'register.html')
    if request.method == 'POST':
        # 获取数据并校验
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        if username and password and password2 and password == password2:
            if not User.objects.filter(username=username).exists():
                # 这样写避免了if else 太多了不好, 尽量少用
                # 保存
                User.objects.create_user(username=username,
                                         password=password)
                # 跳转
                return HttpResponseRedirect(reverse('user:login'))
            error = '用户已存在, 请更换账号'
            return render(request, 'register.html', {'error': error})
        else:
            error = '注册参数有误, 请确认'
            return render(request, 'register.html', {'error': error})


def login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    if request.method == 'POST':
        # 获取数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username and password:
            # 校验
            user = auth.authenticate(username=username,
                                     password=password)
            if user:
                # 设置登录状态
                # 查看session是否变化, request.user这个东西的变化
                # 变化: 开始是匿名用户, 运行这一步之后就显示你写的用户名了
                auth.login(request, user)
                # auth.logout(request)
                return HttpResponseRedirect(reverse('user:index'))
            error = '用户名或者密码错误'
            return render(request, 'login.html', {'error': error})

        else:
            error = '登录信息请填写完整'
            return render(request, 'login.html', {'error': error})


def index(request):
    if request.method == 'GET':
        # request上面绑定属性的, 如user属性, {{ user }}来调用
        return render(request, 'index.html')


def logout(request):
    if request.method == 'GET':
        auth.logout(request)
        return HttpResponseRedirect(reverse('user:login'))


# 不用django里面的方法
def my_register(request):
    if request.method == 'GET':
        return render(request, 'register.html')
    if request.method == 'POST':
        # 获取数据并校验
        username = request.POST.get('username')
        password = request.POST.get('password')
        password2 = request.POST.get('password2')
        if username and password and password2 and password == password2:
            if not MyUser.objects.filter(username=username).exists():
                # 保存
                pwd = make_password(password)  # 将密码加密(编码),不然下面的密码是明文的
                MyUser.objects.create(username=username,
                                      password=pwd)
                # 跳转
                return HttpResponseRedirect(reverse('user:login'))
            error = '用户已存在, 请更换账号'
            return render(request, 'register.html', {'error': error})
        else:
            error = '注册参数有误, 请确认'
            return render(request, 'register.html', {'error': error})


def my_login(request):
    if request.method == 'GET':
        return render(request, 'login.html')

    if request.method == 'POST':
        # 获取数据
        username = request.POST.get('username')
        password = request.POST.get('password')
        if username and password:
            # 校验
            user = MyUser.objects.filter(username=username).first()
            if user:
                # 校验密码
                if check_password(password, user.password):
                    # TODO 登录操作 m
                    request.session['user_id'] = user.id
                    return HttpResponseRedirect(reverse('user:index'))
            error = '用户名或者密码错误'
            return render(request, 'login.html', {'error': error})

        else:
            error = '登录信息请填写完整'
            return render(request, 'login.html', {'error': error})


def sess_operate(request):
    if request.method == 'GET':
        # 取session_key的值
        session_key = request.session.session_key
        print(session_key)
        # TODO 退出: 1.删除session-data(标识符)的字段 但客户端的数据还没删(删的是数据库的信息)
        # del request.session['user_id']
        # TODO 2.通过key来删掉整个数据退出 但客户端的数据还没删(删的是数据库的信息)
        # request.session.delete(session_key)
        # TODO 3.通过在客户端删除, 数据库也会删除数据
        request.session.flush()

        return HttpResponseRedirect('操作session数据')
3./user/models.py中 - 要用自己定义的登录注册先创建一个类
from django.db import models


class MyUser(models.Model):
    username = models.CharField(max_length=10, unique=True, null=False)
    password = models.CharField(max_length=255, null=False)

    class Meta:
        db_table = 'my_user'
3.有django自带的装饰器,
也可以用中间件
还可以写个装饰器(建一个utils包, 创建functions.py文件)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,088评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,715评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,361评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,099评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 60,987评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,063评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,486评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,175评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,440评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,518评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,305评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,190评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,550评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,880评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,152评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,451评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,637评论 2 335

推荐阅读更多精彩内容

  • 1. 路由定义位置 Django的主要路由信息定义在工程同名目录下的urls.py文件中,该文件是Django解析...
    Elvis_zhou阅读 753评论 0 0
  • 一 Django中路由的作用 URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL与要...
    乔治大叔阅读 347评论 0 1
  • python django官方文档地址:https://docs.djangoproject.com/zh-han...
    漓江塔塔主阅读 1,301评论 0 0
  • 已经同步到gitbook,想阅读的请转到gitbook: Django 1.10 中文文档 URL dispatc...
    leyu阅读 14,170评论 0 16
  • 为了日更而日更 这个周末是个忙碌的日子。 醒来都己经是上午十点了。 然后就去煲粥。 由于昨晚睡得不好,脖子很疼。 ...
    玲ining阅读 97评论 0 1