Django之 路由层

一.路由层

     1.路由匹配规则 (正则匹配):

        
    urlpatterns = [
                url(r'^admin/', admin.site.urls),
                url(r'^$',views.home),
                url(r'^test/$',views.test),
                url(r'^testadd/$',views.testadd),
                url(r'',views.error)
            ]

    注意: 第一个参数是正则表达式,匹配规则按照从上往下依次匹配,匹配到一个之后立即匹配,直接执行对应的视图函数

网站首页路由:
    url(r'^$',views.home)

网站不存在页面:
    url(r'',views.error)

       2.无名分组 (将加括号的正则表达式匹配到的内容当做位置参数自动传递给对应的视图函数):

url(r'^test/(d+)/',views.test),  # 匹配一个或多个数字
        
        

def  test(request,xxx):
     print(xxx)
     return HttpResponse('test')

     3.有名分组(将加括号的正则表达式匹配到的内容当做关键字参数自动传递给对应的视图函数):

url(r'^test/(?P<year>d+)/',views.test),  # 匹配一个或多个数字
        
def  test(request,year):
      print(year)
      return HttpResponse('test')

    注意: 无名分组和有名分组不能混着用!!!

url(r'^test/(d+)/(?P<year>d+)/',views.test)

     4.支持用一类型多个形式匹配:

无名分组多个:
        url(r'^test/(d+)/(d+)/',views.test),
有名分组多个:
        url(r'^test/(?P<year>d+)/(?P<xxx>d+)/',views.test),

 二.反向解析(根据名字动态获取到对应路径):

     

视图导入reverse:
from django.shortcuts import reverse

路由路径起别名:        
url(r'^index6668888/$',views.index,name='index')
# 可以给每一个路由与视图函数对应关系起一个名字
# 这个名字能够唯一标识出对应的路径
# 注意这个名字不能重复是唯一的
        

1.前后端使用反向解析:

    前端使用
        {% url 'index' %}
        {% url '你给路由与视图函数对应关系起的别名' %}
    
    后端使用
        reverse('index')
        reverse('你给路由与视图函数对应关系起的别名')

2.无名分组反向解析:

        user_list = models.User.objects.all()
        
        
        url(r'^edit/(d+)/',views.edit,name='edit')
        前端模板语法
            {%for user_obj in user_list%}
                <a href='edit/{{ user_obj.pk }}/'></a>
            {% endfor %}
        
        视图函数
        from django.shortcuts import reverse
        def edit(request,edit_id):
            url = reverse('edit',args=(edit_id,))
            
        模板
            {% url 'edit' edit_id %}

3.有名分组反向解析:

        后端使用
            # 后端有名分组和无名分组都可以用这种形式
            print(reverse('list',args=(10,)))
            # 下面这个了解即可
            print(reverse('list',kwargs={'year':10}))
        前端使用
            # 前端有名分组和无名分组都可以用这种形式
            {% url 'list' 10 %}
            # 下面这个了解即可
            {% url 'list' year=10 %}

总结:针对有名分组与无名分组的反向解析统一采用一种格式即可

        后端
        reverse('list',args=(10,))  # 这里的数字通常都是数据的主键值
        前端
        {% url 'list' 10 %}
    反向解析的本质:就是获取到一个能够访问名字所对应的视图函数

三.路由分发

django每一个app下面都可以有自己的urls.py路由层,templates文件夹,static文件夹

项目名下urls.py(总路由)不再做路由与视图函数的匹配关系而是做路由的分发
from django.conf.urls import include
    
# 路由分发  注意路由分发总路由千万不要$结尾
    url(r'^app01/',include(app01_urls)),
    url(r'^app02/',include(app02_urls))
    
# 在应用下新建urls.py文件,在该文件内写路由与视图函数的对应关系即可
    from django.conf.urls import url
    from app01 import views
    urlpatterns = [
        url(r'^index/',views.index)
    ]

四.名称空间 (避免重名造成的问题):

   from app01 import urls as app01_urls
from app02 import urls as app02_urls

url(r'^app01/',include(app01_urls,namespace='app01')), url(r'^app02/',include(app02_urls,namespace='app02')) app01.urls.py from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index,name='index') ] app02.urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index,name='index') ] app01.views.py reverse('app01:index') app02.views.py reverse('app02:index')

