Django从入门到放弃一 -- 基础部分

参考地址:http://www.cnblogs.com/yuanchenqi/articles/7629939.html

一、什么是Django

  Django是一个Web应用程序的框架。

  预备知识:1、python基础    2、数据库    3、前端( jquey + bootstrap )

 

1.1、Django请求生命周期

Django从入门到放弃一 -- 基础部分_第1张图片

 

二、Web请求的本质

    CS架构:client   ---   server        #客户端 -- 服务端
    BS架构:browser  ---  server     #浏览器 -- 服务端

 

三、MTV模型

   代表模型(Model): 负责业务对象和数据库的关系映射(ORM)。与数据库交互

   代表模板(Template): 负责如何把页面(根据请求,决定给用户什么样的页面)展示给用户(HTML)。

   代表视图(View): 负责业务逻辑,并在适当的时候调用Model和Template(把数据封装成模板的样子返还给用户)

图解MTV模型:

  URL控制器:什么路径 ( login | admin | index 等) 交给什么函数去处理。

Django从入门到放弃一 -- 基础部分_第2张图片

 

四、Django学习过程

4.1、下载与命令  -- 在命令行操作的方式  ( django是依赖于Python库的,用什么pip版本下载的,django就存在于对应版本的Python库的Scripts目内[django-admin.exe] )

  下载:        pip3 install django==1.11.1    #最新版本django-2.1.4

  卸载:        pip3 uninstall django-1.11.1  

  创建项目:django-admin startproject mysite    #其中mysite为项目名称(项目名可以修改)

  创建一个应用:python3 manage.py startapp app01  #app01为应用名称

  项目启动命令:python3 manage.py runserver  IP+PORT   #默认是127.0.0.1:8000

                  mysite 项目包含的:

                       1 --- mysite     #和项目名称同名的目录(不能更改名称)

                             --- settings    项目配置文件

                             --- urls           路径与视图函数的映射关系

                             --- wsgi         封装的socket

                      2 --- manage.py     Django项目进行交互的脚本

                      3 --- app01 项目应用   #python3 manage.py startapp app01(创建一个应用)

                             --- models     数据库操作

                             --- views        视图函数

                      4 --- app02 项目应用   #python3 manage.py startapp app02(创建一个应用)

                             --- models     数据库操作

                             --- views        视图函数

                     5 --- templates   #存放模板的文件夹(名称必须为templates)

                             --- index.html

                             --- login.html

 

4.3、查看django版本号  pip show django

Django从入门到放弃一 -- 基础部分_第3张图片

 

4.4、在pycharm中创建Django项目的方式

方式一:使用现有的Python(版本)环境

Django从入门到放弃一 -- 基础部分_第4张图片

方式二:创建一个新的Python虚拟环境

make available to all projects:表示创建的项目工程可以被其他项目使用

inherit global site-packages:继承本地的Python版本库

Django从入门到放弃一 -- 基础部分_第5张图片


  五.URL控制器  urls.py -- Django实践  

  URL:  协议://IP(域名):端口(80)/路径?GET参数

  URL的功能:反映URL的路径和视图函数的映射关系

  5.1、URL的简单使用 -- 在urls.py文件配置

from app01 import views  # 指定路径

urlpatterns = [
    url(r'^timer/', views.timer),   #views.timer(request) django会帮我们把http请求头的信息拿到,默认传进去。
]

  然后在应用目录APP01的views.py文件里,定义timer

from django.shortcuts import render,HttpResponse
# HttpResponse为封装响应体的类

def timer(request):  # request请求信息对象
    import time
    ctime=str(time.time())
    return HttpResponse(ctime)   # 执行timer函数,[HttpResponse这个类在实例化的时候需要传入的值为字符串类型,所以ctime要设置为字符串类型]

访问:http://127.0.0.1:8000/timer/ 拿到当前机器的时间!

 

5.2、URL的无名分组 --  一般用来传URL路径里面的某一个参数,或者说是获取URL路径里面的某一个参数。

