温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

Django基础-1:静态文件、路由、视图和模板

发布时间:2020-08-03 18:03:11 来源:网络 阅读:1441 作者:小生博客 栏目:开发技术

小生博客:http://xsboke.blog.51cto.com

                            -------谢谢您的参考,如有疑问,欢迎交流

一、静态文件
二、路由映射
三、视图函数
四、template(模板)基础

  1. 关于静态文件

    1.1 首先需要在配置文件settings.py中指定静态目录
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"statics"),
    )

    1.2 然后在html中使用django模板语言指定静态文件
    {% load static from staticfiles %}
    <link href="{% static "index.css" %}" rel="stylesheet" type="text/css" />
    <script src="{% static "index.js" %} "></script>

    1.3 也可以这样写

    # 指定前缀
    STATIC_URL = '/a/' 
    
    STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"statics"),
    )
    
    <link href="/a/css/index.css" rel="stylesheet" type="text/css" />
    <script src="/a/js/index.js"></script>
  2. 路由映射

    Django URL是一个URL和视图函数的映射表

    urlpatterns = [
    path('admin/', admin.site.urls),
    ]

    urlpatterns = [
    url(正则表达式,views视图函数,参数,别名)
    ]
    参数:可选的要传递给视图函数的默认参数
    别名:一个可选的name参数,用于前端

    注意:要想使用url去配置路径需要加载模块:from django.conf.urls import url

    2.1 无名分组
    url(r'^articles/[0-9]{4}/([0-9]{4})/([0-9]+)/$',views.special_case_2018),
    ^articles:以articles开头匹配articles
    /:目录符号
    [0-9]{4}:包含一个4位数,每一位的范围是0-9
    ():加括号的意思是传入一个参数
    这时候,views.py需要这样写(使用HttpResponsen需要导入这个模块):
    def special_case_2018(req,变量) #可以传入多个变量,用逗号分隔
    return HttpResposen(变量+"year") #将用户输入的内容返回到浏览器上

    2.2 命名分组

    2.2.1 讲解
    import re

    ret = re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')
    
    ?P:固定格式,意思是这种分组是有名字的
    <id>:匹配的名字就是id,可以看做是一个变量,是匹配内容的变量
    \d{3}:是匹配的内容,3个数字。
    \w{3}:就是3个字母
    'weeew34ttt123/ooo':这段字符串就是被匹配的内容,最终结果会匹配出"123/ooo"
    
    print(ret.group())      :取出所有匹配到的内容
    print(ret.group('id'))  :只取出名字为的id的内容
    print(ret.group('name')):只取出名字为的name的内容

    2.2.2 url格式
    urlpatterns = [
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{4})/$',views.year_archive),
    ]

    views.py配置
    def year_archive(req,year,month):               # 使用命名分组,形参必须是url中定义的名字,顺序可以不同
        return HttpResposen(year+"y"+month+"m")

    2.3 参数三
    urlpatterns = [
    url(r'index',views.index,{"name":'dashan'}),
    ]

    def index(req,name):
        return HttpResposen(name)       # 返回"dashan"
        # 如果在使用参数的同时,使用了命名分组,两边的名字如果一样,那么参数会覆盖命名分组

    2.4 参数四
    urlpatterns = [
    url(r'index',views.index,name="dashan"), # name是固定的写法,name就是别名
    ] # name="dashang",代替的就是index,就是index的别名

    这时候,前端可以通过别名去找到视图函数
    
    <form action={% url "dashan" %} method="post">
        <input type="text" name="usernmae">
        <input type="passwrod" name="passwd">
        <input type="submit" name="submit">
    <form>

    2.5 url映射分发(include)
    当有上万页面时,你就得在urls.py中写上万条url匹配,造成数据量大,容易写重,容易造成结藕

    解决方法:在每个app下创建一个urls.py,全局的urls.py只做一个映射
    
    2.5.1 全局urls.py
    
        from django.conf.urls import url,include
        from appname import views
    
        urlpatterns = [
            url(r'^appname',include('appname.urls')),
        ]
    
    2.5.2 app的urls.py
        from django.conf.urls import url,include
    
        urlpatterns = [
            url(r'page1/page1.1',views.page1),      # page1是紧跟appname的内容
            url(r'page2',views.page2),
        ]
  3. 视图函数

    HTTP请求中产生两个核心对象:
    http请求:HttpRequest对象
    http响应:HttpResponse对象
    所在位置:django.http

    # 获取两种请求方法
    request.POST.get
    request.GET.get

    3.1 HttpRequest对象的属性
    path: 请求页面的全路径,不包括域名
    method: 请求中使用的HTTP方法的字符串表示,全大写表示。例如GET和POST
    if req.method == "POST" or req.method == "GET"
    GET: 包含所有HTTP GET参数的类字典对象
    POST: 包含所有HTTP POST参数的类字典对象
    服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
    HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
    if req.POST 来判断是否使用的HTTP POST 方法,应该使用 if req.method == "POST"

    COOKIES:    包含所有cookies的标准python字典对象;key和values都是字符串
    FILE:       包含所有上传文件的类字典对象;files中的米一个key都是<input type="file" name="" />标签中
                name的属性值,files中的每一个values同时也是一个标准的python字典对象,包含下面是哪个keys:
    
                    filename:       上传文件名,用字符串表示
                    content_type:   上传文件的Content Type
                    content:        上传文件的原始内容
    user:       是一个Django.contrib.auth.models.User对象,代表当前登录的用户,如果访问用户当前没有登录,
                user将初始化为django.contrib.auth.models.AnonymousUser的实例。你可以通过user的
                is_authenticated()方法来辨别用户是否登录:
                    if req.user.is_authenticated();只有激活Django中的AuthenticationMiddleware时,该属性
                    才可用
    
    session:    唯一可读写的属性,代表当前会话的字典对象;只有激活Django中的session支持时该属性才可用

    3.2 HttpResponse对象
    对于HttpRequest对象来说,是由django自动创建的,但是,HttpResponse对象就必须我们自己创建,
    每个view请求处理方法必须返回一个HttpResponse对象。

    HttpResponse类在django.http.HttpResponse
    在HttpResponse对象上扩展的常用方法:
        页面渲染: render(),render_to_response(),  
            # 使用render_to_response()方法需要引入render_to_response模块
                return render(req,"index.html")
                return render_to_response("index.html")         -- 有坑不建议使用
    
        本地变量:locals():  可以直接将函数中所有的变量传给模板,locals是本地变量的意思,将本地变量传入html中
            例:
                views.py 中写
                    name="dashan"
                    return render_to_response("index.html",{"a":name})  
                html就得写
                    {{ a }}
    
                当views.py 这样写
                    name="dashan"
                    return render_to_response("index.html",locals())
    
                html就可以这样写,直接调用变量,而不需要使用参数调用
                    {{ name }}
    
                注意,使用render也可以
    
        页面跳转(重定向): redirect()
            return redirect("http://www.baidu.com")
            return redirect("http://www.baidu.com")
    
            render 是直接渲染某个页面并返回,redirect是重定向到指定的views函数,同时也会做一定的判断,
            比如用户登录。
  4. template基础

    在向前端输出字符串时使用模板语言进行处理,而不是使用 "欢迎 %s 登录" %(name) ,这种方式是为了实现前后端分离

    什么是模板语言?
    格式:HTML + 逻辑控制语句,如果HTML中存在模板语言,则HTML就叫模板,而不是HTML

    模板语言的作用?
    起到前端到后端的纽带作用

    render(request,"index.html",{"name":name})
        "index.html"        就叫模板
        {"name":name}       就叫上下文,Context
    
    在pycharm的terminal界面输入python manage.py shell即可进入当前django的命令行
    输入:
    >>> t=Template("hello {{ name }}")          创建模板语言
    >>> c=Context({"name":"dashan"})            创建上下文
    >>> t.render(c)                             渲染模板语言和上下文
    'hello dashan'

    4.1 一次模板创建,多次调用render()实现更高效的渲染

    t = Template("hello, {{ name }}")
    for name in ('dashan','lisi','wangwu'):
        print t.render(Context({'name'}:name))
    
    在view中使用Template和Context需要引入,from django.template import Template,Context

    4.2 深度变量的查找(万能的句点号".")

    import datetime
    
    def index(req):
        s=[1,2,3,4]
        s2={"uname":"dashan","sex":23}
        s3=datetime.datetime.now()
    
        class Person:
            def __init__(self,name,age):
                self.name = name
                self.age = age
    
        s4=Person("dashan",18)
    
        return render(req,"index.html",{"list":s})
        return render(req,"index.html",{"obj":s2})
        return render(req,"index.html",{"time":s3})
        return render(req,"index.html",{"P":s4})
    
    <html>
        <p> Template </p>
        {{ list.2}}   <!-- 输出的结果是3 ,列表通过索引取值-->
        {{ obj.sex}}   <!-- 输出的结果是23,字典通过key取values -->
        {{ time.year }}   <!-- 属性也是通过"."召唤出来的 -->
        {{ time.month }}   <!-- 属性也是通过"."召唤出来的 -->
        {{ P.age }}   <!-- 属性也是通过"."召唤出来的,结果是18 -->
        {{ P }}   <!-- 如果不加属性,那么输出的是一个对象属性 -->
    </html>

    4.3 if和for循环

    4.3.1 if,只支持布尔值True或者False,1(True)和(False)也可以
    
        { % if True % }
            <p>hello world</p>
            { % elif obj % }
                <p>hello2</p>
        { % endif % }
    
    4.3.2 for
        # 用列表举例
        { % for i in list % }
            <p>{{ i }}</p>          <!--  i 是vaules,和js不一样(js取的是索引) -->
            <p>{{ forloop.counter }}:{{ i }}</p>        <!--  输出"索引值:values",索引从1开始 -->
            <p>{{ forloop.counter0 }}:{{ i }}</p>       <!--  输出"索引值:values",索引从0开始 -->
            <p>{{ forloop.revcounter }}:{{ i }}</p>     <!--  输出"索引值:values",索引反着打印 -->
        { % endfor % }
    
        # 用字典举例
        { % for i in obj % }    
            <p>{{ forloop.counter }}:{{ i }}</p>        <!--  输出"索引值:key",索引从1开始,和列表一样 -->
            <p>{{ forloop.counter }}:{{ i.uname }}</p>      <!--  输出"索引值:values",这样就可以打印值了 -->
        { % endfor % }
    
        # 字典的使用方法
        {% for row in user_dict.keys %}
        {% for row in user_dict.values %}
    
        {% for row in user_dict.items %} 得到元组
    
        {% for k,row in user_dict.items %}

       <li>{{k}}-{{row}}</li>
    {% endfor %}

    4.4 过滤器filter
    {{ ship_date|date:"Fj,Y"}}
    ship_date变量传给date过滤器,date过滤器通过使用"Fj,Y"这几个参数来格式化日期数据,
    "|"和unix的管道符类似

    s = "hello"
    s2 = 1
    s3 = datetime.datetime.now()
    s4 = []
    s5 = "<a href="http://www.baidu.com">百度</a>"
    return render(req,"index.html",{"obj":s})
    return render(req,"index.html",{"num":s2})
    return render(req,"index.html",{"time":s3})
    return render(req,"index.html",{"kong":s4})
    return render(req,"index.html",{"a":s5})
    
    <html>
        {{ 对象|方法:参数}}       - 格式
    
        {{ obj }}               - 打印结果"hello".
        {{ obj|upper }}         - 使用模板语言中的upper方法,将"hello"转为大写"HELLO".
        {{ obj|lower }}         - 小写
        {{ obj|firest }}        - 取出第一个字母
        {{ obj|capfirest }}     - 将第一个字母大写
    
        {{ num|add:5 }}         - num+5 ,结果为6
    
        {{ 对象|cut: ' '}}        - 去除空格
        {{ time|date: 'Y-m-d'}}     - 输出年月日,"-"也可以写为":"
    
        {{ kong|default: '空的'}} - 当对象为空时,输出default指定的字符串,如果不为空则输出对象
    
        {{ % a % }}             - 会将超链接返回为一个字符串,因为浏览器会认为是不安全的
    
        { % autoescape off % }  - 这样浏览器就能解析为html语言了,浏览器就认为是安全的
            {{ % a % }} 
        { % endautoescape % }
    
        {{ a|safe }}            - 这个和上面那个是一样的功能,会告诉浏览器这是安全的
    
        {{ obj|filesizeformat }} -  打印对象的大小
        {{ obj|length }}         -  打印对象的长度
        {{ obj|slice: ':-1' }}   -  切片,从头切到最后一个,最后一个不要
        {{ a|urlencode }}
    
        values="hello I am shan"
        {{ values|truncatechars:'6' }}      按字符截取
        {{ values|truncatewords:'2' }}      按单词截取
    
    </html>
    
    注意:为什么要在前端转而不是后端,试想一下如果输入的是一个字典类型的数据,需要
        for循环完后的数据输出为大写,如果你在后端做这个操作的话就会变得很繁琐,需要
        循环完后赋予一个变量才能转给前端

    4.5 中间件 csrf 跨站请求伪造

    用于生成csrf_token的标签,用于防治跨站***验证。
    
    用于验证form表单
    <form action="/login"  method="post" >
    
        <p>姓名:<input type="text" name="username"></p>
        <p>性别:<input type="text" name="sex"></p>
        <p>邮箱:<input type="text" name="email"></p>
        <p><input type="submit" value="submit"></p>
        {% csrf_token %}        <!-- 指定认证,否则报错Forbidden
                                 django会渲染出一个令牌(input标签),
                                 拥有类型hidden,名字和值,用于告诉Django,
                                 我是一个认证过的表单
                                  -->
    </form>
    
    注意:
        同时如果你在views.py中返回页面时使用 render_to_response,需要这样写
    
        from django.template import RequestContext,Template
    
        return render_to_response("index.html",context_instent=RequestContext(request))
    
        否则也会报错Forbidden,所以之前才不建议使用render_to_response

    4.6 { % load % } - 加载标签库

    4.7 { % url % } - 引用路由配置的地址

    4.8 { % with % } - 用更简单的变量名替代复杂的变量名

    { % with total=fadsfsadfdsaffdsaf % } {{ total }} { % endwith % }
    
    格式:{ % with 新变量名=旧变量名 % } {{ 新变量名 }} { % endwith % }

    4.9 { % varbatim % } - 禁止render

    { % varbatim % }            - name就不会渲染了,输出的就是字符串"{{ name }}    "
        {{ name }}      
    { % endvarbatim % }

    4.10 自定义 simple_tag

    需求:比如后端传给了前端一个变量num=1,我想让这个变量在前端+10,
        原本我可以在前端写为 {{ num|add:'10'}},但是我想使用自定义的方法
        {{ num|add100 }},这就叫做自定义simple_tag(简单标签)
    
    a. 在app目录下中创建templatetags模块
    b. 创建任意.py文件,如文件名"my_tag.py"
        #!/usr/bin/evn python
        #coding:utf-8
        from django import template
        from django.utils.safestring import mark_safe
    
        register = template.Library()   # register是固定变量名,不能改变
    
        @register.simple_tag            # 装饰器
        def my_add100(v1):
            return v1 + 10              # 实现num+10
    
        @register.simple_tag
        def my_input(id,arg):
            result = "<input type="text" id="%s" class="%s">" %(id.arg)
            return mark_safe(result)
    
    c. 在使用自定义simple_tag的html文件中引入之前创建的mytag.py文件名
    
        { % load my_tag % }
    
        <html>
        </html>
    
    d. 使用simple_tag
        <html>
            { % my_add100 1 % }    <!-- 输出11 -->
        </html>
    
        <html>
            { % my_input id1 cl1 % }    <!-- 输出一个input标签,id是id1,class是cl1 -->
        </html>

    4.11 自定义filter
    流程和自定义 simple_tag一样,就差在
    @register.simple_tag了,自定义filter是这样写@register.filter

        调用方式为
        {{ num|my_add100 }}         <!-- 输出11 相当于执行"my_add100(num)" -->
    
        如果自定义filter传入的是两个参数,最多也只能两个(自定义 simple_tag没有这个限制),
        解决方法是传入一个列表
    
        @register.filter                # 装饰器
        def my_add100(v1,v2):
            return v1 + 10 + v2     
    
        {{ num|my_add100:2 }}       <!-- 输出13 -->   
    
        注意:模板的if语句可以加一个自定义filter,但是不能加自定义simple_tag
                同时,使用自定义简单标签和自定义filter,必须在全局文件settings.py中的
                INSTALLED_APPS [
                        'myapp',
                ]
                区域添加你的app名
向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI