• 继续Django


    关于获取数据和文件上传

    实现的代码如下:

    1、在views.py里写如下函数

    def login(request):
        if request.method == "GET":
            return render(request,"login.html")
        elif request.method == "POST":
            # v = request.POST.get("gender")
            # print(v)
            # f = request.POST.getlist("city")
            # print(f)
            # c = request.POST.getlist("favor")
            # print(c)
            # file = request.POST.get("upload")
            # print(file)
            obj = request.FILES.get("upload")
            print(obj, type(obj), obj.name)
            import os
            file_path = os.path.join("upload_dir", obj.name)
            f = open(file_path, mode="wb")
            for i in obj.chunks():
                f.write(i)
            f.close()
            return render(request, "login.html")
        else:
            return redirect('/index/')

    2、login.html文件中代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/login2/" method="POST" enctype="multipart/form-data">
            <p>
                <input type="text" name="user" placeholder="用户名">
            </p>
            <p>
                <input type="password" name="pwd" placeholder="密码">
            </p>
            <p>
                男:<input type="radio" name="gender" value="1">
                女:<input type="radio" name="gender" value="2">
            </p>
            <p>
                乒乓球:<input type="checkbox" name="favor" value="1">
                篮球:<input type="checkbox" name="favor" value="2">
                羽毛球:<input type="checkbox" name="favor" value="3">
            </p>
            <p>
                <select name="city" multiple>
                    <option value="sh">上海</option>
                    <option value="bj">北京</option>
                    <option value="tj">天津</option>
                </select>
            </p>
            <p>
                <input type="file" name="upload">
            </p>
            <input type="submit" value="提交">
        </form>
    </body>
    </html>

    3、关于上述代码中知识点的总结:

    • 当获取单个值的时候类似单选框,可以给标签设置name属性,然后通过类似request.POST.get("gender")方式获取相应的值即:

    request.POST.get("标签name属性值")

    • 当获取多个值的时候类似复选框以及可以多选的select的时候,通过request.POST.getlist("city")的方式获取相应的内容,这样得到的是一个列表,即:

    request.POST.getlist("标签name属性值")

    • 当时获取上传文件的时候

    首先form表单中应该有如下属性:enctype="multipart/form-data"

    然后在views.py中通过obj = request.FILES.get("upload")获取文件的一个对象,通过打印可以看出这个对象的详细内容为:<class 'django.core.files.uploadedfile.InMemoryUploadedFile'>即:

    request.FILES.get("标签name属性值")

    最后通过如下方式循环将文件接收:

    import os
    file_path = os.path.join("upload_dir", obj.name)
    f = open(file_path, mode="wb")
    for i in obj.chunks():
        f.write(i)
    f.close()

    这样最后所有的上传文件都会放在upload_dir目录下,当然这个目录需要自己提前创建

    关于FBV和CBV

    1、    FBV

    FBV对应的是function base view

    urls.py

    index--->函数名

    views.py

    def 函数(request)

    2、    CBV

    CBV对应的是class base view

    3、    之前写的都是FBV的方式多点,下面通过一个CBV的例子来理解CBV

    首先先写一个home.html文件,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <form action="/home/" method="post">
            <input type="text" name="user">
            <input type="submit">
        </form>
    </body>
    </html>

    views.py中写如下代码:

    from django.views import View
    # 这里Home需要继承View
    class Home(View):
        def get(self,request):
            print(request.method)
            return render(request,"home.html")
        def post(self,request):
            print(request.method)
            return render(request, "home.html")

    urls.py文件中增加如下代码高亮部分

    from django.contrib import admin
    from django.urls import path
    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('home/', views.Home.as_view()),
    ]

    效果如下:

    当访问页面内容时:

    查看django打印的日志可以看出都是的get请求:

    当点击提交的时候:查看django的日志可以看出是post请求:

     

    4、关于CBV,django在内部是如何实现的?

    分析

    当访问页面的时候:头部中请求的方法是GET方式:

    当点击提交的时候:头部中的请求的方法是POST方式:

    其实当发送请求的时候,是将Request URL以及Request Method同时传递给django,先匹配url,然后去找对应的类,然后找相应的方法,也就是post或者get等,这里判断是post还是get是通过反射实现的。

    查看view类里面有一个函数:dispatch函数

        def dispatch(self, request, *args, **kwargs):
            # Try to dispatch to the right method; if a method doesn't exist,
            # defer to the error handler. Also defer to the error handler if the
            # request method isn't on the approved list.
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
            else:
                handler = self.http_method_not_allowed
            return handler(request, *args, **kwargs)

    从函数可以看出是dispatch先做了一个反射的功能

    所以这个请求的过程是:请求--->dispatch--->get/post

    将views.py中的代码更改为如下:

    from django.views import View
    # 这里Home需要继承View
    class Home(View):
        # 这样这里就相当于一个装饰器的功能,可以自己定制化内容
        def dispatch(self, request, *args, **kwargs):
            # 调用父类中dispatch方法
            print("before")
            result = super(Home, self).dispatch(request,*args,**kwargs)
            print("after")
            return result
        def get(self,request):
            print(request.method)
            return render(request,"home.html")
        def post(self,request):
            print(request.method)
            return render(request, "home.html")

    运行结果如下:

     如上可以看出当再次访问home页面的时候,每次都需要打印before以及after

    模板语言中字典的循环

    views.py中写如下代码:

    USER_DICT = {
        "K1":"root1",
        "K2":"root2",
        "K3":"root3",
        "K4":"root4",
        "K5":"root5",
    }
    
    def index(request):
        return render(request,"index.html",{"user_dict":USER_DICT})

    创建一个index.html文件,代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for k,row in user_dict.items %}
                <li>{{ k }}-{{ row }}</li>
            {% endfor %}
        </ul>
    </body>
    </html>

    按照上面的循环方式结果如下:

    同样的字典循环包含以下几种方式:

    user_dict.items ---- 这样循环row为(k,value)

    user_dict.values ---- 这样循环row为value值

    user_dict ----这样循环的话row为k值

    关于URL路由系统

    1、实现一个点击查看详情的例子(方法一)

    views.py中的代码如下:

    from django.shortcuts import render
    
    USER_DICT = {
        "K1":{"name":"root1","email":"root1@qq.com"},
        "K2":{"name":"root2","email":"root2@qq.com"},
        "K3":{"name":"root3","email":"root3@qq.com"},
        "K4":{"name":"root4","email":"root4@qq.com"},
    }
    
    def index(request):
        return render(request,"index.html",{"user_dict":USER_DICT})
    
    def detail(request):
        nid = request.GET.get("nid")
        detail_info = USER_DICT[nid]
        return render(request,"detail.html",{"detail_info":detail_info})

    index.html文件中的代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for k,row in user_dict.items %}
                <li><a target="_blank" href="/detail/?nid={{ k }}">{{ row.name }}</a></li>
            {% endfor %}
        </ul>
    </body>
    </html>

    detail.html代码为如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>详细信息</h1>
        <h6>用户名:{{ detail_info.name }}</h6>
        <h6>邮箱:{{ detail_info.email }}</h6>
    </body>
    </html>

    urls.py中写如下代码高亮部分:

    from django.contrib import admin
    from django.urls import path
    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        path('home/', views.Home.as_view()),
        path('detail/', views.detail),
    ]

    实现效果为当打开index主页的时候显示:

    点击某个选项,则可以显示详细信息:

    2、实现一个点击查看详情的例子(方法二)

    urls.py中的代码如下高亮部分:

    from django.contrib import admin
    from django.urls import path,re_path
    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('index/', views.index),
        path('home/', views.Home.as_view()),
        # path('detail/', views.detail),
        re_path('detail-(d+).html', views.detail),
    ]

    views.py中的代码如下:

    from django.shortcuts import render
    from django.shortcuts import HttpResponse
    
    USER_DICT = {
        "1":{"name":"root1","email":"root1@qq.com"},
        "2":{"name":"root2","email":"root2@qq.com"},
        "3":{"name":"root3","email":"root3@qq.com"},
        "4":{"name":"root4","email":"root4@qq.com"},
    }
    
    def index(request):
        return render(request,"index.html",{"user_dict":USER_DICT})
    
    def detail(request,nid):
        # return HttpResponse(nid)
        detail_info = USER_DICT[nid]
        return render(request,"detail.html",{"detail_info":detail_info})

    index.html的代码如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <ul>
            {% for k,row in user_dict.items %}
                <li><a target="_blank" href="/detail-{{ k }}.html">{{ row.name }}</a></li>
            {% endfor %}
        </ul>
    </body>
    </html>

    detail.html中代码不变,如下:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>详细信息</h1>
        <h6>用户名:{{ detail_info.name }}</h6>
        <h6>邮箱:{{ detail_info.email }}</h6>
    </body>
    </html>

    最终的效果,点击详细页面之后,地址变为/detail-2.html而不是之前的/detail?nid=K2:

    3、针对上述的例子,我们将urls.py进行修改:

    将 re_path('detail-(d+).html', views.detail),

    修改为:

    re_path('detail-(d+)-(d+).html', views.detail),

    这样就存在两个正则,这样在views.py中获取到的时候也需要两个参数,def detail(request,nid,uid),并且这两个参数和顺序有关,第一个参数就是匹配的第一个正则,第二个匹配第二个正则,这样就会有个弊端,一旦调用函数的时候参数传递错误,那么整个函数里设计这两个参数的计算都会出现问题。

    所以我们通常用如下方法:

    re_path('detail-(?P<nid>d+)-(?P<uid>d+).html', views.detail),

    这样就相当于分组,这样就不会因为顺序问题而影响结果

    其实在views.py中有一个终极的方法:

    def detail(*args,**kwargs),这样当多个参数的就会传递到*args里,当传递字典类型的参数的时候就会传递到**kwargs

    4、name

    name是对URL路由关系进行命名,以后可以根据此名称生成自己想要的URL

    • path('sdfffddddd/', views.index,name="i1"),
    • path('sdfffddddd/(d+)/(d+)/', views.index,name="i2"),
    • path('sdfffddddd/(?P<nid>d+)/(?P<uid>d+)/', views.index,name="i3"),

    注意:

    获取当前URL

    request.path_info

    在函数里可以通过reverse模块找到当前的URL:

    def index(request,*args,**kwargs):

      from django.urls impore reverse

      url1 = reverse("i1")  ----这样就会生成/sdfffddddd/

      url2 = reverse("i2",args=(1,2,)) ---生成/sdfffddddd/1/2/

      url3 = reverse("i3",kwargs={"nid":1, "uid":9}) ---生成/sdfffddddd/1/9

    在模板语言中:

    {% url "i1" %}    ---生成/sdfffddddd/

    {% url "i2" 1 2 %}  --生成/sdfffddddd/1/2/

    {% url "i3" nid=1 uid=3 %} ---生成/sdfffddddd/1/3/

    5、路由分发

    当有 多个app的时候

    当请求来的时候先到项目的urls.py里,这里的配置如下:

    from django.conf.urls import url,include
    from django.contrib import admin
    
    urlpatterns = [
        path('app01/',include("app01.urls")),
        path('app02/',include("app02.urls")),
    
    ]

    根据不同的app去不同的app下找相应的app级别的urls

    这样就实现了路由的分发

    6、默认值

    在url写路由关系的时候可以传递默认参数,如下:

    path('index/', views.index,{"name":"root"}),

    这样在视图函数中,就可以获取这个默认参数name:

    from django.shortcuts import HttpResponse
    
    def index(request,name):
        print(name)
        return HttpResponse("%s is OK" %name)

    7、命名空间

    通过下面例子理解:

    在项目的urls里写入如下代码:

    from django.contrib import admin
    from cmdb import views
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('cmdb/', include("cmdb.urls",namespace="author")),
        path('monitor/', include("monitor.urls")),
    
    ]

    在app的urls里写入如下代码:(注意高亮部分必须有)

    from cmdb import views
    
    app_name="cmdb"
    urlpatterns = [
        path('index/', views.index,name="index"),
    ]

    最后在views视图函数中写入如下代码:

    from django.urls import reverse
    def index(request):
        v = reverse("author:index")
        print(v)
        return HttpResponse("is ok")

    当访问页面:

    关于获取用户请求信息

    我们在视图函数中写的函数中都加了一个request参数,我们可以通过from django.core.handlers.wsgi import WSGIRequest 导入之后通过request.environ查看详细的信息

    而request.environ是一个字典我们循环之后打印:

    for k,v in (request.environ).items():
        print(k,v)

    则可以看到整个请求头的信息

  • 相关阅读:
    HDU 5115 Dire Wolf ——(区间DP)
    2016 ICPC 大连网络赛 部分题解
    CodeForces 707D Persistent Bookcase ——(巧妙的dfs)
    HDU 5806 NanoApe Loves Sequence Ⅱ ——(尺取法)
    【Permutations II】cpp
    【Permutations】cpp
    【Subsets II】cpp
    【Subsets】cpp
    【Search a 2D Matrix】cpp
    【Search Insert Position 】cpp
  • 原文地址:https://www.cnblogs.com/cyfiy/p/10195868.html
Copyright © 2020-2023  润新知