# 在urils.py里对应的配置。
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^articles/(\d{4})/$', views.article_year),    
]                                                       
# \d{4}:表示4位数字
# (\d{4}) :表示接收浏览器URL路径里面的某一个值,接收到的值会传给views.article_year(request,(\d{4})),那么在后端的代码里面article_year函数里面也要传2个参数。


# 在views.py里对应的配置。
def article_year(request,year):
    #数据库查询
    return HttpResponse(year)

 

5.2、URL的有名分组  --  根据定义的关键字传参 -- 相当于关键字传参 -- (?P\d{4}) 只能接收数字

# 在urils.py里对应的配置。
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^articles/(?P\d{4})/(?P\d{2})/$', views.article_year_month), 
    # year接收传入的第一个值并赋值给year(year=1999),month接收传入的第二个值并赋值给month(month=12)
]                                                       

# 在views.py里对应的配置。
def article_year_month(request,year,month):
    #数据库查询
    return HttpResponse(year+"/"+month)

 

5.3、URL的分发 --  每个应用下单独定义urls,只需要在项目目下做总的分发,实现解耦效果。

# 在项目目录下的urls.py文件内定义

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^app01/',include('app01.urls'))        # 定义访问app01应用的走app01目录下urls.py文件
]

# 那么在app01目录下urls.py文件定义如下:实现解耦的效果

from django.conf.urls import include, url
from django.contrib import admin
from app01 import views

urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    # 无名分组
    url(r'^articles/(\d{4})/(\d{2})/$', views.article_year_month),
    # 有名分组
    url(r'^articles/(?P\d{4})/(?P\d{2})/$', views.article_year_month),
]

# 在views.py文件中的代码如下:
from django.shortcuts import render,HttpResponse

def article_year_month(request,year,month):
    return HttpResponse(year+":"+month)

# 访问的URL就必须加上app01前缀,否则无法访问
# http://127.0.0.1:8000/app01/articles/2005/19/

 

5.4、URL的反射  --  给固定的URL路径起一个别名,那么在使用路径时用这个别名即可。无论这个URL的路径在urls.py中如何修改,只要在前端html中定义"action={% url 'login' %}",那么"{% url 'login' %}"就总能获取到urls.py中定义的URL路径(前端HTML不需要修改对应的路径)。--可参照 (7.2、渲染URL标签 {% %} )

在Html中写法:
在在Python中写法:url(r'^login/',views.login,name="login"), # name="login" 定义一个别名叫"login" # 例子: # 在Python中:views.py文件中定义 urlpatterns = [ url(r'^login/',views.login,name="login"), 在 Html中:timer.html中定义
# 在html中,首先会查找有没有模板语法,如果没有的话,那么就直接丢给浏览器去读取html的内容了。 # 如果有模板语法,那么根据模板语法的内容,去全局的urls.py文件中找一个叫"login"的别名字符串。 # 找到"login"这个别名字符串后,会把这个别名对应的URL动态的获取,然后放在html中的action里面,然后交给浏览器去读取html中的action的内容。 ]

 

例子:实现用户的登录及认证功能

# 前端HTML:


