十四、Django学习

目录

一、Web服务的本质

二、Django的下载

三、Django的基础创建

四、MTV模型

五、URL控制器

六、View视图函数

七、Template模板语法


 

一、Web服务的本质

#服务端
import socket
server = socket.socket()
server.bind(('127.0.0.1',8080))
server.listen(5)

while True:
    conn,addr = server.accept()
    recv_data = conn.recv(1024)
    print('recv_data:',recv_data)

    #发送符合浏览器Brower解析格式
    conn.send(b'HTTP/1.1 OK \r\n\r\n<h1>hello world!</h1>')

 

二、Django的下载

pip  install  django

 

三、Django的基础创建

#a.创建一个django project的项目
django-admin startproject  项目名   #在当前目录下创建一个django项目

#b.创建应用
python  manage.py  startapp  app名

#c.启动django应用命令
python  manage.py  runserver  ip:port

#d.测试,访问http://ip:port

  django常用命令

#将models类转化成数据库表项(orm)
python manage.py makemigrations 
python manage.py  migrate

python  manage.py syncdb  #同步更改数据库表或字段
python  manage.py  flush     #清空数据库

python  manage.py  createsuperuser   #创建超级管理员
python  manage.py  changepassword username  #修改密码

  

  django项目的文件介绍:

mysite
    ---mysite
        ---settings    #项目配置文件
        ---urls           #路径与视图函数的映射关系
        ---wsgi         #封装的socket
    ---manage.py    #与Django项目进行交互的脚本
    ---app名  
        ---models       #数据库操作
        ---view           #视图函数
    ---templates        #自建文件夹
        ---html 文件           #自建html页面

  静态文件配置 

  STATIC主要指的是如css,js,images等文件

STATIC_URL = '/static/'  #别名

STATICFILES_DIRS = (
    os.path.join(BASE_DIR,"statics"),#实际文件夹名字
)

注意点1:
    django对别名和实际名进行映射,引用时,只能按照别名来,不能按实际名去找,如:
    html代码:
    //错误演示,/statics/为实际名
        <script src="/statics/jquery.js"></script>

   //正确演示,/static/为别名
        <script src="/static/jquery.js"></script>

注意点2:
STATICFILES_DIRS = (
    ('app01',os.path.join(BASE_DIR,"app01/statics")),   #不能再这里写注释,否则无法读取static路径,切记,切记,切记
)

  数据库配置(MySql)

#1.在mysql数据库里先创建数据库
create database  library

#2.在setting.py文件里
DATABASES = {
    'default':{
        'ENGINE':'django.db.backends.mysql',
        'NAME':'library',
        'USER':'root',
        'PASSWORD':'123456',
        'HOST':'127.0.0.1',
        'PORT':3306
    }
}

INSTALLED_APPS = [
    'app01.apps.App01Config',    
    'app02'
]

#3.在app01文件里models.py,创建类表映射ORM
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    price = models.DecimalField(max_digits=8,decimal_places=2)
    pub_date = models.DateField()
    publish = models.CharField(max_length=32)
  create_date = models.DateTimeField(auto_now=True)  

  #自定义对象返回内容
  def __str__(self):
    return self.title
#4.创建ORM python manage.py makemigrations python manage.py migrate ps1:如果报no module named MySQLdb错误,在步骤2,因为django如果使用mysql,默认导入的驱动是MySQLdb,而MySQLdb在python3中有很大问题,我们需要使用PyMySQL,我们只需要找到项目名文件下的__init__.py,在里面写入: import pymysql pymysql.install_as_MySQLdb()
ps2:在models.py表里创建有一个创建时间字段create_date,设置了auto_now=True,表示创建就会更新当前时间,默认在setting.py里设置的是USE_TZ = False,表示使用UTC标准时间,
若服务在供一个时区,可以使用本地时间,将USE_TZ=False

 

 

