Django基本知识、路由层、视图层、模版层

基本知识

Django命令行操作

  • 创建Django项目:django-admin startproject  项目名
  • 运行Django项目:python manage.py runserver    注意:需要切换到Django项目下
  • 创建应用: python manage.py startapp 应用名称   

Django主要文件介绍(以我创建的my_djagon项目为例子

- my_djagon文件夹

  - setting.py               --配置文件
  - urls.py                    --路由和视图函数对应关系(路由层)
  - wsgi.py                   --wsgiref模块

- 应用文件夹

  - admin.py                 --django后台管理
  - apps.py                   --注册使用
  - migration文件夹      --数据库迁移记录
  - models.py               --数据库相关的模型类(orm)
  - tests.py                   --测试文件
  - views.py                  --视图函数(视图层)

- manage.py                     --django的入口文件
- db.sqlite3                       --django自带的sqlite3数据库(小型数据库,功能不是很多,存有bug)

Django注意事项:

1、命令行创建的app,需要去配置文件注册

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'app01',  #注册应用简写
    # 'app01.apps.App01Config',  #注册应用全写

]
settings配置文件

2、命令行创建的django项目没有templates文件夹,需要自己创建,创建后需要去配置文件配置一句话

'DIRS': [os.path.join(BASE_DIR, 'templates')],
TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [os.path.join(BASE_DIR, 'templates')],   #命令行创建的时候需要手动创建
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]
templates在settings的配置

 Django必备的三件套:

1、render(request,模版文件,字典)     将字典的数据填充进模板文件,并把结果返回给浏览器

2、HttpResponse(‘字符串’)   将字符串参数返回给浏览器

3、redirect(urlt)     重定向 ,跳转到request这个连接

from django.shortcuts import render,HttpResponse,redirect

# Create your views here.

def index(request):
    return HttpResponse('index') #返回字符串

def home(request):
    return render(request,'01.html',{"name":'alex'})

def chongdingxiang(request):
    return redirect('https://www.baidu.com')
三件套例子

 Django静态文件static的配置

#静态解析 
<link rel="stylesheet" href="/static/bootstrap-3.3.7-dist/css/bootstrap.min.css">
 <script src="/static/bootstrap-3.3.7-dist/js/bootstrap.min.js"></script>
#setting文件的配置

STATIC_URL = '/static/'   
#类似于访问静态文件的令牌,你要访问静态文件,就必须以static开头
#从下面这个列表里从上往下依次查找所要的资源
#如果查找没有该资源,才会报错。
#令牌“static"更改,html文件里面相应的内容也要更改
STATICFILES_DIRS=[
    os.path.join(BASE_DIR,'static'),
]

#如果采用动态解析静态文件,则令牌的更改,静态文件的访问链接会自动更改
    {%  load static %}
    <link rel="stylesheet" href="{%  static 'bootstrap-3.3.7-dist/css/bootstrap.min.css' %}">
    <script src="{% static 'bootstrap-3.3.7-dist/js/bootstrap.min.js' %}"></script>

#例子,当 STATIC_URL = '/static/'变为STATIC_URL = '/static11/' 时
#静态文件资源访问链接也会随着自动改变,不用再自己去html修改静态资源的令牌。
 URL:http://127.0.0.1:8000/static11/bootstrap-3.3.7-dist/css/bootstrap.min.css

 Django请求生命周期流程

路由层

 路由匹配

url(r'^admin/', admin.site.urls),
url(r'^$'.views.home) #主页

'''
url第一个参数是正则匹配,^表示以xx开头,$表示结束
url链接中最后的/没写,django会自动帮加上重新再匹配一次
路由匹配是从上往下,匹配到就不会再继续往下面匹配了
取消自动加斜杆,在settings文件最后面加APPEND_SLASH=False 默认是True
'''

 路由匹配中无名分组和有名分组

 无名分组:就是将括号内的正则表达式匹配到的值当作位置参数传递给后面的视图函数

有名分组:就是将括号内的正则表达式匹配到的值 当作关键字参数传递给后面的视图函数

 #无名参数
 url(r'^group/(\d+)',views.group),
#无名分组的视图函数
def group(request,xx):
    print(xx)  #xx就是位置参数
    return HttpResponse('helloword')

 #有名参数
 url(r'^name/(?P<k>\d+)',views.name)
