美文网首页
django路由

django路由

作者: 遥远的她197 | 来源:发表于2019-03-26 20:23 被阅读0次
    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文件)

    相关文章

      网友评论

          本文标题:django路由

          本文链接:https://www.haomeiwen.com/subject/hxinvqtx.html