四、MTV模型

  Model:模型,负责业务对象和数据库的关系映射(ORM)

  Template:模板,负责如何把页面展示给用户(html)

  View:视图,负责业务逻辑,并在适当的时候调用Model和Template

 

五、URL控制器

  5.0 作用

将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template

  5.1 url控制器的格式

#在django 1.x版本里
from django.conf.urls import url
from django.contrib import admin
from app01 import views
urlpatterns = [
    url(正则表达式,views视图函数,参数,别名),
]

参数说明:
  正则表达式,如r'^book/2018/$'
  views视图函数:一个可调用对象
  参数:可选,传递给


#在django 2.x版本里
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [
    path('admin/', admin.site.urls),
    re_path('^index/(<year>[0-9]{4})/$',views.index)
]

参数说明:
    path:第一个参数表示一个常规路径
    re_path:第一个参数是正则表达式

 

  5.2 url的简单实用

    url(r'^book/2018/$',views.book)         #默认传入参数request
    url(r'^book/\d{4}/$',views.book_year)  #\d(4)为任意4为数字,即年份
    url(r'^book/(\d{4})/$',views.book_year) #传递无名分组参数,book_year(request,year)

  5.3 url的有名分组

    url(r'^book/(?P<YEAR>\d{4})/$', views.book_year) #book_year(request,YEAR)

  5.4 url的分发

    url(r'^book/', include(app01.urls)) 

  5.5 url的别名

    url(r'^login.html$', views.login,name='login_xxx')

  ps:在template文件下html文件采用模板语言里的{% url  "login_xxx"  %},即url里匹配字段变的时候,别名不用变,即html文件不用更新

 

六、View视图函数

  6.1 储备知识

URL格式:
协议://域名(或IP):端口/路径/?GET参数
例如:
http://www.baidu.com/article/?a=hello

  主要掌握俩个参数,request,response

  6.2  request

request.GET      #获得get方式的类:django.http.request.QueryDict GET类的方法:
  类的方法:
        request.GET.get(key)   #获得get请求里的参数key的对应的值,没有返回None
        如:请求http://127.0.0.1:8001/login.html?a=1&value2=222
        request.GET.get("value2")    #结果=222  

        request.GET.dict()      #获的get请求里的参数,形成字典
        如:请求http://127.0.0.1:8001/login.html?a=1&value2=222
        request.GET.dict()          #结果{'a': '1', 'value2': '222'}

        request.GET.encoding     #获得get请求的编码方式,一般为utf-8
        request.GET.getlist(key)  #获得get请求里的参数key对应的值,放入列表
        request.GET.urlencode()   #获得get请求里的参数字符串,人类可读    
request.POST      #获得post方式的类:django.http.request.QueryDict GET类的方法:
  类的方法:
        request.POST.get(key)   #获得get请求里的参数key的对应的值,没有返回None
        如:请求http://127.0.0.1:8001/login.html
        request.POST.get("username")    #结果=lisl  

        request.POST.dict()      #获的post请求里的参数,形成字典
        如:请求http://127.0.0.1:8001/login.html
        request.POST.dict()          #结果{'username': 'lisl', 'password': '123456'}

        request.POST.encoding     #获得post请求的编码方式,一般为utf-8
        request.POST.getlist(key)  #获得post请求里的参数key对应的值,放入列表
      
request.method      #请看请求方式,如GET,POST...,是字符串
request.path          #url路径,不包含请求参数
如:请求http://127.0.0.1:8001/login.html?a=1&value2=222
request.path       #结果login.html

request.get_full_path()    #返回url路径+参数
如:请求http://127.0.0.1:8001/login.html?a=1&value2=222
request.get_full_path()    #结果login.html?a=1&value2=222

  6.3 response

HttpResponse("string")     #响应字符串,如return   HttpResponse("OK")
render(request,template_name)       #返回模板,如return  render(request,'login.html')          
redirect(to_url)      #重定向到指定url,如return   redirect('/app01/login.html')

 