#有名分组的视图函数
def name(request,k):
    print(k)
    return HttpResponse('有名参数')

注意:无名分组跟有名分组无法混合使用,但是两者都可以无限制使用,无名分组多次使用,传递参数是以列表形式,有名分组,则是字典的形式。

#无名参数
url(r'^group/(\d+)/(\d+)/(\d+)',views.group),
#有名参数
 url(r'^name/(?P<k>\d+)/(?P<k1>\d+)/(?P<k2>\d+)',views.name)

#无名分组的视图函数
def group(request,*args):
    print(args)  #xx就是位置参数
    return HttpResponse('helloword')
#返回结果:('123413', '12', '243')

#有名分组的视图函数
def name(request,**kwargs):
    print(kwargs)
    return HttpResponse('有名参数')
#返回结果:{'k': '1222', 'k1': '11', 'k2': '22'}
无名分组、有名分组使用多次例子

反向解析

 实质:通过一些方法得到一个结果,该结果可以访问到对应url,从而触发视图函数,也就是让路由跟视图函数实现动态解析,这样改了url,也可以映射到原来的视图函数

实现步骤:1、给路和视图函数起一个别名: 如:

url(r'^edit/$',views.edit,name='ho')

2、可以在前端进行反向解析,也可以在后端进行反向解析

#前端
<a href="{% url 'ho' %}">111</a>
#后端
from django.shortcuts import reverse
reverse('ho')#动态获取url名

有名、无名分组的反向解析:

#无名分组反向解析,编辑数据
url(r'^edit/(\d+)',views.edit,name='ee'),
#前端解析
<a href="{% url 'ee' li.id %}" class="btn btn-primary btn-xs">编辑</a>
#后端
def edit(request,id):
    id=id
    edit_boj=models.User.objects.filter(id=id).first()
    if request.method=="POST":
        username = request.POST.get('username')
        password=request.POST.get('password')  models.User.objects.filter(id=id).update(username=username,password=password)
        return redirect('/showlist/')
    return render(request,'edit.html',locals())

#后端解析:
reverse('ee',args=(1,))

 有名分组反向解析:

url(r'^index/(?P<k>\d+)',views.index,name='iii')
#前端
<a href='{% url 'iii' k=123 %}>111</a>
#也可以直接这样写
<a href='{% url 'iii' 123 %}>111</a>
#后端
reverse('iii',kwargs={'k':123})
#简写
reverse('iii',args(1,))

 路由分发

1、 总路由不再做路由跟视图函数的映射,而改为做子路由分发。让各个应用的路由去做映射

from django.conf.urls import url,include
urlpatterns = [
    #只有url前缀是app01的,就交给app01的路由去寻找映射关系
    url(r'^app01/',include('app01.urls')),
    url(r'^app02/',include('app02.urls')),
]
#注意:url第一个参数尾部不能加$

2、在应用文件夹下新建一个urls.py文件,用来处理路由跟视图函数的映射。

from django.conf.urls import url
from app01 import views
urlpatterns = [
    url(r'^index/', views.index),
]

空间别名

当不同应用app下出现别名相同的时候,就可以用空间别名来区分,正常情况下,一般app设置别名的时候,都会添加app名字前缀,如:app01_xxx。

#总路由
urlpatterns = [
    url(r'^app01/',include('app01.urls',namespace='app01')),
    url(r'^app02/',include('app02.urls',namespace='app02')),
]
#子路由1
urlpatterns = [
    url(r'^index/', views.index,name='xxx'),
]
#子路由2
urlpatterns = [
    url(r'^index/', views.index,name='xxx'),
]
#app01下的视图函数
def index(request):
    reverse('app01:xxx')
    return HttpResponse(reverse('app01:xxx'))
#app02下的视图函数
def index(request):
    reverse('app01:xxx')
    return HttpResponse(reverse('app02:xxx'))

伪静态:就是将动态网页伪装成静态的网页,有助于 增加网站seo查询力度,增加搜索引擎收藏的概率

#伪静态一般是直接在url后面添加.html后缀
urlpatterns = [
    url(r'^index.html', views.index,name='xxx'),
]

 

Media配置:在settings文件下添加这句代码

#配置用户上传文件的存储位置
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')

资源暴露:比如用户头像显示

from django.conf import settings
from django.views.static import serve
#media配置
url(r'^media/(?P<path>.*)',serve,{'document_root':settings.MEDIA_ROOT})

