zoukankan      html  css  js  c++  java
  • django~1

    http://www.cnblogs.com/yuanchenqi/articles/6083427.html

    本节内容:

    1:MVC和MTV是什么

    2:django命令

    3:Django的配置文件(settings)

    4:Django URL (路由系统)

    5:Django Views(视图函数) ~V 

    6:Django Template基础  ~T

    7:Django Model基础 ~M

    8:Django Admin

    1:MVC和MTV是什么

    著名的MVC模式:所谓MVC就是把web应用分为模型(M),控制器(C),视图(V)三层;他们之间以一种插件似的,松耦合的方式连接在一起。

    模型负责业务对象与数据库的对象(ORM);
    视图负责与用户的交互(页面);
    控制器(C)接受用户的输入调用模型和视图完成用户的请求。

    Django的MTV模式本质上与MVC模式没有什么差别,也是各组件之间为了保持松耦合关系,只是定义上有些许不同,Django的MTV分别代表:

    Model(模型):负责业务对象与数据库的对象(ORM)
    Template(模版):负责如何把页面展示用户
    View(视图):负责业务逻辑,并在适当的时候调用Model和Template
    
    此外,Django还有一个url分发器,它的作用是将一个个URL的页面请求分发给不同的view处理,view再调用相应的Model和Template
    

    注意的是:

    在MVC中的V视图是代表着--->html文件。而在MTV中的V是一个个的函数视图。

    def index(request):
    
        return render(request,"base.html")

     2:django常用命令

    安装: pip3 install django
    
    django-admin startproject sitename  ##创建project  
    
    python manage.py runserver 0.0.0.0 ##启动服务
    python manage.py startapp appname  ##创建app 
    python manage.py syncdb
    python manage.py makemigrations  ##数据库
    python manage.py migrate
    
    python manage.py createsuperuser

     import django
     django.VERSION ##查看django的版本是多少
     pip3 install django --upgrade # #升级django
     pip3 uninstall django ##卸载django

    3:Django的静态文件(settings)

    a:setting配置文件要有django.contrib.staticfiles'

    INSTALLED_APPS = [
        'django.contrib.admin',
        'django.contrib.auth',
        'django.contrib.contenttypes',
        'django.contrib.sessions',
        'django.contrib.messages',
        'django.contrib.staticfiles',
        "app01",
    ]
    View Code

    b:setting文件的STATIC_URL

    STATIC_URL = '/static/'    ##使用的时候只能是采用别名的方式去引用静态文件: 
    STATICFILES_DIRS = (
        os.path.join(BASE_DIR,"statics"),
        # os.path.join(BASE_DIR,"blog","statics"),  ##一个app对应一个静态文件
    )
    View Code

    c:在template目录的html文件中 使用

    ##第一种
    <script src="/static/jquery-3.3.1.min.js"></script>
    
    #第二种
    {% load staticfiles %}  ##首行
    <script src="{% static "jquery-3.3.1.min.js" %}"></script>
    View Code

     4:Django URL (路由系统)

        URL配置(URLconf)就像Django 所支撑网站的目录。它的本质是URL模式以及要为该URL模式调用的视图函数之间的映射表;你就是以这种方式告诉Django,对于这个URL调用这段代码,对于那个URL调用那段代码。

    urlpatterns = [
    
        url(正则表达式, views视图函数,参数,别名),
    ]

    参数说明:

    • 一个正则表达式字符串
    • 一个可调用对象,通常为一个视图函数或一个指定视图函数路径的字符串
    • 可选的要传递给视图函数的默认参数(字典形式)
    • 一个可选的name参数

    传递的参数始终是字符串


    from
    django.conf.urls import url from app01 import views urlpatterns = [ # 一般 url(r'^articles/2003/$', views.special_case_2003), url(r'^articles/([0-9]{4})/$', views.year_archive), url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive), # 路由分发 url(r'^contact/', include('django_website.contact.urls')), # 传给视图的默认参数,对应的视图函数也必须加上同名的参数 url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}), #name参数 别名 url(r'^index',views.index,name='bieming'), ##<a href="{% url "bieming" %}">click me</a> ]

    5:Django Views(视图函数)

    当一个请求来了,会对应的去匹配app 里面view视图函数。而一个view视图即一个请求的过程。

    http请求中产生两个核心对象:

            http请求:HttpRequest对象

            http响应:HttpResponse对象

    1 HttpRequest对象的属性和方法:

     path:       请求页面的全路径,不包括域名
    #
    # method:     请求中使用的HTTP方法的字符串表示。全大写表示。例如
    #
    #                    if  req.method=="GET":
    #
    #                              do_something()
    #
    #                    elseif req.method=="POST":
    #
    #                              do_something_else()
    #
    # GET:         包含所有HTTP GET参数的类字典对象
    #
    # POST:       包含所有HTTP POST参数的类字典对象
    #
    #              服务器收到空的POST请求的情况也是可能发生的,也就是说,表单form通过
    #              HTTP POST方法提交请求,但是表单中可能没有数据,因此不能使用
    #              if req.POST来判断是否使用了HTTP POST 方法;应该使用  if req.method=="POST"
    #
    #
    #
    # COOKIES:     包含所有cookies的标准Python字典对象;keys和values都是字符串。
    #
    # FILES:      包含所有上传文件的类字典对象;FILES中的每一个Key都是<input type="file" name="" />标签中                     name属性的值,FILES中的每一个value同时也是一个标准的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支持时该属性才可用。
    
    #方法
    get_full_path(),   比如:http://127.0.0.1:8000/index33/?name=123 ,req.get_full_path()得到的结果就是/index33/?name=123
    req.path:/index33
    View Code

    2 HttpResponse对象:

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

      HttpResponse类在django.http.HttpResponse

      在HttpResponse对象上扩展的常用方法:

    页面渲染:render,render_to_response(不需要加request)
    其本质就是调用的:HttpResponse
    
    页面跳转:redirect
    
    locals: 可以直接将函数中所有的变量传给模板
    from django.shortcuts import render,render_to_response,redirect
    from django.shortcuts import HttpResponse
    
    def index(request):
    
        # return render(request,"base.html")
        # return render_to_response("base.html")
        return  redirect("/register/")
        # return HttpResponse("SUCCESS")
    View Code

     6:Django Template基础

    Django的template目录中的html文件是包括了html标签和template语言的。
    在发送response响应给客户端,要先将template模版语言html标签进行渲染之后才发送给客户端。

    模板语法

    1:变量(使用双大括号来引用变量):

    语法格式:       {{var_name}}
    

    a:Template和Context对象(了解)

    >>> python manange.py shell  (进入该django项目的环境)
    >>> from django.template import Context, Template
    >>> t = Template('My name is {{ name }}.')
    >>> c = Context({'name': 'Stephane'})
    >>> t.render(c)
    'My name is Stephane.'
    
    
    # 同一模板,多个上下文,一旦有了模板对象,你就可以通过它渲染多个context,无论何时我们都可以
    # 像这样使用同一模板源渲染多个context,只进行 一次模板创建然后多次调用render()方法渲染会
    # 更为高效:
    # Low
    for name in ('John', 'Julie', 'Pat'):
        t = Template('Hello, {{ name }}')
        print t.render(Context({'name': name}))
    
    # Good
    t = Template('Hello, {{ name }}')
    for name in ('John', 'Julie', 'Pat'):
        print t.render(Context({'name': name}))
    View Code

    我们对Template和Context对象的了解之后,基本是不用这个的:而是直接用render

    def current_time(req):
    
        now=datetime.datetime.now()
    
        return render(req, 'current_datetime.html', {'current_date':now})
    View Code

    b:万能的点(.)

    view可以template中传递的数据类型:
    列表、字典、元组、字符串、数字....

    而要使用如字典还有列表等数据格式。采用点(.)

    ######view###########
    class foo:
        def __init__(self,a):
            self.a = a
    
    def register(request,FOO):
        person = {"name":'cfp',"age":22,"hobby":"gril"}
        l = [1,2,3]
        str1  = "hello"
        num = 10
        c = foo('xx')
        return render(request,"register.html",locals())
    
        
    #########register.html##########
    <body>
    
    {{ person.age }} #22
    {{ c.a }}     ##xx 
    {{ str1 }}     ##hello
    
    </body>
        
    View Code

    c:变量的过滤器(filter)的使用

    语法格式:      {{obj|filter:param}}
    
    # 1  add          :   给变量加上相应的值
       #
       # 2  addslashes   :    给变量中的引号前加上斜线
       #
       # 3  capfirst     :    首字母大写
       #
       # 4  cut          :   从字符串中移除指定的字符
       #
       # 5  date         :   格式化日期字符串
       #
       # 6  default      :   如果值是False,就替换成设置的默认值,否则就是用本来的值
       #
       # 7  default_if_none:  如果值是None,就替换成设置的默认值,否则就使用本来的值
    
    
    #实例:
    
    #value1="aBcDe"
    {{ value1|upper }}<br>
    
    #value2=5
    {{ value2|add:3 }}<br>
    
    #value3='he  llo wo r ld'
    {{ value3|cut:' ' }}<br>
    
    #import datetime
    #value4=datetime.datetime.now()
    {{ value4|date:'Y-m-d' }}<br>
    
    #value5=[]
    {{ value5|default:'空的' }}<br>
    
    #value6='<a href="#">跳转</a>'
    
    {{ value6 }}
    
    {% autoescape off %}
      {{ value6 }}
    {% endautoescape %}
    
    {{ value6|safe }}<br>
    
    {{ value6|striptags }}
    
    #value7='1234'
    {{ value7|filesizeformat }}<br>
    {{ value7|first }}<br>
    {{ value7|length }}<br>
    {{ value7|slice:":-1" }}<br>
    
    #value8='http://www.baidu.com/?a=1&b=3'
    {{ value8|urlencode }}<br>
        value9='hello I am yuan'
    View Code

    2:标签(tag)的使用(使用大括号和百分比的组合来表示使用tag)

    {% tags %}
    

    a:{% if %} 的使用 

    {% if num >= 100 and 8 %}
    
        {% if num > 200 %}
            <p>num大于200</p>
        {% else %}
            <p>num大于100小于200</p>
        {% endif %}
    
    {% elif num < 100%}
        <p>num小于100</p>
    
    {% else %}
        <p>num等于100</p>
    
    {% endif %}
    
    
    
    {% if %} 标签接受and,or或者not来测试多个变量值或者否定一个给定的变量
    {% if %} 标签不允许同一标签里同时出现and和or,否则逻辑容易产生歧义,例如下面的标签是不合法的:
    
    {% if obj1 and obj2 or obj3 %}
    View Code

    b:{% for %}的使用

    <ul>
    {% for obj in list %}
        <li>{{ obj.name }}</li>
    {% endfor %}
    </ul>
    
    
    
    #在标签里添加reversed来反序循环列表:
    
        {% for obj in list reversed %}
        ...
        {% endfor %}
    
        
    #{% for %}标签可以嵌套:
    
        {% for country in countries %}
            <h1>{{ country.name }}</h1>
            <ul>
             {% for city in country.city_list %}
                <li>{{ city }}</li>
             {% endfor %}
            </ul>
        {% endfor %}
    
    
    #系统不支持中断循环,系统也不支持continue语句,{% for %}标签内置了一个forloop模板变量,
    #这个变量含有一些属性可以提供给你一些关于循环的信息
    
    1:forloop.counter表示循环的次数,它从1开始计数,第一次循环设为1:
    
        {% for item in todo_list %}
            <p>{{ forloop.counter }}: {{ item }}</p>
        {% endfor %}
    2,forloop.counter0 类似于forloop.counter,但它是从0开始计数,第一次循环设为0
    3,forloop.revcounter
    4,forloop.revcounter0
    5,forloop.first当第一次循环时值为True,在特别情况下很有用:
    
        
        {% for object in objects %}   
             {% if forloop.first %}<li class="first">{% else %}<li>{% endif %}   
             {{ object }}   
            </li>  
        {% endfor %}  
        
    # 富有魔力的forloop变量只能在循环中得到,当模板解析器到达{% endfor %}时forloop就消失了
    # 如果你的模板context已经包含一个叫forloop的变量,Django会用{% for %}标签替代它
    # Django会在for标签的块中覆盖你定义的forloop变量的值
    # 在其他非循环的地方,你的forloop变量仍然可用
    
    
    #{% empty %}
    
    {{li }}
          {%  for i in li %}
              <li>{{ forloop.counter0 }}----{{ i }}</li>
          {% empty %}
              <li>this is empty!</li>
          {% endfor %}
    
    #         [11, 22, 33, 44, 55]
    #            0----11
    #            1----22
    #            2----33
    #            3----44
    #            4----55
    View Code

    c:{%csrf_token%}:csrf_token标签

         用于生成csrf_token的标签,用于防治跨站攻击验证。注意如果你在view的index里用的是render_to_response方法,不会生效

         其实,这里是会生成一个input标签,和其他表单标签一起提交给后台的。

    <form action="/register/" method="post">
        <input type="text" name="user">
        <input type="password" name="pwd">
        <input type="submit">
        {% csrf_token %}
    </form>
    View Code

    d:{% url %}:  引用路由配置的地址

    <form action="{% url "bieming"%}" >
              <input type="text">
              <input type="submit"value="提交">
              {%csrf_token%}
    </form>
    View Code

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

    {% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
    

    f:{% verbatim %}: 禁止render

    {% verbatim %}
             {{ hello }}
    {% endverbatim %}
    
    ###不将 hello进行渲染,本文内容就是 {{hello}}

    g:{% load %}: 加载标签库  

    3:自定义变量过滤(filter)和标签(simple_tag)

    a、在app中创建templatetags模块(必须的)

    b、创建任意 .py 文件,如:my_tags.py

    from django import template
    from django.utils.safestring import mark_safe
    
    register = template.Library()   #register的名字是固定的,不可改变
    
    @register.filter
    def  filter_multi(x,y,):
        return x*y
    
    
    @register.simple_tag
    def simple_multi(x,y,z):
        return x**y*z
    View Code

    c、在使用自定义simple_tag和filter的html文件中导入之前创建的 my_tags.py :{% load my_tags %}

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

    -------------------------------.html
    {% load xxx %}   #首行
        
        
        
        
     # num=12
    {{ num|filter_multi:2 }} #24   ##只能有一个参数
    
    {{ num|filter_multi:"[22,333,4444]" }}
    
    
    {% simple_tag_multi 2 5 %}   #参数不限,但不能放在if for语句中
    {% simple_tag_multi num 5 %}
    View Code

    e、在settings中的INSTALLED_APPS配置当前app,不然django无法找到自定义的simple_tag.

    4: extend模板继承

    母html:{% block content %} {% endblock %}  ##block越多越好,block也可以叫做钩子
    
    子html:
        {% extends "base.html" %}  ##必须在html页面的首行
        
        {% block content %}  ##要修改的内容都在block包含,其他都是一样的
        {{ block.super }}  ##执行母版中的block中的内容
            内容。。。
        {% endblock %}
        
        我觉的一个html文件内容写的很好。想直接内嵌到自己的html文件中:
        1:{% load staticfiles %}
        2:{% include "test.html" %}
    {% load staticfiles %}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    
    </head>
    <style>
        *{
            margin: 0;
            padding: 0;
        }
        .nav {
            line-height: 40px;
             100%;
            height: 40px;
            background-color: #2459a2;
            color: white;
            font-size: 20px;
            text-align: center;
    
        }
        .left {
              20%;
             background-color: lightblue;
             min-height: 694px;
            overflow: hidden;
            float: left;
        }
        .manage {
            text-align: center;
            padding: 15px 0;
            margin: 20px 0;
            font-size: 20px;
            color: white;
        }
        a {
            text-decoration: none;
        }
        .content {
             80%;
            min-height: 694px;
            display: inline-block;
            float: left;
        }
        h1 {
            text-align: center;
        }
    </style>
       {% block css %}
    
       {% endblock %}
    <body>
    
    <div class="outer">
        <div class="nav">标题</div>
        <div class="left">
            <div class="student manage"><a href="/student/">学生管理</a></div>
            <div class="teacher manage"><a href="">老师管理</a></div>
            <div class="class manage"><a href="">班级管理</a></div>
            <div class="course manage"><a href="">课程管理</a></div>
        </div>
        <div class="content">
            {% block content %}
                <h1>WELCOME TO MANAGE </h1>{% block manage %} {% endblock %}
            {% endblock %}
    
        </div>
    </div>
    
    
    
    <script src="/static/jquery-3.3.1.min.js"></script>
    
    <script src="{% static "jquery-3.3.1.min.js" %}"></script>
    <script>
        $("h3").css("color","red")
    </script>
    
    </body>
    </html>
    base.html
    {% extends "base.html" %}
    {% load staticfiles %}
    
    
    {% block css %}
        <style>
            H1,h2 {
                text-align: center;
            }
        </style>
    {% endblock %}
    
    {% block content %}
        {{ block.super }}{% block manage %}FOR STUDENT MANAGE{% endblock %}
        {% for item in student_list %}
           <h2>学生:{{ item }}</h2>
        {% endfor %}
        {% include "test.html" %}
    {% endblock %}
    student.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    
    <h1>hello world</h1>
    
    </body>
    </html>
    test.html

     7:Django Model基础 ~M

    一、表与表之间的关系

    一对一  一个外键加字段的unique 
    一对多  一个外键
    多对多  两个外键 

    二、django的ORM 

    ORM(Object relation mapping)对象关系映射,把用python的一个类去对应数据库里面的一个表,用于实现面向对象编程语言里不同类型系统的数据之间的转换,换言之,就是用面向对象的方式操作数据库创建表以及增删改查等操作

    优点:

    1 :ORM使得我们的通用数据库交互变得简单易行,而且完全不用考虑该死的SQL语句。快速开发,由此而来。

    2 :可以避免一些新手程序猿写sql语句带来的性能问题。

    注意:没有ORM我们一样是可以对数据库进行操作的:无非就是在view里面导入模块,创建游标

    import pymysql
    def index(request):
        conn = pymysql.connect(host="127.0.0.1",port=3306,user="root",password='',database='')
        cursor = conn.cursor()
        cursor.execute("select * from t1;")  
        data = cursor.fetchall()
        print(data)
        conn.commit()
        cursor.close()
        conn.close()
        return render(request,"base.html")
    View Code

     三、Model数据库的配置

    1    django默认支持sqlite,mysql, oracle,postgresql数据库。

         <1> sqlite

                django默认使用sqlite的数据库,默认自带sqlite的数据库驱动 , 引擎名称:django.db.backends.sqlite3

         <2> mysql

                引擎名称:django.db.backends.mysql

    2    mysql驱动程序

    •    MySQLdb(mysql python)
    •    mysqlclient
    •    MySQL
    •    PyMySQL(纯python的mysql驱动程序)

    3     在django的项目中会默认使用sqlite数据库,在settings里有如下设置:

               

    如果我们想要更改数据库,需要修改如下:

               

    DATABASES = {
    
        'default': {
    
            'ENGINE': 'django.db.backends.mysql', 
    
            'NAME': 'books',    #你的数据库名称
    
            'USER': 'root',   #你的数据库用户名
    
            'PASSWORD': '', #你的数据库密码
    
            'HOST': '', #你的数据库主机,留空默认为localhost
    
            'PORT': '3306', #你的数据库端口
    
        }
    
    }
    View Code

    注意:

    NAME即数据库的名字,在mysql连接前该数据库必须已经创建,而上面的sqlite数据库下的db.sqlite3则是项目自动创建
    
    USER和PASSWORD分别是数据库的用户名和密码。
    
    设置完后,再启动我们的Django项目前,我们需要激活我们的mysql。
    
    然后,启动项目,会报错:no module named MySQLdb
    
    这是因为django默认你导入的驱动是MySQLdb,可是MySQLdb对于py3有很大问题,所以我们需要的驱动是PyMySQL
    
    所以,我们只需要找到项目名文件下的__init__,在里面写入:
    
    import pymysql
    pymysql.install_as_MySQLdb()
    
    问题解决!
    View Code

    四、在model文件创建一个表

    1: ###app01下的model创建一个类

    from django.db import models
    
    # Create your models here.
    
    class Book(models.Model):
        name = models.CharField(max_length=30)
        price = models.IntegerField()
        pub_date = models.DateField()
    View Code

    2:执行命令:python manage.py makemigrations

    3:执行命令:python manage.py migrate 才会真正的在数据库中生成表

    4:对数据库的快捷操作

    步骤一:

     

    步骤二:

    步骤三: 

    步骤四:

     五、表的操作(增删改查):

    增加:

    第一种:通过类的对象去增加
    b = Book(name='python1',price=67,pub_date="2018-4-12",author='yhy')
    b.save()
    
    第二种:这种方式不需要再save一次
    Book.objects.create(name='python4',price=124,pub_date="2018-4-12",author='cfp')
    
    在学函数的时候:要是一个个的key = value的时候,我们可以采用
    **dic的方式去传入值:
    dic = {
    "name":"python4","price":124,"pub_date":"2018-4-12","author":"cfp"}
    Book.objects.create(**dic)
    View Code

    修改:

    查找数据的时候: filter 和 get 两种方式
        filter方式:是获取到一个QuerySet的集合。
        get的方式:是获取到一个model对象 ,而只要是model对象就必须才用save方法。
        注意:save的效率太低,你要是只是修改一个字段,会将其他的字段都一起重新赋值,虽然没改别的字段。 
        
        ##filter
        Book.objects.filter(author='cfp').update(price='999')
        
        ##get 
        b = Book.objects.get(author='cfp')
        b.price=123
        b.save()
    View Code

    查看每个的sql的语句是怎么执行的:

    需要在settings加上日志记录部分

    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    
    LOGGING
    View Code

    删除:

    Book.objects.get(author='cfp').delete()
    
    b = Book.objects.filter(author='yhy').delete()
    print(b)  ##(2, {'app01.Book': 2})Book表删除了两条数据
    

    查找:

    # 查询相关API:
    
    #  <1>filter(**kwargs):      它包含了与所给筛选条件相匹配的对象
    
    #  <2>all():                 查询所有结果
    
    #  <3>get(**kwargs):         返回与所给筛选条件相匹配的对象,返回结果有且只有一个,如果符合筛选条件的对象超过一个或者没有都会抛出错误。
    	
    

    对查询到的进行操作:

    select_list = Book.objects.all()[:2]  ###切片操作 
    select_list = Book.objects.all()[2:2]    
    select_list = Book.objects.all()[::2] 
    
    
    b =Book.objects.filter(author='cfp').values("name","price") 
    ##<QuerySet [{'name': 'python4', 'price': 124}]>  ##字典列表的方式
    
    c = Book.objects.filter(author='cfp').values_list("name","price") 
    ##<QuerySet [('python4', 124)]>  ##元组列表
    
    
    #  <5>exclude(**kwargs):     它包含了与所给筛选条件不匹配的对象
    
    #  <6>order_by(*field):      对查询结果排序
    
    #  <7>reverse():             对查询结果反向排序
    
    #  <8>distinct():            从返回结果中剔除重复纪录
    ###b =Book.objects.filter(author='cfp').values("name").distinct().count()
    
    #  <9>values_list(*field):   它与values()非常相似,它返回的是一个元组序列,values返回的是一个字典序列
    
    #  <10>count():              返回数据库中匹配查询(QuerySet)的对象数量。
    
    # <11>first():               返回第一条记录
    
    # <12>last():                返回最后一条记录
    
    #  <13>exists():             如果QuerySet包含数据,就返回True,否则返回False。
    View Code

    万能双下划线“__”

    #    models.Tb1.objects.filter(id__lt=10, id__gt=1)   # 获取id大于1 且 小于10的值
    #
    #    models.Tb1.objects.filter(id__in=[11, 22, 33])   # 获取id等于11、22、33的数据
    #    models.Tb1.objects.exclude(id__in=[11, 22, 33])  # not in
    #
    #    models.Tb1.objects.filter(name__contains="ven")   ##就是模糊查询 包含ven的书籍名字
    #    models.Tb1.objects.filter(name__icontains="ven") # icontains大小写不敏感
    #
    #    models.Tb1.objects.filter(id__range=[1, 2])   # 范围bettwen and
    #
    #    startswith,istartswith, endswith, iendswith,

     六、多表查询

    查询记录(基于对象) 

    ##正向查询  ##go这本书的出版社名字和地址
    # cc = Book.objects.get(name="go")
    # cc = Book.objects.filter(name="go")[0]
    # print(cc.publist_id.name,cc.publist_id.addr)
    
    ##反向查询  ###通过"人民出版社"找到它出版的书名和价格
    cc = Publish.objects.filter(name="人民出版社")[0]
    print(cc.book_set.all().values("name","price")) ##<QuerySet [{'name': 'go', 'price': 34}, {'name': 'java', 'price': 45}]>

     查询记录(基于"__")filter或value的双下划线

    ####通过"人民出版社"找到它出版的书名和价格
    ret = Book.objects.filter(publist_id__name="人民出版社").values("name","price")
    print(ret)  ##<QuerySet [{'name': 'go', 'price': 34}, {'name': 'java', 'price': 45}]>
    
    
    ####go这本书的出版社名字   ##book可以理解成反向查找
    ret = Publish.objects.filter(book__name="go").values("name")
    print(ret) ##<QuerySet [{'name': '人民出版社'}]>

     ret = Book.objects.filter(name="go").values("publist_id__name","publist_id__addr")
     print(ret) ##<QuerySet [{'publist_id__name': '人民出版社', 'publist_id__addr': '北京'}]>

     七、多对多表操作

    多对多表的创建:

    第一种:
    让models自动帮你创建第三张表
    class Book(models.Model):
        name = models.CharField(max_length=30)
        authors = models.ManyToManyField("Author")
        def __str__(self):
            return self.name
            
            
    第二种:
    自己建第三张表:
    class Book_Author(models.Model):
        book = models.ForeignKey("Book")
        author = models.ForeignKey("Author")
    View Code

    ManyToManyField操作

    ##添加数据
    # book_obj = Book.objects.get(id=1)
    # authors = Author.objects.all()
    # # book_obj.authors.add(*authors)  ##*是分解列表
    #book_obj.authors.add(1)
    #book_obj.authors.add([2,3])  #给id为1的book加上,id为1,2,3的作者
    
    
    ##删除数据
    # # book_obj.authors.remove(*authors)  ##解除全部
    # book_obj.authors.remove(2)  ##将id=2的作者移除
    #book_obj.authors.clear()     ##将id为1的book都清空
    #book_obj.authors.set([2,3,5]) ##将id为1的book 作者重置为2,3,5的id
    
    
    
    ##查操作和多表查询是一样的都有基于对象和基于"__"
    # book= Book.objects.get(id=1)
    # ret=book.authors.all()
    # print(ret.values("name"))
    # 
    # ret=Author.objects.filter(name='alex').values("book__name","book__price")
    # print(ret)
    View Code
    表: 
    class User(models.Model):
        name = models.CharField(max_length=32)
        m = models.ManyToManyField(to="Tag",related_name="mm")
    
        def __str__(self):
            return self.name
    
    class Tag(models.Model):
        caption = models.CharField(max_length=32)
        def __str__(self):
            return self.caption
    
    
    
    
    tages = models.User.objects.filter(name="yhy").values("m__caption")
    ##m是在User表中,m直接关联了对应tags里面的多条字段
    
    tages1 = models.Tag.objects.filter(user__m__user__name="yhy").values()
    
    # tag 和user 没有直接关联,而是通过user里面的m 第三张表
    #  user__m 找到第三张表,再反向__user找到user表  然后__name = "yhy"
    额外

    手动创建第三张表操作:

    操作 : 
    
    ##添加
    # book_obj = Book.objects.get(id=2)
    # authors = Author.objects.all()[0]
    # Book_Author.objects.create(author=authors,book=book_obj)
    
    ##删除
    Book_Author.objects.filter(author=1).delete()
    
    
    ##查询 
    表:
    
    class User(models.Model):
        name = models.CharField(max_length=32)
    
        def __str__(self):
            return self.name
    
    class Tag(models.Model):
        caption = models.CharField(max_length=32)
        def __str__(self):
            return self.caption
    
    class UserToTag(models.Model):
        nid = models.AutoField(primary_key = True)
        uid = models.ForeignKey(to="User")
        tid = models.ForeignKey(to="Tag")
        class Meta:
            unique_together = [("uid","tid"),]
            
            
    #反向查询 查询yhy对应的标签  找到对应的反向查询的表: usertotag 再根据里面表的,tid 或 uid找到对应的表
    #tages= models.User.objects.filter(name="yhy").values("usertotag__tid__caption")
    #tages = models.Tag.objects.filter(usertotag__uid__name="yhy").values()
    View Code

    八、聚合和分组查询

    要想使用聚合:aggregate先导入

    from django.db.models import Min,Max,Count,Sum
    

    聚合操作:

    ##查询alex出书的最少的价格是多少
    # ret = Book.objects.filter(book_author__author__name="alex").aggregate(Sum("price"))
    # print(ret)
    
    ##查询出了多少本书
    ret = Book.objects.filter(book_author__author__name="alex").aggregate(Count("price"))
    print(ret)

    分组操作:

    annotate: 分组,先分组再操作  

    filter: 就是筛选

    ##查询每个出版社出了几本书
    # ret= Publish.objects.values("name").annotate(Count("book__name"))
    # print(ret) ##<QuerySet [{'name': '人民出版社', 'book__name__count': 2}, {'name': '河南出版社', 'book__name__count': 2}]>
    
    ##查询每个作者出了几本书
    # ret = Book.objects.values("book_author__author__name").annotate(count=Count("name"))
    # print(ret)
    # < QuerySet[{'book_author__author__name': None, 'count': 2}, {'book_author__author__name': 'alex', 'count': 2}] >

     九、F查询和Q查询

    仅仅靠单一的关键字参数查询已经很难满足查询要求。此时Django为我们提供了F和Q查询:

    什么是单关键字?

    obj = Book.objects.get(name='go',price=45)  ##get返回的结果有且只有一个,不然报错
    ##name = "go"  就叫做单个关键字,一组键值对
    

    要求1给每个书卖价加10块钱

    Book.objects.all().update(price=price+10) ?
    不对!这写法是错误是,虽然在mysql的sql语句中可以写
    

    a、导入F、Q

    from django.db.models import  F,Q
    

    b、实现要求:

    Book.objects.all().update(price=F("price")+10) ##用F给他包起来

    要求2找出书籍价格为67 或 书籍名字为go的

    obj = Book.objects.get(name='go',price=45) 你可以通过逗号实现与的操作。 而要想使用或就必须用到Q操作 

    obj =  Book.objects.filter(Q(name="go")|Q(price=47))
    print(obj) ##<QuerySet [<Book: go>, <Book: linux>]>

    具体操作:

    # F 使用查询条件的值,专门取对象中某列值的操作
    
        # from django.db.models import F
        # models.Tb1.objects.update(num=F('num')+1)
    
    
    # Q 构建搜索条件
        from django.db.models import Q
    
        #1 Q对象(django.db.models.Q)可以对关键字参数进行封装,从而更好地应用多个查询
        q1=models.Book.objects.filter(Q(title__startswith='P')).all()
        print(q1)#[<Book: Python>, <Book: Perl>]
    
        # 2、可以组合使用&,|操作符,当一个操作符是用于两个Q的对象,它产生一个新的Q对象。
        Q(title__startswith='P') | Q(title__startswith='J')
    
        # 3、Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
        Q(title__startswith='P') | ~Q(pub_date__year=2005)
    
        # 4、应用范围:
    
        # Each lookup function that takes keyword-arguments (e.g. filter(),
        #  exclude(), get()) can also be passed one or more Q objects as
        # positional (not-named) arguments. If you provide multiple Q object
        # arguments to a lookup function, the arguments will be “AND”ed
        # together. For example:
    
        Book.objects.get(
            Q(title__startswith='P'),
            Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
        )
    
        #sql:
        # SELECT * from polls WHERE question LIKE 'P%'
        #     AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')
    
        # import datetime
        # e=datetime.date(2005,5,6)  #2005-05-06
    
        # 5、Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面。
        # 正确:
        Book.objects.get(
            Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
            title__startswith='P')
        # 错误:
        Book.objects.get(
            question__startswith='P',
            Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))
    View Code

     十、QuerySet的高效使用

    <1>Django的queryset是惰性的
    
         Django的queryset对应于数据库的若干记录(row),通过可选的查询来过滤。例如,下面的代码会得
         到数据库中名字为‘Dave’的所有的人:person_set = Person.objects.filter(first_name="Dave")
         上面的代码并没有运行任何的数据库查询。你可以使用person_set,给它加上一些过滤条件,或者将它传给某个函数,
         这些操作都不会发送给数据库。这是对的,因为数据库查询是显著影响web应用性能的因素之一。
    
    <2>要真正从数据库获得数据,你可以遍历queryset或者使用if queryset,总之你用到数据时就会执行sql.
       为了验证这些,需要在settings里加入 LOGGING(验证方式)
            obj=models.Book.objects.filter(id=3)
            # for i in obj:
            #     print(i)
    
            # if obj:
            #     print("ok")
    
    <3>queryset是具有cache的
         当你遍历queryset时,所有匹配的记录会从数据库获取,然后转换成Django的model。这被称为执行
        (evaluation).这些model会保存在queryset内置的cache中,这样如果你再次遍历这个queryset,
         你不需要重复运行通用的查询。
            obj=models.Book.objects.filter(id=3)
    
            # for i in obj:
            #     print(i)
                              ## models.Book.objects.filter(id=3).update(title="GO")
                              ## obj_new=models.Book.objects.filter(id=3)
            # for i in obj:
            #     print(i)   #LOGGING只会打印一次
    
    <4>
         简单的使用if语句进行判断也会完全执行整个queryset并且把数据放入cache,虽然你并不需要这些
         数据!为了避免这个,可以用exists()方法来检查是否有数据:
    
                obj = Book.objects.filter(id=4)
                #  exists()的检查可以避免数据放入queryset的cache。
                if obj.exists():
                    print("hello world!")
    
    <5>当queryset非常巨大时,cache会成为问题
    
         处理成千上万的记录时,将它们一次装入内存是很浪费的。更糟糕的是,巨大的queryset可能会锁住系统
         进程,让你的程序濒临崩溃。要避免在遍历数据的同时产生queryset cache,可以使用iterator()方法
         来获取数据,处理完数据就将其丢弃。
            objs = Book.objects.all().iterator()
            # iterator()可以一次只从数据库获取少量数据,这样可以节省内存
            for obj in objs:
                print(obj.name)
            #BUT,再次遍历没有打印,因为迭代器已经在上一次遍历(next)到最后一次了,没得遍历了
            for obj in objs:
                print(obj.name)
    
         #当然,使用iterator()方法来防止生成cache,意味着遍历同一个queryset时会重复执行查询。所以使
         #用iterator()的时候要当心,确保你的代码在操作一个大的queryset时没有重复执行查询
    
    总结:
        queryset的cache是用于减少程序对数据库的查询,在通常的使用下会保证只有在需要的时候才会查询数据库。
    使用exists()和iterator()方法可以优化程序对内存的使用。不过,由于它们并不会生成queryset cache,可能
    会造成额外的数据库查询。
    View Code

     8:Django Admin

    Django Admin: 关于数据库的一个后台管理工具 和naicat 差不多。 

    a、创建超级用户

    python manage.py createsuperuser ##创建超级用户

    b、admin文件中的自定制:

    from django.contrib import admin
    
    # Register your models here.
    
    from app01 import  models
    
    class BookAdmin(admin.ModelAdmin):
        list_display = ("id","name","pub_date","price") ##显示
        list_editable = ("name",)  ##可以直接编辑的
        filter_horizontal = ("authors",) ##在增加author的时候可以水平查找
        list_per_page = 21  ##21条记录为1页
        search_fields = ("name","authors__name") ##可以用name继续搜索记录,也可以用author_name
        list_filter = ("pub_date","publist_id") ##相当于分组了,根据日期、根据出版社查询
        # ordering = ("-price",) ##admin里面的字段按降序排序
        ordering = ("price","id") ##按升序,如果价格一样再按id去排
    
    
    
    admin.site.register(models.Book,BookAdmin)
    admin.site.register(models.Publish)
    admin.site.register(models.Author)
    View Code

     c、admin页面都是英文  看中文setting配置文件

     # LANGUAGE_CODE = 'en-us'
    LANGUAGE_CODE = 'zh-hans'
    

    d、让admin页面的字段出现中文 models字段加verbose_name

    class Book(models.Model):
        name = models.CharField(max_length=30,verbose_name="姓名")
        price = models.IntegerField("价格")  ##不写verbose_name直接放在第一个也是可以的
        pub_date = models.DateField(verbose_name="出版日期")

    model的补充:

    Field的重要参数

    <1> CharField
            #字符串字段, 用于较短的字符串.
            #CharField 要求必须有一个参数 maxlength, 用于从数据库层和Django校验层限制该字段所允许的最大字符数.
    
    <2> IntegerField
           #用于保存一个整数.
    
    <3> FloatField
            # 一个浮点数. 必须 提供两个参数:
            #
            # 参数    描述
            # max_digits    总位数(不包括小数点和符号)
            # decimal_places    小数位数
                    # 举例来说, 要保存最大值为 999 (小数点后保存2位),你要这样定义字段:
                    #
                    # models.FloatField(..., max_digits=5, decimal_places=2)
                    # 要保存最大值一百万(小数点后保存10位)的话,你要这样定义:
                    #
                    # models.FloatField(..., max_digits=19, decimal_places=10)
                    # admin 用一个文本框(<input type="text">)表示该字段保存的数据.
    
    <4> AutoField
            # 一个 IntegerField, 添加记录时它会自动增长. 你通常不需要直接使用这个字段; 
            # 自定义一个主键:my_id=models.AutoField(primary_key=True)
            # 如果你不指定主键的话,系统会自动添加一个主键字段到你的 model.
    
    <5> BooleanField
            # A true/false field. admin 用 checkbox 来表示此类字段.
    
    <6> TextField
            # 一个容量很大的文本字段.
            # admin 用一个 <textarea> (文本区域)表示该字段数据.(一个多行编辑框).
    
    <7> EmailField
            # 一个带有检查Email合法性的 CharField,不接受 maxlength 参数.
    
    <8> DateField
            # 一个日期字段. 共有下列额外的可选参数:
            # Argument    描述
            # auto_now    当对象被保存时,自动将该字段的值设置为当前时间.通常用于表示 "last-modified" 时间戳.
            # auto_now_add    当对象首次被创建时,自动将该字段的值设置为当前时间.通常用于表示对象创建时间.
            #(仅仅在admin中有意义...)
    
    <9> DateTimeField
            #  一个日期时间字段. 类似 DateField 支持同样的附加选项.
    
    <10> ImageField
            # 类似 FileField, 不过要校验上传对象是否是一个合法图片.#它有两个可选参数:height_field和width_field,
            # 如果提供这两个参数,则图片将按提供的高度和宽度规格保存.     
    <11> FileField
         # 一个文件上传字段.
         #要求一个必须有的参数: upload_to, 一个用于保存上载文件的本地文件系统路径. 这个路径必须包含 strftime #formatting, 
         #该格式将被上载文件的 date/time 
         #替换(so that uploaded files don't fill up the given directory).
         # admin 用一个<input type="file">部件表示该字段保存的数据(一个文件上传部件) .
    
         #注意:在一个 model 中使用 FileField 或 ImageField 需要以下步骤:
                #(1)在你的 settings 文件中, 定义一个完整路径给 MEDIA_ROOT 以便让 Django在此处保存上传文件. 
                # (出于性能考虑,这些文件并不保存到数据库.) 定义MEDIA_URL 作为该目录的公共 URL. 要确保该目录对 
                #  WEB服务器用户帐号是可写的.
                #(2) 在你的 model 中添加 FileField 或 ImageField, 并确保定义了 upload_to 选项,以告诉 Django
                # 使用 MEDIA_ROOT 的哪个子目录保存上传文件.你的数据库中要保存的只是文件的路径(相对于 MEDIA_ROOT). 
                # 出于习惯你一定很想使用 Django 提供的 get_<#fieldname>_url 函数.举例来说,如果你的 ImageField 
                # 叫作 mug_shot, 你就可以在模板中以 {{ object.#get_mug_shot_url }} 这样的方式得到图像的绝对路径.
    
    <12> URLField
          # 用于保存 URL. 若 verify_exists 参数为 True (默认), 给定的 URL 会预先检查是否存在( 即URL是否被有效装入且
          # 没有返回404响应).
          # admin 用一个 <input type="text"> 文本框表示该字段保存的数据(一个单行编辑框)
    
    <13> NullBooleanField
           # 类似 BooleanField, 不过允许 NULL 作为其中一个选项. 推荐使用这个字段而不要用 BooleanField 加 null=True 选项
           # admin 用一个选择框 <select> (三个可选择的值: "Unknown", "Yes""No" ) 来表示这种字段数据.
    
    <14> SlugField
           # "Slug" 是一个报纸术语. slug 是某个东西的小小标记(短签), 只包含字母,数字,下划线和连字符.#它们通常用于URLs
           # 若你使用 Django 开发版本,你可以指定 maxlength. 若 maxlength 未指定, Django 会使用默认长度: 50.  #在
           # 以前的 Django 版本,没有任何办法改变50 这个长度.
           # 这暗示了 db_index=True.
           # 它接受一个额外的参数: prepopulate_from, which is a list of fields from which to auto-#populate 
           # the slug, via JavaScript,in the object's admin form: models.SlugField
           # (prepopulate_from=("pre_name", "name"))prepopulate_from 不接受 DateTimeFields.
    
    <13> XMLField
            #一个校验值是否为合法XML的 TextField,必须提供参数: schema_path, 它是一个用来校验文本的 RelaxNG schema #的文件系统路径.
    
    <14> FilePathField
            # 可选项目为某个特定目录下的文件名. 支持三个特殊的参数, 其中第一个是必须提供的.
            # 参数    描述
            # path    必需参数. 一个目录的绝对文件系统路径. FilePathField 据此得到可选项目. 
            # Example: "/home/images".
            # match    可选参数. 一个正则表达式, 作为一个字符串, FilePathField 将使用它过滤文件名.  
            # 注意这个正则表达式只会应用到 base filename 而不是
            # 路径全名. Example: "foo.*.txt^", 将匹配文件 foo23.txt 却不匹配 bar.txt 或 foo23.gif.
            # recursive可选参数.要么 True 要么 False. 默认值是 False. 是否包括 path 下面的全部子目录.
            # 这三个参数可以同时使用.
            # match 仅应用于 base filename, 而不是路径全名. 那么,这个例子:
            # FilePathField(path="/home/images", match="foo.*", recursive=True)
            # ...会匹配 /home/images/foo.gif 而不匹配 /home/images/foo/bar.gif
    
    <15> IPAddressField
            # 一个字符串形式的 IP 地址, (i.e. "24.124.1.30").
    <16># CommaSeparatedIntegerField
            # 用于存放逗号分隔的整数值. 类似 CharField, 必须要有maxlength参数.
    View Code

    字段修饰符:

    related_name
    
    #s2c = models.ForeignKey("Classes")
    s2c = models.ForeignKey("Classes",related_name="ssss") ##被关联的查询
    
    ##反向
    #Classes.objects.all().values("cname","student__sname")
    Classes.objects.all().values("cname","ssss__sname")
  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/hero799/p/8849736.html
Copyright © 2011-2022 走看看