七、Template模板语法

  7.1 变量     

        格式:{{ 变量}}

#1.深度查询
    {{  L.0 }}   #L为列表,0表示取列表第一个元素
    {{  dic.name }}    #dic为字典,name表示取key,结果输出value
    {{  person_class.name }}   #person_class为类,name为类属性

#2.过滤器
     格式:{{ val|filter_name:param }}

    加法过滤器:
        {{ num|add:20 }}      //num +=20

    时间过滤器:
        {{ value|date:"Y-m-d h:i" }}    #view视图里必须是使用datetime模块
    
    默认显示过滤器:
        {{ book_list|default:"没有符合条件的书籍" }}    #book_list为空列表,则输出default值

    文件大小友好转化
        {{ file_size|filesizeformat }}    #将文件大小自动转成人类可读,如‘10KB’,'25.5MB'等等

    关闭自动转义:禁止将标签转义成字符串
        views视图:
             value='<a href="">点击</a>'
        template:
             {{ value|safe }}

    返回长度,对字符串和列表斗气作用
       {{  value|length }}

  切片过滤器
    {{ value|slice:"2:-1" }} #加入value是字符串,从第3个字符到倒数第一个

  7.2 标签  

    格式:{%  tag  %}

  7.2.1 for标签

{% for i in l %}             <!--循环列表-->
    <div>{{ i }}</div>
{% endfor %}

ps:可利用{%  for i in l reversed %}  ,反向循环

{% for key,value in dic.items%}   <!--循环字典-->
    <div>{{ key }}:{{ value }}</div>
{% endfor %}

  注意:循环序号可以通过{{forloop}}显示,相当于python里的enumerate()函数

forloop.counter      <!--从索引1开始-->
forloop.counter0   <!--从索引0开始-->
forloop.revcounter  <!--索引从大到小,最小是1-->
forloop.revcounter0    <!--索引从大到小,最小是0-->
forloop.first            <!--判断是否是第一个元素,是返回True,不是返回False-->
forloop.last            <!--判断是否是最后一个元素,是返回True,不是返回False-->
forloop方法

  for....empty搭配

 for标签带有一个可选的{%  empty %}从句,以便在给出的组是空的或者没有找到时,可以有所操作

{% for i in l %}
    <div>{{ forloop.last }}&nbsp:&nbsp{{ i }}</div>
{% empty %}
    <div>此列表为空</div>
{% endfor %}

  7.2.2 if标签