视图层

JsonResponse

向前端返回一个json类型的数据:

#用法:
from django.http import JsonResponse
def index(request):
    reverse('app01:xxx')
    dic_data={'k':'hello','k2':'world','k3':'bye','k4':'你好,世界'}
    return JsonResponse(dic_data,json_dumps_params={'ensure_ascii':False})

'''
ensure_ascii:False,关闭ascii码,这样前端可以显示中文
safe=False,表示可以序列化任何对象,设置为True,则只能序列化字典
'''
def index(request):
    data_list=[11,22,33,44]
    return JsonResponse(data_list,safe=False)

 Django中request对象方法:

  • request.method   获取请求方法
  • request.POST   获取post请求中的数据
  • request.POST.get(key)   获取最后一个元素
  • request.POST.getlist(key)  获取整个列表
  • request.GET  获取get请求中的数据
  • request.META 获取请求头信息
登陆页面获取账号密码的例子
  • request.FILES  获取文件对象
#urls.py的路由跟视图函数映射
urlpatterns = [
    url(r'^file/',views.fileDoload)
]
#vies.py下的文件下载方法:
def fileDoload(request):
    if request.method=='POST':
        #获取文件对象
        file_obj=request.FILES.get('filename')
        #注意,括号内filename这个参数是跟input文件类型标签下的name属性相对应
        with open(file_obj.name,'wb') as f:
            for line in file_obj:
                f.write(line)
        return HttpResponse(request.FILES)

#html页面
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/js/bootstrap.min.js"></script>
</head>
<body>
    <form method="post" enctype="multipart/form-data">
        <p>user:<input type="text" name="i"></p>
        <p>file<input type="file" name="filename"></p>
        <input type="submit">
    </form>
</body>
</html>
文件下载
  • request.path  获取路径信息
  • request.path_info  获取路径信息
  • request.get_full_path()  获取路径和路径?后面的参数   如:http://127.0.0.1:8000/app01/file/?user=123  结果:/app01/file/?user=123

 模板层(Django模版语言DTL)

模版语法:{{变量名}}

注意:列表字典等取值都是有 . 方法,比如去列表list 的第一个值,就是 list.0,dic.key

Fiters(过滤器)

语法: {{ value|filter_name:参数 }}

<p>统计长度:{{ s|length }}</p>
<p>默认值(第一个参数布尔值True就先试下第一个参数,false就显示冒号后的值):{{ b|default:'我是false' }}</p>
<p>文件大小:{{ file_size|filesizeformat }}</p>
<p>日期格式:{{ currt_time|date }}</p>
<p>切片操作(支持隔几个取一个) {{ l|slice:'0:4:2' }}</p>
<p>切取字符(注意:包含三个点){{ info|truncatechars:10 }}</p>
<p>切取单词(不包含三个点,按空格切){{ world|truncatewords:9 }}</p>
<p>切取单词{{ info|truncatewords:9 }}</p>
<p>移除特定的字符:{{ world|cut:' ' }}</p>
<p>拼接操作:{{ b|join:'$' }}</p>
<p>拼接操作(加法):{{ a|add:10 }}</p>
<p>拼接操作(加法):{{ world|add:info }}</p>
#前端取消转义
<p>取消转义:{{ h|safe}}</p>
#后端取消转义,在views.py文件写
#from django.utils.safestring import mark_safe
#res=mark_safe('<h1>hello</h1>')
<p>{{ res }}</p>

标签

主要有:fro循环标签、if判读、with起别名、url标签

{% for l in user_list %}
    {% if forloop.first %}
        <li>第一个</li>
    {% elif forloop.last%}
        <li>最后一个</li>
    {% else %}
        <li>{{ l }}</li>
    {% endif %}
{% empty %}
     <li>空空如也</li>
{% endfor %}
#with给复杂变量起别名
{% with d.k3.3.info as info %}
     <li>{{ info }}</li>
{% endwith %}
#注意Django不支持连续if判断
{% if a>b>c %}
{% endif %}

url标签

url(r'^edit/$',views.edit,name='ho')
#反向解析 name是路由起的别名
{ % url 'ho' %}

for循环的一些参数