{# login默认访问当前请求URL下的IP+端口/login/ #} {# action: 用户提交后,请求到后端的地址 #} {# method="post": 提交请求为"POST"请求 #} 用户名: {# 这个user是用来:获取用户输入的"用户名" #} 密码: {# 这个pwd是用来:获取用户输入的"密码" #} {# submit是一次提交 #}
# 后端代码: # 一、urls.py文件内 from app01 import views urlpatterns = [ url(r'^admin/', include(admin.site.urls)), url(r'^timer/', views.timer), # 二合一版本 url(r'^login/', views.login), ] # 二、views.py文件内 from django.shortcuts import render,HttpResponse def login(request): method=request.method # request.method 拿到的是用户请求一个页面的方式"GET"或者"POST" if method == "GET": # 判断用户的请求方式 return render(request,"login.html") # 如果为"GET",则返回"login.html" else: user=request.POST.get("user") # 通过“request.POST.get”,拿到前端用户输入的"用户名" pwd=request.POST.get("pwd") # 通过“request.POST.get”,拿到前端用户输入的"密码" # 校验数据 if user == "szq" and pwd == '123': return HttpResponse('登录成功') # 响应 return HttpResponse("登录失败")

 

  六.视图语法  views.py

  6.1、request  -- 请求信息

# 在views.py文件里面编辑:
# 然后访问:http://127.0.0.1:8000/index/ 拿到如下信息!

def index(request):
    # 请求信息
    print(request.GET)     # 发送GET请求
    # 

    print(request.POST)    # 发送POST请求
    # < QueryDict: {} >

    print(request.method)  # 获取本次请求的方式 "GET或POST"
    # GET

    print(request.path)    # 获取本次请求的相对路径
    # /index/

    print(request.get_full_path())    # 获取本次请求的全部路径(ip+port之后的路径地址)
    # /index/?a=1

 

  6.2、HttpResponse  --  响应信息

    1、Django必须响应HttpResponse对象

    2、HttpResponse 响应字符串

# 使用例子,在views.py文件中:
def index(request):
    return HttpResponse("首页!")

    3、render       响应模板(对应的html文件)

    4、redirect     重定向 -- 用户登录成功后,重定向到网站首页!  (服务器让浏览器重定向请求,浏览器相当于请求了2次服务器)

Django从入门到放弃一 -- 基础部分_第6张图片

# 使用例子,在views.py文件中:
def login(request):
    if request.method=="GET":
       return render(request,'login.html')
    else:
       if 1:
       return redirect("/index/")  # 在这里做了重定向跳转,跳转的路径为"/index/",触发这次重定向之后,就会跳转到http://127.0.0.1:8000/index/这个页面。

 

  七.模板语法  templates -- 模板语法都是由render解析的  

   7.1、render方法的功能:
      方式一:return render(request,"login.html")
           按着settings指定路径找到对应的login.html,读取文件内容,构建return HttpResponse(文件字符串)

      方式二:return render(request,"timer.html",{"ctime":ctime, "name":name, "age":age,})
           按着settings指定路径找到对应的timer.html,读取文件内容,进行渲染,把文件字符串中所有的{{}}的内容按着{"ctime":ctime, "name":name, "age":age,}的方式进行替换,将新的替换字符串构建return HttpResponse(文件字符串)
 

   7.2、模板语法分为:

      1.变量 :1)深度查询,2)过滤器 

      2.标签

  1、模板语法之变量的用法 {{ }} 小例子:

# 渲染变量的
在Html中写法:
在在Python中写法:return render(request,"timer.html",{"ctime":ctime,"name":name,"age":age,}) # 例子: # 在Python中:views.py文件中定义 def timer(request): import time ctime=str(time.time()) name="sudada" age=18 return render(request,"timer.html",{ # render能够找到"timer.html"文件,是因为在setting,py (里面的TEMPLATES定义了'DIRS': [os.path.join(BASE_DIR, 'templates'))。django会从全局变量里面找到templates目录] "ctime":ctime, #"ctime"是给templates里面的timer.html用的,而ctime取得是当前文件下的ctime "name":name, # 同"ctime"一样 "age":age, # 同"ctime"一样 }) 在 Html中:timer.html中定义

当前时间: {{ ctime }}

# 调用后端里面的"ctime"

My name is: {{ name }}

# 同上

My age is: {{ age }}

# 同上

  2、模板语法之标签{% %}的用法 小例子:渲染URL标签 -- 在Html模板里面对URL进行渲染  {% %}

# 渲染URL标签的
在Html中写法:
在在Python中写法:url(r'^login/',views.login,name="login"),  # name="login" 定义一个别名叫"login"

# 例子:
# 在Python中:views.py文件中定义
urlpatterns = [
    url(r'^admin/', include(admin.site.urls)),
    url(r'^login/',views.login,name="login"),  

在 Html中:timer.html中定义
  
  # 在html中,首先会查找有没有模板语法,如果没有的话,那么就直接丢给浏览器去读取html的内容了。
  # 如果有模板语法,那么根据模板语法的内容,去全局的urls.py文件中找一个叫"login"的别名字符串。
  # 找到后会把这个别名动态的获取,然后放在html中,然后交给浏览器去读取html的内容。
]

 

 7.3、模板语法(变量)的使用:深度查询

  在python中的用法:

  如下:定义了"name" "l" "dic"等变量,以及类"Animal"等。

def template(request):
    '''
    模板语法:
        变量
            --- 深度查询
            --- 过滤器
    '''
    name="sudada"
    l=[11,22,33]
    dic={"name":"sudada","age":18,"sex":"male"}

    class Animal(object):
        def __init__(self,name,age):
            self.name=name
            self.age=age

    zzz=Animal("zzz",10)
    lll=Animal("lll",20)
    sss=Animal("sss",30)

    person_list=[zzz,lll,sss]

    return render(request,"templates.html",{"name":name,"l":l,"dic":dic,"person_list":person_list})
    # return render(request,"templates.html",locals())

  那么在前端是如何调用的呢?   前端HTML代码使用是效果展示:{{  }} 的方式调用Python里面定义的变量

{{ name }}

# sudada 拿到变量name的赋值 <<---------分隔----------->>

{{ l }}

#[11, 22, 33] 拿到l列表里面定义的所有值

{{ l.0 }}

#11 取l列表里面定义的第一个值

{{ l.1 }}

#22 取l列表里面定义的第二个值

{{ l.2 }}

#33 取l列表里面定义的第三个值 <<---------分隔----------->>

{{ dic.name }}

#sudada 取字典里面的第一个值

{{ dic.age }}

#18 取字典里面的第二个值

{{ dic.sex }}

#male 取字典里面的第三个值 <<---------分隔----------->>

{{ person_list.0 }}

#.Animal object at 0x000001AFD0655198> 拿到的是实例化的对象,可以看出定义的类为"Animal"

{{ person_list.0.name }}

#zzz 拿到的是列表person_list里面实例化后的对象name对应的值,0表示列表里面的第一个对象,name表示对象name对应的值。

{{ person_list.0.age }}

#10 同上

{{ person_list.1.name }}

#lll同上

{{ person_list.1.age }}

#20同上

{{ zzz.name }}

# zzz 直接获取对象zzz的name对应的值

{{ zzz.age }}

# 10 直接获取对象zzz的age对应的值


  7.4、模板语法(变量)的使用:过滤器语法 {{val(变量)|filter_name(过滤器名字):参数}}  -- 更友好的显示一些数据

  在python中的用法:

def template(request):    
    """
    过滤器的使用之语法:{{val(变量)|filter_name(过滤器名字):参数}}
    """
    number=100
    import datetime
    now=datetime.datetime.now()

    # book_list=["三国演义","金瓶梅"]
    book_list=[]
    file_size=12312311
    s="Hello World"
    article="asd,哈哈哈,asd,爱 asd asd 12 lasdj lqniuqg id bsmnc buqho namv uqbwi namsb iuqoiejlqkwbdbnmasb j"

    link="rick"
    # return render(request,"templates.html",{"name":name,"l":l,"dic":dic,"person_list":person_list}) # 写法一
    return render(request,"templates.html",locals())     # 写法二
    # locals() == {"name":name,"l":l,"dic":dic,"person_list":person_list}

  那么在前端是如何调用的呢?

  前端HTML代码使用是效果展示:

过滤器

{{number|add:20}}

# number变量名,"|"固定写法,add表示加法,":"固定写法,20表示数字。表示在number=100的基础上在加20

{{ now|date:"Y-m-d h:i" }}

# 原本"Dec. 30, 2018, 11:54 p.m."的格式加上过滤器date:"Y-m-d h:i"后,变成了"2018-12-30 11:54"

{{ book_list|default:"没有符合条件的数据" }}

# 当book_list=[]为空的时候,默认显示"没有符合条件的数据",当book_list=["三国演义","金瓶梅"]里面存在值的时候,就显示列表里面的值。

{{ file_size|filesizeformat }}