{% if l %}                <!--l列表不为空-->
    <div>{{ l | length }}</div>
{% elif dic %}
  <div>{{ dic | length }}</div>
{% else %}
  <div>没有</div> {% endif %}

  7.2.3  自定义标签和过滤器

  1. settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义simple_tag
  2. 在app中创建templatetags包文件夹(模块名只能是templatetags)
  3. 在templatetags包文件夹下创建任意.py文件,如:my_tags.py,如下
    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()
    
    #定义俩数相乘
    @register.filter
    def filter_multi(v1,v2):
        return v1 * v2
    
    
    @register.simple_tag
    def simple_tag_multi(v1,v2):
        return v1 * v2
    
    @register.simple_tag
    def my_input(id,arg):
        result = "<input type='text' id='%s' class='%s' />"%(id,arg,)
        return mark_safe(result) 
  4. 在使用自定义simple_tag和filter的html文件中导入之前创建的my_tags.py
    {%  load my_tags  %}
  5. 使用simple_tag和filter
    {% load my_tags %}
    
    <div>{{ num|filter_multi:2 }}</div>  <!--假如num=20,结果:40-->
    <div>{{ num|filter_multi:"[22,11,2]" }}</div>  <!--假如num=20,结果:重复20个[22,11,2]列表-->
    
    <div>{% simple_tag_multi 2 5 %}</div>        <!--结果:10-->
    <div>{% my_input "user" "user_content" %}</div>
  •   注意:filter可以用在if等语句后,simple_tag不可以,如
    {% if  num|filter_multi:30 > 100 %}
        <div>{{  num|filter_multi:30 }}</div>
    {% endif %}
  • 7.3 简单示例
    #在view.py视图中
    def login(request):
        if request.method =='GET':
            l= ['a','c','b','d']
            # l= []
            num =20
            return render(request,'login.html',{'l':l,"num":num})
        else:
            print(request.POST.dict())
            return HttpResponse('OK')
    #在template文件里的html文件<!--xx-->
    <div>{{ num }}</div>    <!--结果:num=20-->
    <div>{{ l | slice:"2:-1" }}</div>      <!--将列表l从第3个元素到倒数第一个进行切片,序号从0开始,取值范围[2,-1)-->
    <div>{{ num|filter_multi:2 }}</div>  <!--使用自定义模板过滤器,求乘积,结果为40-->
    
    {% for i in l %}            <!--循环-->
        <div>{{ forloop.last }}&nbsp:&nbsp{{ i }}</div>
    {% empty %}
        <div>此列表为空</div>
    {% endfor %}
    
    
    {% if l %}           <!--判断-->
        <div>{{ l | length }}</div>
    {% endif %}

     

  • 7.4  模板的继承
    #介绍
    假如有三个网页(分别为a,b,c.html),他们的头部header和左边的导航栏都是固定不变的,只有中间的内容块是变化的,
    我们可以将不变的部分制作成模板,在此命名为base.html
    <!--base.html  母版--->
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>{% block title %}默认标题{% endblock %}</title>
        <style>
            *{
                margin: 0;
            }
            #header{
                width: 970px;
                height: 30px;
                background-color: aqua;
            }
            #main{
                width:970px;
                height: 1000px;
            }
            #left{
                float:left;
                width:300px;
                height: 1000px;
                background-color: aquamarine;
            }
            #content{
                float:left;
                width: 670px;
                height: 100%;
                background-color: red;
            }
        </style>
    </head>
    <body>
    <div id="header">头部</div>
    <div id="main">
        <div id="left">左半部</div>
        <div id="content">
            {% block content %}
                默认内容
            {% endblock %}
        </div>
    </div>
    
    </body>
    </html>
    <!--子板 A.html-->
    {% extends "base.html" %}
    {% block title %}A网页{% endblock title %}
    
    {% block content %}
        <h1>A网页的内容1</h1>
        <h1>A网页的内容2</h1>
        <h1>A网页的内容3</h1>
    {% endblock content %}

     

 八、ORM单表操作

  8.1 建立sql基本数据源
#参考"三、Django的基础创建"中数据库配置(MySql)部分

  8.2 创建表数据

#方式一
##create方法的返回值为book_obj对象
from app01.models import *
def query(request):
    import datetime
    now = datetime.datetime.now()  

    #pub_data的格式只能是'年-月-日 时:分:秒',可以不那么详细,但是一定要按标准格式
    #pub_data的值,可以由datetime模块里的datetime.datetime.now()来作为值
    #返回的值是创建书的对象book_obj
    book_obj = Book.objects.create(name='三国演义',pub_data='2010-08-11',price=99.99,publish='人民出版社',create_date=now)

    return HttpResponse('ok')


#方式二
from app01.models import *
def query(request):
    import datetime
    now = datetime.datetime.now()

    #创建数据命令以下俩条
    book_obj = Book(name='水浒传3',pub_data='2010-05-10',price=122,publish='机械工业出版社',create_date=now)
    book_obj.save()

    return HttpResponse('ok')

   8.3查询表数据

book_obj = Book.objects.方法