VariableDescription
forloop.counter 当前循环的索引值(从1开始)
forloop.counter0 当前循环的索引值(从0开始)
forloop.revcounter 当前循环的倒序索引值(从1开始)
forloop.revcounter0 当前循环的倒序索引值(从0开始)
forloop.first 当前循环是不是第一次循环(布尔值)
forloop.last 当前循环是不是最后一次循环(布尔值)
forloop.parentloop 本层循环的外层循环

 

 

 

 

 

 

 

 

 

自定义过滤器 filters、标签Tag、 inclusion_tag

1、自定义过滤器的操作:

(1)在app目录下新建一个templatetags文件夹,然后在该文件夹下,新建一个.py文件,用来放自定义过滤器的代码

 

 (2)在新建的.py 文件中写代码

from django import template
#注意register这个单词不能写错
register=template.Library()

#自定义过滤器,参数不能超过两个
@register.filter(name='sum')
def my_sum(x1,x2):
    return x1+x2

(3)在前端的使用方法:先加载.py文件,其他的就跟内置的过滤器使用方法一样

<h1>自定义过滤器的使用</h1>
{% load mytag %}  {# 加载templatetag文件夹下创建的fiter代码文件 #}
<p>{{ a|sum:b }}</p>

(2)自定义标签的使用跟过滤器基本一致:

from django import template

register=template.Library()
#自定义标签可以接收多个参数
@register.simple_tag(name='formate')
def my_tag(a,b,c,d):
    return '%s-%s-%s-%s' %(a,b,c,d)

#在前端的使用
{% load mytag %}
<p>{% formate '' '' '' '' %}</p>

3、自定义inclusion_tag

inclusion_tag的原理:定义一个方法、然后在一个页面上调用该方法,同时也可以传值,调用该方法后,会生成一些数据然后传递给一个html页面,渲染后会将结果返回到该页面

from django import template
register=template.Library()

@register.inclusion_tag('ul.html')
def i_tag(n):
    data=['第{}项'.format(i) for i in range(n)]
    return locals() #将data传递给ul.html文件

#ul.html代码
<ul>
    {% for l in data %}
        <li>{{ l }}</li>
    {% endfor %}
</ul>

#页面使用inclusion_tag的方法
{% load mytag %}
{% i_tag 10 %}

总结:当html页面需要数据才能动态渲染出来的时候,多个页面需要该html页面的时候,就可以考虑将该html页面做成inclusion_tag形式

模版的继承

 两个页面出现大部分相同的情况,就可以通过继承模板,然后修改不相同部分的代码。这样就可以避免代码冗余

1、在模板html文件中需要修改的那部分代码用 {% block 块名字 %} {% endblock %}封起来,如下面代码一样

 {% block fun_title %}
<h3 class="panel-title">主页</h3>
{% endblock %}

2、在子页面html文件写这句代码{% extends '模板.html' %}来继承模板的html模板

3、在子页面中,根据不同块名,来书写不同块的代码,如:

{% extends 'home.html' %}
{% block fun_title %}
    <h3 class="panel-title">登陆</h3>
{% endblock %}

总结:一般模板html会定义三个块,分别是js块、css块、html块。还可以根据自己的需求设置相应的块

 

Django各个版本的区别:

1.xx版本路由跟视图函数的映射是用url,2.xx跟3.xx版本不再用url,而是用path、re_path

注意:re_path用法跟url一致,但是path第一个参数不支持正则,写什么就匹配什么,但是,其内部增加了五种转换器

from django.urls import path,re_path
from app01 import views
urlpatterns = [
    path('articles/<int:year>/', views.year_archive), 
'''
<int:year>相当于一个有名分组,其中int是django提供的转换器,相当于正则表达式,专门用于匹配数字类型,
而year则是我们为有名分组命的名,并且int会将匹配成功的结果转换成整型后按照格式(year=整型值)传给函数year_archive ''' ]
#注意:如果<>内没有设置转换器,则会匹配任意字符,包括/
  • str      匹配除了路径分隔符(/)之外的非空字符串,这是默认的形式
  • int      匹配正整数,包含0。
  • slug   匹配字母、数字以及横杠、下划线组成的字符串。
  • uuid   匹配格式化的uuid,如 075194d3-6885-417e-a8a8-6c931e272f00。
  • path   匹配任何非空字符串,包含了路径分隔符(/)(不能用?)
posted @ 2020-10-02 22:40  NQ31  阅读(201)  评论(0编辑  收藏  举报