# 把file_size=123123123换算成字节大小,显示的效果为"117.4 MB"(格式单位自动调节),可以一眼看出文件有多大。

{{ s|slice:"0:3" }}

# 对s="Hello World" 切片(顾头不顾尾),取"0:3"的值

{{ s|slice:"0::2" }}

# 对s="Hello World" 切片(顾头不顾尾),每隔2个单位取一个值 {#展示一篇文章前面的一部分内容#}

{{ article|truncatechars:10 }}

# 展示一片文章的前7个字符(后面会默认加...三个字符)

{{ article|truncatewords:3 }}

# 展示一片文章的前3个单词(默认以空格为单词之间的分隔符分隔符)

{{ link|safe }}

# Django的安全机制会将link="rick"标签字符串进行转译,那么需要加上一个safe的过滤器,让他保持原意

 

7.4、自定义标签和过滤器

  1、在settings中的INSTALLED_APPS配置当前app01(项目名),不然django无法找到自定义的simple_tag.

  2、在app01中创建templatetags模块 (模块名只能是templatetags)

  3、创建任意 .py 文件,如:my_tags.py,并自定义过滤器函数和标签函数

from django import template
from django.utils.safestring import mark_safe
 
register = template.Library()   #register的名字是固定的,不可改变
 
 
@register.filter
def filter_multi(v1,v2):     # 自定义过滤器函数
    return  v1 * v2

@register.simple_tag 
def my_input(id,arg):          # 自定义标签函数
    result = "" %(id,arg,)
    return mark_safe(result)

4、在使用自定义simple_tag和filter的index.html文件中导入之前创建的 my_tags.py

# 在index.html文件中:


{% load my_tag %}

5、使用simple_tag和filter(如何调用)

# 在index.html文件中:


{% load my_tag %}         # 导入自定义的过滤器
{{ 3|filter_multi:4 }}    # 3:表示第一个参数,4:表示第二个参数,这种方式只能传2个值。my_tags.py中的filter_multi函数会接受这2个值,并做下一步处理
{% my_input 'id_test' 'class_test' %}   # 给自定义标签my_input传值。

 

 7.5、模板语法(标签)的使用:for标签 {%%} -循环渲染

在Python里面的用法:

def template(request): 
    ###########标签############
    book_list = ["三国演义","金瓶梅","西游记"]
    dic={"name":"sudada",
         "age":18,
         "sex":"male",
         }
    return render(request,"templates.html",locals())

    #或者使用这种方式
    return render(request,"books.html",{"book_list":book_list})  

    # {"book_list":book_list} == locals()

  前端HTML代码使用是效果展示:

{% for n in book_list %}   # for 循环开始,针对列表循环
    

{{ n }}