关于常用查询方法:
all()     #查询所有结果,返回的QuerySet对象
filter(**kwargs)   #查询符合条件的结果,返回QuerySet对象
get(**kwargs)    #返回符合条件的结果,返回结果有且只能有一个,没有或者大于1条符合的,都会抛出异常,返回Book对象
exclude(**kwargs)  #查询指定条件外的所有结果,返回QuerySet对象
order_by(*field)   #对QuerySet对象进行排序,*field为指定数据表中的列名,如'name',或者'price'等等,默认是升序,返回的结果是QuerySet对象
reverse()        #对QuerySet对象进行反序,返回结果是QuerySet对象,可与order_by(*field)配合使用
count()    #返回数据库匹配到符合对象的数量,返回结果int类型
first()    #返回queryset对象里第一条符合的book_obj对象
last()   #返回queryset对象里最后一条符合的book_obj对象 
exists()    #如果queryset对象里有符合的数据,就返回True,否则返回False
values(*field)  #对Queryset对象进行符合列名显示,返回结果是QuerySet对象,但是不同的是列表元素是字典,取值的时候不是加点.,而是dic['name'],见'测试数据'示例
values_llist(*field)   #与values(*field)相似,差别是上面返回的是字典,而这里返回的是元组
distinct()    #去重,要针对某个字段去重,可配合values(*field)使用,见“测试数据”示例,返回结果queryset对象
#在views.py里
from django.shortcuts import render,HttpResponse,redirect


from app01.models import *
def query(request):
    #查询整张表信息
    # queryset_obj = Book.objects.all()
    # print(queryset_obj)
    # print(type(queryset_obj),dir(queryset_obj))
    # for book_obj in book_obj:
    #     print (book_obj.name,book_obj.create_date)

    #查询书名为三国演义所有信息
    # queryset_obj = Book.objects.filter(name='三国演义')
    # print(queryset_obj)
    # print(type(queryset_obj),dir(queryset_obj))
    # for book_obj in queryset_obj:
    #     print (book_obj.name,book_obj.create_date)

    #查询书名为水浒传
    # book_obj = Book.objects.get(name='水浒传')
    # print(book_obj)
    # print(type(book_obj),dir(book_obj))
    # print(book_obj.name,book_obj.create_date)

    #查询除三国演义外的所有信息
    # queryset_obj = Book.objects.exclude(name='三国演义')
    # print(queryset_obj)
    # print(type(queryset_obj),dir(queryset_obj))
    # for book_obj in queryset_obj:
    #     print (book_obj.name,book_obj.create_date)

    #查询除三国演义外的所有信息,并对结果进行升序
    # queryset_obj = Book.objects.exclude(name='三国演义').order_by('price')
    # print(queryset_obj)
    # print(type(queryset_obj),dir(queryset_obj))
    # for book_obj in queryset_obj:
    #     print (book_obj.name,book_obj.create_date)



    # queryset_obj = Book.objects.order_by('name').reverse()
    # print(queryset_obj)
    # print(type(queryset_obj),dir(queryset_obj))
    # for book_obj in queryset_obj:
    #     print (book_obj.name,book_obj.create_date)

    # book_int = Book.objects.all().count()
    # print(book_int)
    # print(type(book_int), dir(book_int))

    # book_obj = Book.objects.all().exists()
    # print(book_obj)
    # print(type(book_obj), dir(book_obj))

    # queryset_obj = Book.objects.all().values('name','publish','pub_data')
    # print(queryset_obj)
    # print(type(queryset_obj), dir(queryset_obj))
    # for i in queryset_obj:
    #     print(i['name'],i['publish'],i['pub_data'])

    # queryset_obj = Book.objects.all().values_list('name','publish','pub_data')
    # print(queryset_obj)
    # print(type(queryset_obj), dir(queryset_obj))
    # for i in queryset_obj:
    #     print(i[0],i[1],i[2])

    queryset_obj = Book.objects.all().values('name').distinct()
    print(queryset_obj)
    print(type(queryset_obj), dir(queryset_obj))
    for i in queryset_obj:
        print(i)
    return HttpResponse('ok')
测试数据

   基于双下划线的模糊查询

 

 

 

 

 
 
posted @ 2018-08-21 16:39  森林326  阅读(245)  评论(0编辑  收藏  举报