Django2(路由相关) - downtiser/python-one GitHub Wiki

Djnago 处理提交数据

  • 对于接受复选框的多个值,通过request.POST.getlist('name')来获取指定name的复选内容,返回一个列表,对于上传文件,首先要在form标签中添加属性enctype="multipart/form-data",在对应的函数中,通过obj = request.FILES.get('name')获取相应的文件对象,通过obj.name获取文件名,for i in obj.chunks迭代文件中的内容, obj.size获取文件字节
  • request.path_info获取当前请求的url

Django FBV & CBV

  • FBV: Function Base Views, 即对于用户的请求通过函数来处理
  • CBV: Class Base Views, 即对于用户的请求通过相应的类来处理, 在urls中,通过path('page/', views.YourClass.as_view)绑定对应的类, 在类中,定义相应的方法来处理不同类型的请求,能够处理以下几种请求:http_method_names = ['get', 'post', 'put', 'patch', 'delete', 'head', 'options', 'trace'],定义类时要继承django.views中的View类, 实际上是通过反射实现的
from django.views import View
class Home(View): #要继承View这个类
    def dispatch(self, request, *args, **kwargs): #父类中的方法,通过反射实现调用子类中的方法
        #继承并定制重构父类中的dispatch
        print('begin')
        res = super(Home, self).dispatch(request, *args, **kwargs)
        return res

    def get(self, request): #以get方式请求时执行此方法
        print(request.method)
        return render(request, 'home.html')

    def post(self, request): #以post方式请求时执行此方法
        print(request.method)
        return render(request, 'home.html')

url正则匹配

  • re_path('detail-(\d+)/', views.Detail.as_view()),匹配所有detail-数字的url,且动态的数字会被当做参数传入到关联的函数或类中,在函数或类中用*args接受参数,组成一个列表
  • 分组匹配:re_path('detail-(?P<nid>\d+)-(?P<uid>\d+)/', views.Detail.as_view()),此时第一个数字会传给nid这个参数,第二个数字会传给uid这个参数,格式为:(?P<arg>....),函数或类中用**kwargs接受,组成一个字典

path中的name:对url路由关系进行命名,可根据此名称在模板中直接引用url

  • re_path('^detail-(?P<uid>\d+)/', views.Detail.as_view(), name='detail'), 在模板语言中通过{% url 'detail' 123 %}来引用该url的静态部分,即detail-,动态部分123需要手动添加,也可以以uid=123来传入
  • {{ request.path_info }}可以获取当前url,包括动态部分

通过name反向获取url:利用导入的reverse函数,可通过name和必要的参数生成特点url

from django.urls import reverse
path = reverse('detail') #静态url
path = reverse('detail', args=(uid, )) #针对detail-(\d+)/ 这种url
path = reverse('detail', kwargs={'uid': uid}) #针对detail-(?P<nid>\d+)/这种url

url路由转发,如果一个工程内含多个APP,就需要对url进行分组转发,对于不同的APP拥有一套自己的url路由

  • 在工程目录下的urls中:
from django.urls import path, re_path, include #要先导入include
urlpatterns = [
    path('admin/', admin.site.urls),
    path('myApp/', include('myApp.urls')) # app下的路由系统路径
]

这样要访问该APP下的页面,就要以myApp/....这种形式访问,在APP目录下创建urls.py,并导入相应路径:

from django.contrib import admin
from django.urls import path, re_path, include
from myApp import views

urlpatterns = [
    path('admin/', admin.site.urls),
    path('files/', views.files),
    path('home/', views.Home.as_view()),
    path('index/', views.Index.as_view()),
    re_path('^detail-(?P<uid>\d+)/', views.Detail.as_view(), name='detail')
]

url默认值,如果在url中传入参数,例如path('url_test/', views.url_test, {'user': 'root'}),每次访问url时都会将user='root',作为参数传入view函数,所以定义view函数时要接受参数:def url_test(request, user):....

url命名空间:当两个url都指向两个APP,且这两个APP的分路由的某个url具有相同的name时,在对应的函数中进行反解url时会出现冲突,所以可以给url添加命名空间namespace用于标识url

  • 总路由:
urlpatterns = [
    path('space_a/', include(('app01.urls', 'app01'), namespace='space_a')), #注意添加namespace属性时,include的第一个参数要传入一个元组,包括分路由的模块名和应用名, 或者在分路由模块中添加变量 app_name = 应用名
    path('space_b/', include(('app02.urls', 'app02'), namespace='space_b'))
]
  • 分路由a:
urlpatterns = [
    path('index/', views.index_a, name='space')
]
* 分路由b:
```python
urlpatterns = [
    path('index/', views.index_b, name='space')
]
  • 视图函数
def index_a(request):
    url_a = reverse('space_a:space')  # 返回通过namespace为space_a的路由url
    print(url_a)
    return HttpResponse('Index')
def index_b(request):
    url_b = reverse('space_b:space')  # 返回通过namespace为space_b的路由url
    print(url_b)
    return HttpResponse('Index')
  • 模板语言
{% url space_a:space %}
⚠️ **GitHub.com Fallback** ⚠️