{% endfor %} # for 循环结束,固定语法 三国演义 金瓶梅 西游记 {% for book in book_list %}
  • {{ book }}
  • {% endfor %} *三国演义 *金瓶梅 *西游记 {% for i in book_list %}

    {{ forloop.counter }} {{ i }}

    {% endfor %} 1 三国演义 2 金瓶梅 3 西游记 {% for key in dic %} # 针对字典循环

    {{ key }}

    # 拿到的值为字典的key {% endfor %} name age sex {% for key,value in dic.items %} # 针对字典里面的key和value的循环

    {{ key }} {{ value }}

    {% endfor %} name sudada age 18 sex male

     

     7.6、模板语法(标签)的使用:if标签-if条件判断

     在Python里面的用法:

    def template(request): 
        ###########if 条件判断标签############
        score=90
        num_list=[123,34,546,8,98,2,344123,30,435457,65,456,4]
    
        return render(request,"templates.html",locals())

      前端HTML代码使用是效果展示:

    if 标签

    {% if score > 90 %}

    very good

    {% elif score > 60 %}

    good

    {% else %}

    NO

    {% endif %} # 输出的值如下: good

    条件判断大于50的数字

    # for循环里面嵌套if条件判断 {% for num in num_list %} {% if num > 50 %}

    {{ num }}

    {% endif %} {% endfor %} # 输出的值如下: 123 546 98 344123 435457 65 456

     

    7.7、Django引入静态文件

      1、首先在项目根路径下创建 "static" 目录,然后把静态文件都放在这个目录下。

      2、在settings.py文件的最后一行,新增"static"目录

    # 别名:之后在使用时,可以用别名代替实际路径
    STATIC_URL = '/static/'   # 这个配置是Django自带就有的
    
    # 文件的实际存在目录,给Django使用的
    STATICFILES_DIRS=[
        os.path.join(BASE_DIR,"static")
    ]

      3、在前端html文件中引用静态文件

    
        
        Title
          # 引用免费CDN上面的js文件
          # 引用static目录下的静态文件
    

     

    7.8、Django模板的继承 

       Django模版引擎中最强大也是最复杂的部分就是模版继承了。模版继承可以让您创建一个基本的“骨架”模版,它包含您站点中的全部元素,并且可以定义能够被子模版覆盖的 blocks 。

      1、继承的目的就是减少前端代码冗余

      2、Django模板继承大体就是:先写一个父类HTML,然后子类HTML继承父类HTML的代码的方式。 具体如下:

        2.1 父类HTML ,先写一堆父类HTML代码,然后定义一个 "block" (具体写法为:{% block Title %} )。"block"就是一个子类HTML可重写代码的部分。

    {# 父类HTML文件base.html #}
    
    
    
        
      
        {# 继承的写法#}
        {% block Title %}
            Title
        {% endblock %}
    
        
        {# 使用这套布局方式 #}
        
        
    
    
    
    
    

    Panel title

    Panel content
    {% block centent %} {# block的功能:当其他的html文件继承base.html(当前文件)时,可以重写centent的内容。 #} {# centent这个名字不是固定写法 #}

    这是一个盒子

    {% endblock %}

        2.2 子类HTML ,继承父类HTML的方法 (只能继承一个父类HTML模板)

           1). 在子类HTML中,使用{% extends "base.html" %} 明确继承哪个父类HTML

           2). 在子类HTML中,使用{% block centent %} 自定义代码

    {# 子类HTML文件order.html #}
    {% extends "base.html" %}    {# 继承base.html文件,必须放在第一位 #}
    
    {% block centent %}     {# 然后重写block里面的内容 #}
        

    订单列表

    {% for order in order_list %}

    {{ order }}

    {% endfor %} {% endblock %}

     

      3、在子类HTML中使用{% block centent %}重写HTML后,还想要显示父类HTML中的{% block centent %},这种需要该如何实现。

    {% extends "base.html" %}
    
    {% block centent %}
        

    商品列表

    {% for shopper in shopper_list %}

    {{ shopper }}

    {% endfor %}
    {{ block.super }}
    {# 写一个div标签,然后加上"{{ block.super }}"就可以了 #} {% endblock %}

     

      4、使用继承的一些注意事项

    1).如果你在模版中使用 {% extends %} 标签,它必须是模版中的第一个标签。其他的任何情况下,模版继承都将无法工作。
    
    2).在base模版中设置越多的 {% block %} 标签越好。请记住,子模版不必定义全部父模版中的blocks,所以,你可以在大多数blocks中填充合理的默认内容,然后,只定义你需要的那一个。多一点钩子总比少一点好。
    
    3).如果你发现你自己在大量的模版中复制内容,那可能意味着你应该把内容移动到父模版中的一个 {% block %} 中。
    
    4).为了更好的可读性,你也可以给你的 {% endblock %} 标签一个 名字 。例如:
              {% block content %}
              ...
             {% endblock content %}  
    
    5).在大型模版中,这个方法帮你清楚的看到哪一个  {% block %} 标签被关闭了。
    
    6).最后,请注意您并不能在一个模版中定义多个相同名字的 block 标签。这个限制的存在是因为block标签的作用是“双向”的。这个意思是,block标签不仅提供了一个坑去填,它还在 _父模版_中定义了填坑的内容。如果在一个模版中有两个名字一样的 block 标签,模版的父模版将不知道使用哪个block的内容。

     

    你可能感兴趣的:(python)