一般简便处理方法:

   from app01 import urls as app01_urls
from app02 import urls as app02_urls
    url(r'^app01/',include(app01_urls)),
    url(r'^app02/',include(app02_urls))
    app01.urls.py
        from django.conf.urls import url
        from app01 import views
        urlpatterns = [
            url(r'^index/',views.index,name='app01_index')
        ]
    
    app02.urls.py
        from django.conf.urls import url
        from app02 import views
        urlpatterns = [
            url(r'^index/',views.index,name='app02_index')
        ]
    
    app01.views.py
    reverse('app01:app01_index')
    
    app02.views.py
    reverse('app02:app02_index')

进一步简化:


    url(r'^app01/',include('app01.urls')),
    url(r'^app02/',include('app02.urls'))
    #app01.urls相当于from app01 import urls

app01.urls.py
from django.conf.urls import url from app01 import views urlpatterns = [ url(r'^index/',views.index,name='app01_index') ] app02.urls.py from django.conf.urls import url from app02 import views urlpatterns = [ url(r'^index/',views.index,name='app02_index') ] app01.views.py reverse('app01:app01_index') app02.views.py reverse('app02:app02_index')

五.伪静态网页

 搜索优化seo
 url(r'^index.html',views.index,name='app01_index')

六.虚拟环境 (不同的项目配置不同的python解释器):

    1.django1.0与django2.0之间的区别:

django2.0里面的path第一个参数不支持正则,你写什么就匹配,100%精准匹配
        
django2.0里面的re_path对应着django1.0里面的url

     2.虽然django2.0里面的path不支持正则表达式,但是它提供五个默认的转换器:

        str,匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
        int,匹配正整数,包含0。
        slug,匹配字母、数字以及横杠、下划线组成的字符串。
        uuid,匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
        path,匹配任何非空字符串,包含了路径分隔符(/)(不能用?)

           PS:路由匹配到的数据默认都是字符串形式

     3.自定义转换器:

1.正则表达式
2.类
3.注册


class FourDigitYearConverter:
        regex = '[0-9]{4}'
        def to_python(self, value):
            return int(value)
        def to_url(self, value):
            return '%04d' % value  # 占四位,不够用0填满,超了则就按超了的位数来!
register_converter(FourDigitYearConverter, 'yyyy')

七. FBV与CBV

        FBV:基于函数的视图

          CBV:基于类的视图:

url(r'^mycls/',views.MyCls.as_view())    # url(r'^mycls/',views.view)
    
class MyCls(View):
    def get(self,request):
        return render(request,'index.html')
    def post(self,request):
        return HttpResponse('post')

     无论是FBV还是CBV路由层都是路由对应视图函数内存地址

     源码:

       

        

 url(r'^mycls/',views.MyCls.as_view()) ==>
 url(r'^mycls/',views.view)

               

自身没有dispatch方法,再从父类中查找 (通过反射拿到post和get方法名,加括号执行):  

八.JsonResponse对象 
from django.http import JsonResponse
    def index(request):
        # res = {'name':'Jason大帅比','password':18}
        # return HttpResponse(json.dumps(res))
        return JsonResponse({'name':'Jason大帅比','password':'1888888'},json_dumps_params={'ensure_ascii':False})

json序列化显示中文的改动的一般方式 (在dumps括号内补一个ensure_ascii=False):

分析JsonResponse源码:


所以改法如下:

JsonResponse({'name':'Jason大帅比','password':'1888888'},json_dumps_params={'ensure_ascii':False})

     九.简单文件上传:

 前端需要注意的点:
    1.method需要指定成post
2.enctype需要改为formdata格式

后端暂时需要注意的是:
      1.配置文件中注释掉csrfmiddleware中间件
      2.通过request.FILES获取用户上传的post文件数据

file_obj = request.FILES.get('my_file')
        print(file_obj.name)
        with open(file_obj.name,'wb') as f:
            for line in file_obj.chunks():
                f.write(line)
    

补充路径知识点:

print('path:',request.path)
print('full_path:',request.get_full_path())
    
path: /upload_file/
full_path: /upload_file/?name=jason


原文地址:https://www.cnblogs.com/sima-3/p/10999130.html