Django框架


一、什么是web框架

   框架,即framework,特指為解決一個開放性問題而設計的具有一定約束性的支撐結構,使用框架可以幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞台來做表演。 對於所有的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。

示例:自己寫一個框架

myWeb.py

from wsgiref.simple_server import make_server


import time

def foo1(req):
    f=open("index2.html","rb")
    data=f.read()
    return data

def foo2(req):
    f=open("index1.html","rb")
    data=f.read()
    return data

def login(req):
    print(req["QUERY_STRING"])

    return b"welcome!"

def signup(req):
    pass

def show_time(req):
   times=time.ctime()

   #return ("<h1>time:%s</h1>"%str(times)).encode("utf8")
   f=open("show_time.html","rb")

   data=f.read()
   data=data.decode("utf8")
   data=data.replace("{{time}}",str(times))

   return data.encode("utf8")

def router():
    url_patterns=[
        ("/login",login),
        ("/signup",signup),
        ("/yuan",foo2),
        ("/alex",foo1),
        ("/show_time",show_time),

    ]

    return url_patterns

def application(environ, start_response):

    print("path",environ["PATH_INFO"])
    path=environ["PATH_INFO"]

    start_response('200 OK', [('Content-Type', 'text/html')])

    url_patterns=router()

    func=None
    for item in url_patterns:
        if item[0]==path:
            func=item[1]
            break
    if func:
          return [func(environ)]
    else:
        return [b"404"]


httpd = make_server('', 8080, application)

print('Serving HTTP on port 8080...')
# 開始監聽HTTP請求:
httpd.serve_forever()
View Code

show_time.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

</head>
<body>

<h1>時間:{{time}}</h1>

</body>
</html>
View Code

login.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

</head>
<body>


<form action="http://127.0.0.1:8080/login" method="get">
    <p>用戶名<input type="text" name="user"></p>
    <p>密碼<input type="password" name="pwd"></p>
    <p><input type="submit">提交</p>
</form>

</body>
</html>
View Code

index1.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

</head>
<body>

<h1>hello nulige</h1>

</body>
</html>
View Code

index2.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

</head>
<body>

<h1>hello alex</h1>

</body>
</html>
View Code

  最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。 如果要動態生成HTML,就需要把上述步驟自己來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,如果我們自己來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規范。 正確的做法是底層代碼由專門的服務器軟件實現,我們用Python專注於生成HTML文檔。因為我們不希望接觸到TCP連接、HTTP原始請求和響應格式,所以,需要一個統一的接口,讓我們專心用Python編寫Web業務。 這個接口就是WSGI:Web Server Gateway Interface。

 

二、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。

三、django的流程和命令行工具

django實現流程

django
    #安裝: pip3 install django

          添加環境變量

    #1  創建project
       django-admin startproject mysite

       ---mysite

          ---settings.py
          ---url.py
          ---wsgi.py

       ---- manage.py(啟動文件)  

    #2  創建APP       
       python mannage.py startapp  app01

    #3  settings配置
    
       TEMPLATES

       STATICFILES_DIRS=(
            os.path.join(BASE_DIR,"statics"),
        )

       STATIC_URL = '/static/' 
       #  我們只能用 STATIC_URL,但STATIC_URL會按着你的STATICFILES_DIRS去找#4  根據需求設計代碼
           url.py
           view.py

    #5  使用模版
       render(req,"index.html")   

    #6  啟動項目
       python manage.py runserver  127.0.0.1:8090

    #7  連接數據庫,操作數據
       model.py

django的命令行工具

django-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每一個Django Project里都會有一個mannage.py。

<1> 創建一個django工程 : django-admin.py startproject mysite

        當前目錄下會生成mysite的工程,目錄結構如下:

        

  • manage.py ----- Django項目里面的工具,通過它可以調用django shell和數據庫等。
  • settings.py ---- 包含了項目的默認設置,包括數據庫信息,調試標志以及其他一些工作的變量。
  • urls.py ----- 負責把URL模式映射到應用程序。

<2>在mysite目錄下創建blog應用: python manage.py startapp blog

        

<3>啟動django項目:python manage.py runserver 8080

       這樣我們的django就啟動起來了!當我們訪問:http://127.0.0.1:8080/時就可以看到:

       

<4>生成同步數據庫的腳本:python manage.py makemigrations  

                     同步數據庫:  python manage.py migrate   

       注意:在開發過程中,數據庫同步誤操作之后,難免會遇到后面不能同步成功的情況,解決這個問題的一個簡單粗暴方法是把migrations目錄下

                的腳本(除__init__.py之外)全部刪掉,再把數據庫刪掉之后創建一個新的數據庫,數據庫同步操作再重新做一遍。            

<5>當我們訪問http://127.0.0.1:8080/admin/時,會出現:

 

所以我們需要為進入這個項目的后台創建超級管理員:python manage.py createsuperuser設置好用戶名和密碼后便可登錄啦!

<6>清空數據庫:python manage.py  flush

<7>查詢某個命令的詳細信息: django-admin.py  help  startapp

       admin 是Django 自帶的一個后台數據庫管理系統。

<8>啟動交互界面 :python manage.py  shell

     這個命令和直接運行 python 進入 shell 的區別是:你可以在這個 shell 里面調用當前項目的 models.py 中的 API,對於操作數據,還有一些小測試非常方便。

<9> 終端上輸入python manage.py 可以看到詳細的列表,在忘記子名稱的時候特別有用

實例練習1-提交數據並展示

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>創建個人信息</h1>

<form action="/userInfor/" 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>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性別</td>
        <td>郵箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


-----------------------url.py---------------------------------------
url(r'^userInfor/', views.userInfor)

-----------------------views.py--------------------------------------

info_list=[]

def userInfor(req):

    if req.method=="POST":
        username=req.POST.get("username",None)
        sex=req.POST.get("sex",None)
        email=req.POST.get("email",None)

        info={"username":username,"sex":sex,"email":email}
        info_list.append(info)

    return render(req,"userInfor.html",{"info_list":info_list})

實例練習2-提交數據並展示(數據庫)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<h1>創建個人信息</h1>

<form action="/userInfor/" 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>

</form>

<hr>

<h1>信息展示</h1>

<table border="1">

    <tr>
        <td>姓名</td>
        <td>性別</td>
        <td>郵箱</td>
    </tr>
    {% for i in info_list %}

        <tr>
            <td>{{ i.username }}</td>
            <td>{{ i.sex }}</td>
            <td>{{ i.email }}</td>
        </tr>

    {% endfor %}

</table>

</body>
</html>


----------------------------------------------models.py
from django.db import models

# Create your models here.


class UserInfor(models.Model):

    username=models.CharField(max_length=64)
    sex=models.CharField(max_length=64)
    email=models.CharField(max_length=64)

----------------------------------------------views.py

from django.shortcuts import render

from app01 import models
# Create your views here.


def userInfor(req):

    if req.method=="POST":
        u=req.POST.get("username",None)
        s=req.POST.get("sex",None)
        e=req.POST.get("email",None)


       #---------表中插入數據方式一
            # info={"username":u,"sex":e,"email":e}
            # models.UserInfor.objects.create(**info)

       #---------表中插入數據方式二
        models.UserInfor.objects.create(
            username=u,
            sex=s,
            email=e
        )

        info_list=models.UserInfor.objects.all()

        return render(req,"userInfor.html",{"info_list":info_list})

    return render(req,"userInfor.html")

四 Django的配置文件(settings)

靜態文件設置:

一、概述:

     #靜態文件交由Web服務器處理,Django本身不處理靜態文件。簡單的處理邏輯如下(以nginx為例):

     #          URI請求-----> 按照Web服務器里面的配置規則先處理,以nginx為例,主要求配置在nginx.
                             #conf里的location

                         |---------->如果是靜態文件,則由nginx直接處理

                         |---------->如果不是則交由Django處理,Django根據urls.py里面的規則進行匹配

    # 以上是部署到Web服務器后的處理方式,為了便於開發,Django提供了在開發環境的對靜態文件的處理機制,方法是這樣:

    #1、在INSTALLED_APPS里面加入'django.contrib.staticfiles',

    #2、在urls.py里面加入
       if settings.DEBUG:  
           urlpatterns += patterns('', url(r'^media/(?P<path>.*)$', 
           'django.views.static.serve', {'document_root': settings.MEDIA_ROOT }),   
            url(r'^static/(?P<path>.*)$',
          'django.views.static.serve',{'document_root':settings.STATIC_ROOT}), )  

    # 3、這樣就可以在開發階段直接使用靜態文件了。

二、MEDIA_ROOT和MEDIA_URL

        #而靜態文件的處理又包括STATIC和MEDIA兩類,這往往容易混淆,在Django里面是這樣定義的:

        #MEDIA:指用戶上傳的文件,比如在Model里面的FileFIeld,ImageField上傳的文件。如果你定義

        #MEDIA_ROOT=c:\temp\media,那么File=models.FileField(upload_to="abc/")#,上傳的文件就會被保存到c:\temp\media\abc  
        #eg:
            class blog(models.Model):  
                   Title=models.charField(max_length=64)  
                   Photo=models.ImageField(upload_to="photo") 
        #     上傳的圖片就上傳到c:\temp\media\photo,而在模板中要顯示該文件,則在這樣寫
        #在settings里面設置的MEDIA_ROOT必須是本地路徑的絕對路徑,一般是這樣寫:
                 BASE_DIR= os.path.abspath(os.path.dirname(__file__))  
                 MEDIA_ROOT=os.path.join(BASE_DIR,'media/').replace('\\','/') 

        #MEDIA_URL是指從瀏覽器訪問時的地址前綴,舉個例子:
            MEDIA_ROOT=c:\temp\media\photo  
            MEDIA_URL="/data/"
        #在開發階段,media的處理由django處理:

        #    訪問http://localhost/data/abc/a.png就是訪問c:\temp\media\photo\abc\a.png

        #    在模板里面這樣寫<img src="{{MEDIA_URL}}abc/a.png">

        #    在部署階段最大的不同在於你必須讓web服務器來處理media文件,因此你必須在web服務器中配置,
        #  以便能讓web服務器能訪問media文件
        #    以nginx為例,可以在nginx.conf里面這樣:

                 location ~/media/{
                       root/temp/
                       break;
                    }

        #    具體可以參考如何在nginx部署django的資料。

三、STATIC_ROOT和STATIC_URL、
    STATIC主要指的是如css,js,images這樣文件,在settings里面可以配置STATIC_ROOT和STATIC_URL,
    配置方式與MEDIA_ROOT是一樣的,但是要注意

    #STATIC文件一般保存在以下位置:

    #1、STATIC_ROOT:在settings里面設置,一般用來放一些公共的js,css,images等。

    #2、app的static文件夾,在每個app所在文夾均可以建立一個static文件夾,然后當運行collectstatic時,
    #    Django會遍歷INSTALL_APPS里面所有app的static文件夾,將里面所有的文件復制到STATIC_ROOT。因此,
    #   如果你要建立可復用的app,那么你要將該app所需要的靜態文件放在static文件夾中。

    # 也就是說一個項目引用了很多app,那么這個項目所需要的css,images等靜態文件是分散在各個app的static文件的,比
    #  較典型的是admin應用。當你要發布時,需要將這些分散的static文件收集到一個地方就是STATIC_ROOT。

    #3、STATIC文件還可以配置STATICFILES_DIRS,指定額外的靜態文件存儲位置。
    #  STATIC_URL的含義與MEDIA_URL類似。

    # ----------------------------------------------------------------------------
    #注意1:
        #為了后端的更改不會影響前端的引入,避免造成前端大量修改

        STATIC_URL = '/static/'               #引用名
        STATICFILES_DIRS = (
            os.path.join(BASE_DIR,"statics")  #實際名 ,即實際文件夾的名字
        )

        #django對引用名和實際名進行映射,引用時,只能按照引用名來,不能按實際名去找
        #<script src="/statics/jquery-3.1.1.js"></script>
        #------error-----不能直接用,必須用STATIC_URL = '/static/':
        #<script src="/static/jquery-3.1.1.js"></script>

    #注意2(statics文件夾寫在不同的app下,靜態文件的調用):

        STATIC_URL = '/static/'

        STATICFILES_DIRS=(
            ('hello',os.path.join(BASE_DIR,"app01","statics")) ,
        )

        #<script src="/static/hello/jquery-1.8.2.min.js"></script>

    #注意3:
        STATIC_URL = '/static/'
        {% load staticfiles %}
       # <script src={% static "jquery-1.8.2.min.js" %}></script>

其它重要參數設置:

APPEND_SLASH
       Default: True
       When set to True, if the request URL does not match any of the patterns in the URLconf and it 
       doesn’t end in a slash, an HTTP redirect is issued to the same URL with a slash appended. Note 
       that the redirect may cause any data submitted in a POST request to be lost.

五 Django URL (路由系統)

     URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL模式以及要為該URL模式調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。

urlpatterns = [
    url(正則表達式, views視圖函數,參數,別名),
]

參數說明:

  • 一個正則表達式字符串
  • 一個可調用對象,通常為一個視圖函數或一個指定視圖函數路徑的字符串
  • 可選的要傳遞給視圖函數的默認參數(字典形式)
  • 一個可選的name參數

5.1 Here’s a sample URLconf:

from django.conf.urls import url
from django.contrib import admin

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/([0-9]{4})/$', views.year_archive),  #no_named group

    url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),

    url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),

]

Note:

#1   There’s no need to add a leading slash, because every URL has that. For
#    example, it’s ^articles, not ^/articles.

#2   A request to /articles/2005/03/ would match the third entry in the list.
#    Django would call the function views.month_archive(request, '2005', '03').

#3   /articles/2005/3/ would not match any URL patterns

#4   /articles/2003/ would match the first pattern in the list, not the second one

#5   /articles/2003/03/03/ would match the final pattern. Django would call the
#    functionviews.article_detail(request, '2003', '03', '03').

5.2 Named groups

      The above example used simple, non-named regular-expression groups (via parenthesis) to capture bits of the URL and pass them as positional arguments to a view. In more advanced usage, it’s possible to use named regular-expression groups to capture URL bits and pass them as keyword arguments to a view.

       In Python regular expressions, the syntax for named regular-expression groups is (?P<name>pattern), where name is the name of the group and pattern is some pattern to match.

Here’s the above example URLconf, rewritten to use named groups:

import re

ret=re.search('(?P<id>\d{3})/(?P<name>\w{3})','weeew34ttt123/ooo')

print(ret.group())
print(ret.group('id'))
print(ret.group('name'))

ready
from django.conf.urls import url
  
from . import views
  
urlpatterns = [
    url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/(?P<year>[0-9]{4})/$', views.year_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', views.month_archive),
    url(r'^articles/(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/(?P<day>[0-9]{2})/$', views.article_detail),
]

This accomplishes exactly the same thing as the previous example, with one subtle difference: The captured values are passed to view functions as keyword arguments rather than positional arguments.

5.3  Passing extra options to view functions

       URLconfs have a hook that lets you pass extra arguments to your view functions, as a Python dictionary.

The django.conf.urls.url() function can take an optional third argument which should be a dictionary of extra keyword arguments to pass to the view function.

For example:

from django.conf.urls import url
from . import views
  
urlpatterns = [
    url(r'^blog/(?P<year>[0-9]{4})/$', views.year_archive, {'foo': 'bar'}),
]

  In this example, for a request to /blog/2005/, Django will call views.year_archive(request, year='2005',foo='bar').

This technique is used in the syndication framework to pass metadata and options to views.

Dealing with conflicts

       It’s possible to have a URL pattern which captures named keyword arguments, and also passes arguments with the same names in its dictionary of extra arguments. When this happens, the arguments in the dictionary will be used instead of the arguments captured in the URL.

5.4 name param

urlpatterns = [
    url(r'^index',views.index,name='bieming'),
    url(r'^admin/', admin.site.urls),
    # url(r'^articles/2003/$', views.special_case_2003),
    url(r'^articles/([0-9]{4})/$', views.year_archive),
    # url(r'^articles/([0-9]{4})/([0-9]{2})/$', views.month_archive),
    # url(r'^articles/([0-9]{4})/([0-9]{2})/([0-9]+)/$', views.article_detail),

]
###################

def index(req):
    if req.method=='POST':
        username=req.POST.get('username')
        password=req.POST.get('password')
        if username=='alex' and password=='123':
            return HttpResponse("登陸成功")



    return render(req,'index.html')

#####################

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
{#     <form action="/index/" method="post">#}
     <form action="{% url 'bieming' %}" method="post">
         用戶名:<input type="text" name="username">
         密碼:<input type="password" name="password">
         <input type="submit" value="submit">
     </form>
</body>
</html>


#######################

5.5 Including other URLconfs

#At any point, your urlpatterns can “include” other URLconf modules. This
#essentially “roots” a set of URLs below other ones.

#For example, here’s an excerpt of the URLconf for the Django website itself.
#It includes a number of other URLconfs:


from django.conf.urls import include, url

urlpatterns = [
   url(r'^admin/', admin.site.urls),
   url(r'^blog/', include('blog.urls')),
]

 

綜合應用示例:

新建一個django項目:django_lesson

代碼如下:

statics下面文件:

#導入jquery文件

jquery-3.1.1.js

blog下面文件:

urls.py

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

#引入模塊 from blog import views
#URL路由分發 urlpatterns = [ url(r'article/(\d{4})$',views.article_year), url(r'article/(?P
<year>\d{4})/(?P<month>\d{2})',views.article_year_month), url(r'article/(?P<year>\d{4})/(?P<month>\d{2})/\d+',views.article_year_month), url(r"register",views.register,name="reg"), ]

views.py

from django.shortcuts import render,HttpResponse
import time
# Create your views here. def show_time(requset): #return HttpResponse("hello") t=time.ctime() return render(requset,"index.html",{"time":t})
def article_year(request,y): return HttpResponse(y)
def article_year_month(request,year,month): return HttpResponse("year:%s month:%s"%(year,month))
def register(request): if request.method=="POST": print(request.POST.get("user")) print(request.POST.get("age")) return HttpResponse("success!") return render(request,"register.html")

diango_lensson下面文件:

settings.py

"""
Django settings for django_lesson project.

Generated by 'django-admin startproject' using Django 1.10.5.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '@jm-+mpxpv-@3%=o^fij9w+dtsil=18&6bpt*akkv+=422-vsl'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'blog',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    #'django.middleware.csrf.CsrfViewMiddleware', #django的安全機制,調試程序請注釋掉,否則報錯
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'django_lesson.urls'

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',
            ],
        },
    },
]

WSGI_APPLICATION = 'django_lesson.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}


# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]


# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = True


# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/' #別名

#配置路徑方法一:
# STATICFILES_DIRS=(
#     os.path.join(BASE_DIR,"statics"),
# )
#配置路徑方法二:
STATICFILES_DIRS=( os.path.join(BASE_DIR,"blog","statics"), )

urls.py

"""django_lesson URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url,include
from django.contrib import admin

#引入模塊 from blog import views
#配置URL路由分發 urlpatterns = [ url(r'^admin/', admin.site.urls), url(r'^show_time/', views.show_time), url(r'^blog/', include('blog.urls')), ]

templates下面文件:

register.html

<!DOCTYPE html>
<html lang="en">
<head>
    {% load staticfiles %}
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }


    </style>
</head>
<body>

<h1>學生注冊</h1>
<hr>
<form action="{% url 'reg' %}" method="post">
   <p>姓名<input type="text" name="user"></p>
   <p>年齡<input type="text" name="age"></p>
   <p>愛好<input type="checkbox" name="hobby" value="1">籃球
          <input type="checkbox" name="hobby" value="2">足球
          <input type="checkbox" name="hobby" value="3">乒乓球
   </p>
   <p><input type="submit">提交</p>
</form>

</body> </html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    {% load staticfiles %}
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }

    </style>
</head>
<body>

<h1>hello {{ time }}</h1>

//<script src="/static/jquery-3.1.1.js"></script>
<script src="{% static 'jquery-3.1.1.js' %}"></script>


<script> $("h1").css("color","red") </script>


</body>
</html>

 

六 Django Views(視圖函數)

http請求中產生兩個核心對象:

        http請求:HttpRequest對象

        http響應:HttpResponse對象

所在位置:django.http

之前我們用到的參數request就是HttpRequest    檢測方法:isinstance(request,HttpRequest)

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

注意一個常用方法:request.POST.getlist('')

2 HttpResponse對象:

  對於HttpRequest對象來說,是由django自動創建的,但是,HttpResponse對象就必須我們自己創建。每個view請求處理方法必須返回一個HttpResponse對象。

  HttpResponse類在django.http.HttpResponse

  在HttpResponse對象上擴展的常用方法:

頁面渲染:         render()(推薦)
render_to_response(), 頁面跳轉: redirect("路徑") locals(): 可以直接將函數中所有的變量傳給模板

補充:

-----------------------------------url.py

 url(r"login",   views.login),
 url(r"yuan_back",   views.yuan_back),

-----------------------------------views.py
def login(req):
    if req.method=="POST":
        if 1:
            # return redirect("/yuan_back/")
            name="yuanhao"

            return render(req,"my backend.html",locals())

    return render(req,"login.html",locals())


def yuan_back(req):

    name="苑昊"

    return render(req,"my backend.html",locals())

-----------------------------------login.html

<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>
</form>
-----------------------------------my backend.html
<h1>用戶{{ name }}你好</h1>

#總結: render和redirect的區別:
#   1 if render的頁面需要模板語言渲染,需要的將數據庫的數據加載到html,那么所有的這一部分
#     除了寫在yuan_back的視圖函數中,必須還要寫在login中,代碼重復,沒有解耦.

#   2 the most important: url沒有跳轉到/yuan_back/,而是還在/login/,所以當刷新后
#     又得重新登錄.

七 Template基礎 

模板系統介紹

模板系統的組成:HTML代碼和邏輯控制代碼

邏輯控制代碼可以理解是django模板語言

django的模板語言組成

  1. 變量(使用雙大括號來引用變量):

  2. 標簽(tag)的使用(使用大括號和百分比的組合來表示使用tag)
  3. 模板繼承

模板語言之變量

語法:

1
{{var_name}}   var_name 指變量名

  

使用模板語言之前:

先介紹template對象和Context對象

進入django的項目的交互環境

1
2
3
4
5
6
7
python manange.py shell
 
>>>  from  django.template import Context, Template
>>> t = Template( 'My name is {{ name }}.' )   #模板對象
>>> c = Context({ 'name' 'xixi' })       #上下文對象
>>> t.render(c)
'My name is xixi.'

  

同一模板,多個上下文,一旦有了模板對象,你就可以通過它渲染多個context,無論何時我們都可以像這樣使用同一模板源渲染多個context,只進行 一次模板創建然后多次調用render()方法渲染會更為高效:

模板對象:可以理解文HTML文件,只不過包含了Django的模板語法

context對象:大多數的情況下,我們會將字典傳給Context(),一旦初始化后,就可以使用標准的Python字典語法操作Context對象:

上下文對象如果是不合法的變量,模板系統會把他當做空字符串顯示

1
2
3
>>> t = Template( 'Your name is {{  name }}' )   變量名是name
>>> t.render(Context({ 'var' : 'hello' }))  #沒有 var 這個變量名字
'Your name is '

變量之深度查詢(英文句點符.)

上面只是通過 context 傳遞的簡單參數值主要是字符串,然而,模板系統能夠非常簡潔地處理更加復雜的數據結構,例如list、dictionary和自定義的對象。

 

list索引

1
2
3
4
5
6
>>>  from  django.template import Context, Template
>>> names = [ "xixi" , "abc" , "123" , "hehe" ]
>>> t = Template( "this is {{ name.0}}" )
>>> c = Context({ "name" :names})
>>> t.render(c)
'this is xixi'

如果不寫 {{ name.0}}  后面的(.索引) 表示整個列表

字典

1
2
3
4
5
6
>>>  from   django.template  import  Template, Context
>>> person = { 'name' : "xixi" "age" : 21}
>>> t = Template( "{{ person.name }} is {{ person.age }} years old." )
>>> c = Context({  "person" : person })
>>> t.render(c)
'xixi is 25 years old.'

自定義對象

1
2
3
4
5
6
7
8
9
10
11
12
13
>>>  from    django.template  import  Template, Context
>>> import  datetime
>>> d = datetime.date(1996, 12,12 )
>>> d.year
1996
>>> d.month
12
>>> d.day
12
>>> t = Template( 'The month is {{ date.month }} and year is {{ date.year }}' )
>>> c = Context({ 'date' : d})
>>> t.render(c)
'The month is 12 and year is 1996' 

訪問對象方法

1
2
3
4
5
>>> t = Template( '{{ var }} -- {{ var.upper }} -- {{  var.isdigit }}' )
>>> t.render(Context({ 'var' 'hello' }))
'hello -- HELLO -- False'
>>> t.render(Context({ 'var' '123' }))
'123 -- 123 -- True'

跟python操作差不多 

變量過濾器(filter)的使用

語法格式

1
{{ var |filter:param}}

管道符號后面的功能,比如{{ var|length }},求變量長度的 length 就是一個過濾器。

常用的過濾器

1
2
3
4
5
6
7
8
9
10
11
12
13
1.add          :   給變量加上相應的值
   
2 addslashes   :    給變量中的引號前加上斜線
  
3  capfirst     :    首字母大寫
  
4  cut          :   從字符串中移除指定的字符
  
5  date         :   格式化日期字符串
 
6   default       :   如果值是False,就替換成設置的默認值,否則就是用本來的值
 
7  default_if_none:  如果值是None,就替換成設置的默認值,否則就使用本來的值

標簽(tag)的使用

語法格式

1
{% tags %}

{% if %} 的使用

{% if %} 和 {% endif %}要成對

{% if %}標簽計算一個變量值,如果是“true”,即它存在、不為空並且不是false的boolean值,系統則會顯示{% if %}和{% endif %}間的所有內容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
{%  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 %}   

 {% for %}的使用

{% for %} 和 {% endfor %}要成對

{% for %}標簽允許你按順序遍歷一個序列中的各個元素,每次循環模板系統都會渲染{% for %}和{% endfor %}之間的所有內容

1
2
3
4
5
6
基本格式
<ul>
{%  for  obj  in  list %}
     <li>{{ obj.name }}</li>
{% endfor %}
</ul> 

在標簽里添加reversed來反序循環列表:

1
2
3
{%  for  obj  in  list reversed %}
     ...
{% endfor %} 

{% for %}標簽可以嵌套:

1
2
3
4
5
6
7
8
{%  for  country  in  countries %}
         <h1>{{ country.name }}</h1>
         <ul>
          {%  for  city  in  country.city_list %}
             <li>{{ city }}</li>
          {% endfor %}
         </ul>
{% endfor %}

{% for %}不支持中斷循環,也不支持continue語句

{% for %}關於循環其他用法

1
2
3
4
5
6
7
forloop.counter表示循環的次數,它從1開始計數,第一次循環設為1:
forloop.counter0    索引從 0 開始算
forloop.revcounter表示循環中剩下的items數量,第一次循環時設為items總數,最后一次設為1
forloop.revcounter0表示`items總數少一個,最后一次循環設置為0
forloop.first表示當第一次循環時值為True,在特別情況下很有用:
forloop.last表示當最后一次循環時值為True
forloop。parentioop表示在嵌套循環中表示父級循環的forloop

  

富有魔力的forloop變量只能在循環中得到,當模板解析器到達{% endfor %}時forloop就消失了

如果你的模板context已經包含一個叫forloop的變量,Django會用{% for %}標簽替代它

Django會在for標簽的塊中覆蓋你定義的forloop變量的值

在其他非循環的地方,你的forloop變量仍然可用

1
2
3
4
{%  for  item  in  todo_list %}
         <p>{{ forloop.counter }}: {{ item }}</p>
{% endfor %}
表示循環的次數,它從1開始計數,第一次循環設為1:

{%csrf_token%}:csrf_token標簽

用於生成csrf_token的標簽,用於防治跨站攻擊驗證。注意如果你在view的index里用的是render_to_response方法,不會生效

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

1
2
3
4
5
<form action= "{% url " 路由別名 "%}"  >
           <input type= "text" >
           <input type= "submit" value= "提交" >
           {%csrf_token%}
</form>

{% with %}:用更簡單的變量名替代復雜的變量名

1
2
{% with total=fhjsaldfhjsdfhlasdfhljsdal %} {{ total }} {% endwith %}
基本很少起復雜變量名,一般起變量名都要特變形象

{% verbatim %}: 禁止render渲染

1
2
3
4
5
6
{% verbatim %}
          {{ hello }}
{% endverbatim %
 
 
如果想要{{hello}}在網頁正常顯示出來,則用這個

{% load %}: 加載標簽庫 

靜態文件的引入方式用過

{% load  staticfiles %}

后面引入其他的標簽庫在一一列出

 

自定義filter和simple_tag

我們自定義過濾器和簡單的標簽我們需要

  1. 在app中創建templatetags文件夾(文件夾名字必須的是這個)
  2. 創建任意 .py 文件,如:my_tags.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#!/usr/bin/env python
#-*- coding:utf-8 -*-
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_tag_multi(x,y):
     return  x*y
 
@register.simple_tag
def my_input(id,arg):
     result =  "<input type='text' id='%s' class='%s' />"  %(id,arg)
     return  mark_safe(result)

  

如何調用自定義filter和simple_tag

在使用自定義simple_tag和filter的html文件中導入之前創建的 my_tags.py :{% load my_tags %}

在settings中的INSTALLED_APPS配置當前app,不然django無法找到自定義的simple_tag.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{% load my_tags %}
<!DOCTYPE html>
<html lang= "en" >
<head>
     <meta charset= "UTF-8" >
     <title>Title</title>
</head>
<body>
{{ num|filter_multi:2 }} #24 <br>
 
{{ num|filter_multi: "[22,333,4444]"  }}<br>
 
 
<p>{% simple_tag_multi 2 5 %}  參數不限,但不能放在 if  for 語句中 </p>
{% simple_tag_multi num 5 %}
 
</body>
</html>

  

視圖和路由的配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#路由
from  django.conf.urls import url
from  django.contrib import admin
from  app01 import views
 
urlpatterns = [
     url(r '^admin/' , admin.site.urls),
     url(r '^index/' ,views.index),
]
 
 
#視圖
 
from  django.shortcuts import render,HttpResponse
 
# Create your views here.
def index(request):
 
     num=12
     return   render(request, "index.html" ,locals()) 

注:filter可以用在if等語句后,simple_tag不可以

 

模板引入和繼承

模板引入

 {% include %}該標簽允許在(模板中)包含其它的模板的內容。 標簽的參數是所要包含的模板名稱,可以是一個變量,也可以是用單/雙引號硬編碼的字符串。 每當在多個模板中出現相同的代碼時,就應該考慮是否要使用 {% include %} 來減少重復。

引入方法

1
2
3
4
5
6
{% load staticfiles %}
 
HTML相關內容
 
 
{% include  '要引入的html文件名'  %}

  

模板繼承

常見的 Web 開發問題: 在整個網站中,如何減少共用頁面區域(比如站點導航)所引起的重復和冗余代碼?

解決該問題的傳統做法是使用 服務器端的 includes ,你可以在 HTML 頁面中使用該指令將一個網頁嵌入到另一個中。 事實上, Django 通過剛才講述的 {% include %} 支持了這種方法。 但是用 Django 解決此類問題的首選方法是使用更加優雅的策略—— 模板繼承 。

本質上來說,模板繼承就是先構造一個基礎框架模板,而后在其子模板中對它所包含站點公用部分和定義塊進行重載。

 

如果子板不自定義塊,默認會繼承母板的所有內容(包括模板的css,js),如果子板要修改css或js文件,在相應地方加塊,就可以了

 

例如:

簡單寫一個子板繼承母板

定義母板文件base.html,定義子板要自定義的塊

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<!DOCTYPE html>
<html lang= "en" >
<head>
     <meta charset= "UTF-8" >
     <title>Title</title>
</head>
<body>
 
<H1> HAHA </H1>
 
{% block  content %}
     <h2>子板自定義修改的內容</h2>
 
{% endblock %}
</body>
</html>

  

定義子板文件child.html

1
{% extends  "base.html"  %}

  

子板如果就這么一行代碼,就會繼承母板的所有內容,這{% extends "母板文件" %}必須寫在最首行

 

如果要自定義修改塊

1
2
3
4
{% extends  "base.html"  %}
{% block content %}
     <h2 style= "color: red" >我是子板,修改了母板自定義塊的內容</h2>
{% endblock %}

  

注:

母板

{% block 自定義塊名%}   

 

子板的塊

{% block 母板中相應設置的塊名 }

 

{% block %}  內容 {% endblock %}的標簽也是成對出現

 

使用繼承的注意事項:

  1. 創建 base.html 模板,在其中定義站點的主要外觀感受。 這些都是不常修改甚至從不修改的部分。
  2. 為網站的每個區域創建 base_SECTION.html 模板(例如, base_photos.html 和 base_forum.html )。這些模板對base.html 進行拓展,並包含區域特定的風格與設計。
  3. 為每種類型的頁面創建獨立的模板,例如論壇頁面或者圖片庫。 這些模板拓展相應的區域模板。

 

模板繼承的一些訣竅:

    1. 如果在模板中使用 {% extends %} ,必須保證其為模板中的第一個模板標記。 否則,模板繼承將不起作用。
    2. 一般來說,基礎模板中的 {% block %} 標簽越多越好。 記住,子模板不必定義父模板中所有的代碼塊,因此你可以用合理的缺省值對一些代碼塊進行填充,然后只對子模板所需的代碼塊進行(重)定義。 俗話說,鈎子越多越好。
    3. 如果發覺自己在多個模板之間拷貝代碼,你應該考慮將該代碼段放置到父模板的某個 {% block %} 中。如果你需要訪問父模板中的塊的內容,使用 {{ block.super }}這個標簽吧,這一個魔法變量將會表現出父模板中的內容。 如果只想在上級代碼塊基礎上添加內容,而不是全部重載,該變量就顯得非常有用了。
    4. 不允許在同一個模板中定義多個同名的 {% block %} 。 存在這樣的限制是因為block 標簽的工作方式是雙向的。也就是說,block 標簽不僅挖了一個要填的坑,也定義了在父模板中這個坑所填充的內容。如果模板中出現了兩個相同名稱的 {% block %} 標簽,父模板將無從得知要使用哪個塊的內容。

八 Models

數據庫的配置

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.sqlite3',
        'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    }
}

 

如果我們想要更改數據庫,需要修改如下:

           

注意:

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()

 

4、通過ORM連接數據庫,參考我的另外一篇博文

地址:http://www.cnblogs.com/nulige/p/6484772.html

 語法:

DATABASES = {

    'default': {

        'ENGINE': 'django.db.backends.mysql',

        'NAME': 'Django_ORM',    #你的數據庫名稱

        'USER': 'root',   #你的數據庫用戶名

        'PASSWORD': '123456', #你的數據庫密碼

        'HOST': '', #你的數據庫主機,留空默認為localhost

        'PORT': '3306', #你的數據庫端口
    }}

 

顯示調試信息

在settings.py中加入這段代碼:

#加在任意位置

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

 

ORM(對象關系映射)

SQLAlchemy是Python編程語言下的一款ORM框架,該框架建立在數據庫API之上,使用關系對象映射進行數據庫操作,簡言之便是:將對象轉換成SQL,然后使用數據API執行SQL並獲取執行結果。

  SQLAlchemy本身無法操作數據庫,其必須以來pymsql等第三方插件,Dialect用於和數據API進行交流,根據配置文件的不同調用不同的數據庫API,從而實現對數據庫的操作。

  用於實現面向對象編程語言里不同類型系統的數據之間的轉換,換言之,就是用面向對象的方式去操作數據庫的創建表以及增刪改查等操作。

優點: 1 ORM使得我們的通用數據庫交互變得簡單易行,而且完全不用考慮該死的SQL語句。快速開發,由此而來。

缺點:

1  性能有所犧牲,不過現在的各種ORM框架都在嘗試各種方法,比如緩存,延遲加載登來減輕這個問題。效果很顯著。

2  對於個別復雜查詢,ORM仍然力不從心,為了解決這個問題,ORM一般也支持寫raw sql。

3  通過QuerySet的query屬性查詢對應操作的sql語句

 

模型之間的三種關系:一對一,一對多,多對多。

             一對一:實質就是在主外鍵(author_id就是foreign key)的關系基礎上,給外鍵加了一個UNIQUE=True的屬性;

             一對多:就是主外鍵關系;(foreign key)

             多對多:(ManyToManyField) 自動創建第三張表(當然我們也可以自己創建第三張表:兩個foreign key)

 

 模型常用的字段類型參數

<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參數.

 

Field重要參數

<1> null : 數據庫中字段是否可以為空

    <2> blank: django的 Admin 中添加數據時是否可允許空值

    <3> default:設定缺省值

    <4> editable:如果為假,admin模式下將不能改寫。缺省為真

    <5> primary_key:設置主鍵,如果沒有設置django創建表時會自動加上:
        id = meta.AutoField('ID', primary_key=True)
        primary_key=True implies blank=False, null=False and unique=True. Only one
        primary key is allowed on an object.

    <6> unique:數據唯一

    <7> verbose_name  Admin中字段的顯示名稱

    <8> validator_list:有效性檢查。非有效產生 django.core.validators.ValidationError 錯誤


    <9> db_column,db_index 如果為真將為此字段創建索引

    <10>choices:一個用來選擇值的2維元組。第一個值是實際存儲的值,第二個用來方便進行選擇。
                如SEX_CHOICES= (( ‘F’,'Female’),(‘M’,'Male’),)
                gender = models.CharField(max_length=2,choices = SEX_CHOICES)

 

表的操作

表記錄的添加

方式一:
b=Book(name="python基礎",price=99,author="yuan",pub_date="2017-12-12")
b.save()

方式二:
Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")

表記錄的修改

方式一:
b=Book.objects.get(author="oldboy")
b.price=120
b.save()

方式二:
Book.objects.filter(author="yuan").update(price=999)

表記錄的刪除

Book.objects.filter(author="oldboy").delete()

 

表記錄的查詢(filter,value)

查詢API

# 查詢相關API:

#  <1>filter(**kwargs):      它包含了與所給篩選條件相匹配的對象

#  <2>all():                 查詢所有結果

#  <3>get(**kwargs):         返回與所給篩選條件相匹配的對象,返回結果有且只有一個,如果符合篩選條件的對象超過一個或者沒有都會拋出錯誤。

#-----------下面的方法都是對查詢的結果再進行處理:比如 objects.filter.values()--------

#  <4>values(*field):        返回一個ValueQuerySet——一個特殊的QuerySet,運行后得到的並不是一系列 model的實例化對象,而是一個可迭代的字典序列
                                     
#  <5>exclude(**kwargs):     它包含了與所給篩選條件不匹配的對象

#  <6>order_by(*field):      對查詢結果排序

#  <7>reverse():             對查詢結果反向排序

#  <8>distinct():            從返回結果中剔除重復紀錄

#  <9>values_list(*field):   它與values()非常相似,它返回的是一個元組序列,values返回的是一個字典序列

#  <10>count():              返回數據庫中匹配查詢(QuerySet)的對象數量。

# <11>first():               返回第一條記錄

# <12>last():                返回最后一條記錄

#  <13>exists():             如果QuerySet包含數據,就返回True,否則返回False。

補充:

#擴展查詢,有時候DJANGO的查詢API不能方便的設置查詢條件,提供了另外的擴展查詢方法extra:
#extra(select=None, where=None, params=None, tables=None,order_by=None, select_params=None

(1)  Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
(2)  Blog.objects.extra(
        select=SortedDict([('a', '%s'), ('b', '%s')]),
        select_params=('one', 'two'))

(3)  q = Entry.objects.extra(select={'is_recent': "pub_date > '2006-01-01'"})
     q = q.extra(order_by = ['-is_recent'])

(4)  Entry.objects.extra(where=['headline=%s'], params=['Lennon'])  

 

惰性機制:

所謂惰性機制:Publisher.objects.all()或者.filter()等都只是返回了一個QuerySet(查詢結果集對象),它並不會馬上執行sql,而是當調用QuerySet的時候才執行。

 

QuerySet特點:

       <1>  可迭代的

       <2>  可切片

#objs=models.Book.objects.all()#[obj1,obj2,ob3...]

    #QuerySet:   可迭代

    # for obj in objs:#每一obj就是一個行對象
    #     print("obj:",obj)
    # QuerySet:  可切片

    # print(objs[1])
    # print(objs[1:4])
    # print(objs[::-1])

 

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,可能會造成額外的數據庫查詢。

 

對象查詢,單表條件查詢,多表條件關聯查詢

#--------------------對象形式的查找--------------------------
    # 正向查找
    ret1=models.Book.objects.first()
    print(ret1.title)
    print(ret1.price)
    print(ret1.publisher)
    print(ret1.publisher.name)  #因為一對多的關系所以ret1.publisher是一個對象,而不是一個queryset集合

    # 反向查找
    ret2=models.Publish.objects.last()
    print(ret2.name)
    print(ret2.city)
    #如何拿到與它綁定的Book對象呢?
    print(ret2.book_set.all()) #ret2.book_set是一個queryset集合

#---------------了不起的雙下划線(__)之單表條件查詢----------------

#    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")
#    models.Tb1.objects.filter(name__icontains="ven") # icontains大小寫不敏感
#
#    models.Tb1.objects.filter(id__range=[1, 2])   # 范圍bettwen and
#
#    startswith,istartswith, endswith, iendswith,

#----------------了不起的雙下划線(__)之多表條件關聯查詢---------------

# 正向查找(條件)

#     ret3=models.Book.objects.filter(title='Python').values('id')
#     print(ret3)#[{'id': 1}]

      #正向查找(條件)之一對多

      ret4=models.Book.objects.filter(title='Python').values('publisher__city')
      print(ret4)  #[{'publisher__city': '北京'}]

      #正向查找(條件)之多對多
      ret5=models.Book.objects.filter(title='Python').values('author__name')
      print(ret5)
      ret6=models.Book.objects.filter(author__name="alex").values('title')
      print(ret6)

      #注意
      #正向查找的publisher__city或者author__name中的publisher,author是book表中綁定的字段
      #一對多和多對多在這里用法沒區別

# 反向查找(條件)

    #反向查找之一對多:
    ret8=models.Publisher.objects.filter(book__title='Python').values('name')
    print(ret8)#[{'name': '人大出版社'}]  注意,book__title中的book就是Publisher的關聯表名

    ret9=models.Publisher.objects.filter(book__title='Python').values('book__authors')
    print(ret9)#[{'book__authors': 1}, {'book__authors': 2}]

    #反向查找之多對多:
    ret10=models.Author.objects.filter(book__title='Python').values('name')
    print(ret10)#[{'name': 'alex'}, {'name': 'alvin'}]

    #注意
    #正向查找的book__title中的book是表名Book
    #一對多和多對多在這里用法沒區別

注意:條件查詢即與對象查詢對應,是指在filter,values等方法中的通過__來明確查詢條件。

 

綜合應用示例:

Diango_ORM--->urls.py

from django.conf.urls import url
from django.contrib import admin

#導入相關模塊
from app01 import views


#配置路由分發
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^update/', views.update),
    url(r'^delete/', views.delete),

]

settings.py

"""
Django settings for Django_ORM project.

Generated by 'django-admin startproject' using Django 1.10.5.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))


# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'i464n)l3a$wqvpk9t7lol-7jjg9bb-()v6go0hwgka7!=9+pl%'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []


# Application definition

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

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'Django_ORM.urls'

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',
            ],
        },
    },
]

WSGI_APPLICATION = 'Django_ORM.wsgi.application'


# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

#連接數據庫
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'django_orm', 'USER': 'root', 'PASSWORD': 'oldboy123', 'HOST': '', 'PORT': '3306', } }
# Password validation # https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators AUTH_PASSWORD_VALIDATORS = [ { 'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator', }, { 'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator', }, { 'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator', }, { 'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator', }, ] # Internationalization # https://docs.djangoproject.com/en/1.10/topics/i18n/ LANGUAGE_CODE = 'en-us' TIME_ZONE = 'UTC' USE_I18N = True USE_L10N = True USE_TZ = True # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/1.10/howto/static-files/ STATIC_URL = '/static/' #顯示調試信息 LOGGING = { 'version': 1, 'disable_existing_loggers': False, 'handlers': { 'console':{ 'level':'DEBUG', 'class':'logging.StreamHandler', }, }, 'loggers': { 'django.db.backends': { 'handlers': ['console'], 'propagate': True, 'level':'DEBUG', }, } }

app01--->models.py

from django.db import models

# Create your models here.


# class Book(models.Model):
#     name=models.CharField(max_length=20)
#     price=models.IntegerField()
#     pub_date=models.DateField()


#創建表
class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    author=models.CharField(max_length=32,null=False)

templates--->index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }
        .head{
            line-height: 40px;
            background-color: green;
            color: white;
            text-align: center;

        }

    </style>
</head>
<body>

<div class="outer">
    <div class="head">標題</div>
    <div class="content">
        <a href="/addbook/">添加書籍</a>
        <a href="/update/">修改書籍</a>
        <a href="/delete/">刪除書籍</a>
    </div>
</div>

</body>
</html>
View Code

views.py

from django.shortcuts import render,HttpResponse

# Create your views here.
from app01.models import *

def index(request):

    return render(request,"index.html")

def addbook(request):

    # b=Book(name="python基礎",price=99,author="yuan",pub_date="2017-12-12")
    # b.save()
    Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")
    #Book.objects.create(**dic)

    return HttpResponse("添加成功")


def update(request):

    Book.objects.filter(author="yuan").update(price=999)

    # b=Book.objects.get(author="oldboy")
    # b.price=120
    # b.save()
    # print(b)#<QuerySet [<Book: Book object>]>
    # print(type(b))

    return HttpResponse("修改成功!")


def delete(req):

    Book.objects.filter(author="oldboy").delete()

    return HttpResponse("success")

def select(req):
    book_list=Book.objects.all()
    print(book_list)
    print(book_list[0])#Book object

book_list = Book.objects.filter(id=2)
book_list
= Book.objects.all()[::2] book_list = Book.objects.all()[::-1] book_list = Book.objects.first() book_list = Book.objects.last() book_list = Book.objects.get(id=2)#只能取出一條記錄時才不報錯 ret1=Book.objects.filter(author="oldboy").values("name") ret2=Book.objects.filter(author="yuan").values_list("name","price") book_list=Book.objects.exclude(author="yuan").values("name","price") print(ret1) print(ret2) book_list= Book.objects.all().values("name").distinct() book_count= Book.objects.all().values("name").distinct().count() print(book_count) #萬能的 __ book_list=Book.objects.filter(price__gt=50).values("name","price") book_list=Book.objects.filter(name__contains="P").values_list("name","price") return render(req,"index.html",{"book_list":book_list})

 增加改查的時候,刷新網頁,寫入數據庫中

單表操作總結:

單表操作

        表記錄的添加
             
        方式一:
            Book()
            b=Book(name="python基礎",price=99,author="yuan",pub_date="2017-12-12")
            b.save()
            方式二:
            Book.objects.create()
            Book.objects.create(name="老男孩linux",price=78,author="oldboy",pub_date="2016-12-12")


        表記錄的修改
            方式一:
            
            b=Book.objects.get(author="oldboy")
            b.price=120
            b.save()
            
            方式二:(推薦方法)
            #update是QuerySet
            Book.objects.filter(author="yuan").update(price=999)
         
        表記錄的刪除:
            Book.objects.filter(author="oldboy").delete()
            
        表記錄的查詢(重點):
        
                book_list = Book.objects.filter(id=2)
                book_list=Book.objects.exclude(author="yuan").values("name","price")   


                book_list=Book.objects.all()
                book_list = Book.objects.all()[::2]
                book_list = Book.objects.all()[::-1]
           
                #first,last,get取到的是一個實例對象,並非一個QuerySet的集合對象
                book_list = Book.objects.first()
                book_list = Book.objects.last()  
                book_list = Book.objects.get(id=2)#只能取出一條記錄時才不報錯

                #返回字典的類型記錄值
                ret1=Book.objects.filter(author="oldboy").values("name")

        #集合里面顯示元組的方式返回值
                ret2=Book.objects.filter(author="yuan").values_list("name","price")
            
        #distinct方法去重
                book_list= Book.objects.all().values("name").distinct()
                book_count= Book.objects.all().values("name").distinct().count()
               
            
                模糊匹配查詢 使用:雙下划線__
                book_list=Book.objects.filter(name__icontains="P").values_list("name","price")
                
        #>5的記錄篩選出來
        book_list=Book.objects.filter(id__gt=5).values_list("name","price")
                
 
      多表操作(一對多):
               #添加記錄
               #publish_id=2
               Book.objects.create(name="linux運維",price=77,pub_date="2017-12-12",publish_id=2)
               

               #publish=object
               Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)
               
               #查詢記錄(通過對象)
                     正向查詢:
                     book_obj=Book.objects.get(name="python")   
                     pub_obj=book_obj.publish----》書籍對象對應的出版社對象
                     pub_obj.name

                     反向查詢:
                     pub_obj = Publish.objects.filter(name="人民出版社")[0]
                     pub_obj.book_set.all().values("name","price")

    #查詢記錄 (filter values  雙下划線__)
        #人民出版社出版過的書籍與價格
        ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
        
        #python這本書出版社的名字
        ret2=Publish.objects.filter(book_name=“python”).values("name")

        #python這本書出版社的名字
        ret3=Book.object.filter(name="python").values("publish__name")

        #北京的出版社出版書的名字
        ret4=Book.objects.filter(publish__city="北京").values("name")

        #2017年上半年出版過書的出版社的名字
        ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("name")

 

示例:

views.py

from django.shortcuts import render,HttpResponse
from django.db.models import Avg,Min,Sum,Max,Count
from django.db.models import Q,F
# Create your views here.
from app01.models import *

def index(request):


    return render(request,"index.html")

def addbook(request):

    # Book.objects.create(name="linux運維",price=77,pub_date="2017-12-12",publish_id=2)

    #publish_obj=Publish.objects.filter(name="人民出版社")[0]
    #Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)

    # book_obj=Book.objects.get(name="python")
    # print(book_obj.name)
    # print(book_obj.pub_date)
    #
    # #一對多:book_obj.publish--------一定是一個對象
    # print(book_obj.publish.name)
    # print(book_obj.publish.city)
    # print(type(book_obj.publish))


    #查詢人民出版社出過的所有書籍名字和價格
    #方式一:
    # pub_obj=Publish.objects.filter(name="人民出版社")[0]
    # ret=Book.objects.filter(publish=pub_obj).values("name","price")
    # print(ret)

    #方式二
    # pub_obj = Publish.objects.filter(name="人民出版社")[0]
    # print(pub_obj.book_set.all().values("name","price"))
    #print(type(pub_obj.book_set.all()))

    #方式三
    # ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
    # print(ret)
    #
    # python這本書出版社的名字
    # ret2=Publish.objects.filter(book__name="python").values("name")
    # print(ret2)
    # ret3=Book.objects.filter(name="python").values("publish__name")
    # print(ret3)
    #
    # ret4=Book.objects.filter(publish__city="北京").values("name")
    # print(ret4)
    #
    # ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
    # print(ret5)

    #通過對象的方式綁定關系


    # book_obj=Book.objects.get(id=3)
    # print(book_obj.authors.all())
    # print(type(book_obj.authors.all()))
    #
    # author_obj=Author.objects.get(id=2)
    # print(author_obj.book_set.all())

    # book_obj=Book.objects.get(id=3)
    # author_objs=Author.objects.all()
    # #book_obj.authors.add(*author_objs)
    # # book_obj.authors.remove(*author_objs)
    # book_obj.authors.remove(4)


    #創建第三張表
    # Book_Author.objects.create(book_id=2,author_id=2)
    #
    # obj=Book.objects.get(id=2)
    # print(obj.book_author_set.all()[0].author)

    #alex出過的書籍名稱及價格

    # ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
    # print(ret)

    # ret2=Book.objects.filter(authors__name="alex").values("name","price","authors__name")
    # print(ret2)

    # ret=Book.objects.all().aggregate(Avg("price"))
    # ret=Book.objects.all().aggregate(Sum("price"))
    # ret=Book.objects.filter(authors__name="alex").aggregate(alex_money=Sum("price"))
    # ret=Book.objects.filter(authors__name="alex").aggregate(Count("price"))
    # print(ret)

    # ret=Book.objects.values("authors__name").annotate(Sum("price"))
    # print(ret)

    # ret=Publish.objects.values("name").annotate(abc=Min("book__price"))
    # print(ret)


    # b=Book.objects.get(name="GO",price=77)
    # print(b)

    #Book.objects.all().update(price=F("price")+10)

    # ret=Book.objects.filter(Q(name__contains="G"))
    # print(ret)

    # ret=Book.objects.filter(Q(name="GO"),price=87)
    # print(ret)

    #ret=Book.objects.filter(price=200)

    # for i in ret:
    #     print(i.price)
    #
    # Book.objects.all().update(price=200)
    # ret = Book.objects.filter(price=100)
    # for i in ret:
    #     print(i.price)


    # if ret.exists():
    #     print("ok")

    # ret=ret.iterator()
    # print(ret)
    #
    # for i in ret:
    #     print(i.name)
    #
    # for i in ret:
    #     print(i.name)


    return HttpResponse("添加成功")

def update():pass
def delete():pass
def select():pass

models.py

from django.db import models

# Create your models here.


class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")

    def __str__(self):
        return self.name

class Publish(models.Model):

    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

    def __str__(self):
        return self.name


# class Book_Author(models.Model):
#     book=models.ForeignKey("Book")
#     author=models.ForeignKey("Author")


class Author(models.Model):

    name=models.CharField(max_length=32)
    age=models.IntegerField(default=20)

    def __str__(self):
        return self.name

urls.py

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }
        .head{
            line-height: 40px;
            background-color: green;
            color: white;
            text-align: center;

        }

    </style>
</head>
<body>

<div class="outer">
    <div class="head">標題</div>
    <div class="content">
        <a href="/addbook/">添加書籍</a>
        <a href="/update/">修改書籍</a>
        <a href="/delete/">刪除書籍</a>
        <a href="/select/">查詢書籍</a>
    </div>
    <hr>
    <div class="queryResult">
         {% for book in book_list %}
         <div>
              <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
         </div>
         {% endfor %}
    </div>
</div>

</body>
</html>

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }
        .head{
            line-height: 40px;
            background-color: green;
            color: white;
            text-align: center;

        }

    </style>
</head>
<body>

<div class="outer">
    <div class="head">標題</div>
    <div class="content">
        <a href="/addbook/">添加書籍</a>
        <a href="/update/">修改書籍</a>
        <a href="/delete/">刪除書籍</a>
        <a href="/select/">查詢書籍</a>
    </div>
    <hr>
    <div class="queryResult">
         {% for book in book_list %}
         <div>
              <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
         </div>
         {% endfor %}
    </div>
</div>

</body>
</html>

 

 

聚合查詢和分組查詢

示例:

models.py (建表語句)

from django.db import models

# Create your models here.


class Book(models.Model):
    name=models.CharField(max_length=20)
    price=models.IntegerField()
    pub_date=models.DateField()
    publish=models.ForeignKey("Publish")
    authors=models.ManyToManyField("Author")

    def __str__(self):
        return self.name

class Publish(models.Model):

    name=models.CharField(max_length=32)
    city=models.CharField(max_length=32)

    def __str__(self):
        return self.name


# class Book_Author(models.Model):
#     book=models.ForeignKey("Book")
#     author=models.ForeignKey("Author")


class Author(models.Model):

    name=models.CharField(max_length=32)
    age=models.IntegerField(default=20)

    def __str__(self):
        return self.name

views.py

from django.shortcuts import render,HttpResponse
from django.db.models import Avg,Min,Sum,Max,Count

# Create your views here.
from app01.models import *

def index(request):


    return render(request,"index.html")

def addbook(request):

    # Book.objects.create(name="linux運維",price=77,pub_date="2017-12-12",publish_id=2)

    #publish_obj=Publish.objects.filter(name="人民出版社")[0]
    #Book.objects.create(name="GO",price=23,pub_date="2017-05-12",publish=publish_obj)

    # book_obj=Book.objects.get(name="python")
    # print(book_obj.name)
    # print(book_obj.pub_date)
    #
    # #一對多:book_obj.publish--------一定是一個對象
    # print(book_obj.publish.name)
    # print(book_obj.publish.city)
    # print(type(book_obj.publish))


    #查詢人民出版社出過的所有書籍名字和價格
    #方式一:
    # pub_obj=Publish.objects.filter(name="人民出版社")[0]
    # ret=Book.objects.filter(publish=pub_obj).values("name","price")
    # print(ret)

    #方式二
    # pub_obj = Publish.objects.filter(name="人民出版社")[0]
    # print(pub_obj.book_set.all().values("name","price"))
    #print(type(pub_obj.book_set.all()))

    #方式三
    # ret=Book.objects.filter(publish__name="人民出版社").values("name","price")
    # print(ret)
    #
    # python這本書出版社的名字
    # ret2=Publish.objects.filter(book__name="python").values("name")
    # print(ret2)
    # ret3=Book.objects.filter(name="python").values("publish__name")
    # print(ret3)
    #
    # ret4=Book.objects.filter(publish__city="北京").values("name")
    # print(ret4)
    #
    # ret5=Book.objects.filter(pub_date__lt="2017-07-01",pub_date__gt="2017-01-01").values("publish__name")
    # print(ret5)

    #通過對象的方式綁定關系


    # book_obj=Book.objects.get(id=3)
    # print(book_obj.authors.all())
    # print(type(book_obj.authors.all()))
    #
    # author_obj=Author.objects.get(id=2)
    # print(author_obj.book_set.all())


    # book_obj=Book.objects.get(id=3)
    # author_objs=Author.objects.all()
    # #book_obj.authors.add(*author_objs)
    # # book_obj.authors.remove(*author_objs)
    # book_obj.authors.remove(4)

    #創建第三張表
    # Book_Author.objects.create(book_id=2,author_id=2)
    #
    # obj=Book.objects.get(id=2)
    # print(obj.book_author_set.all()[0].author)

    #alex出過的書籍名稱及價格

    # ret=Book.objects.filter(book_author__author__name="alex").values("name","price")
    # print(ret)

    # ret2=Book.objects.filter(authors__name="alex").values("name","price","authors__name")
    # print(ret2)

    # ret=Book.objects.all().aggregate(Avg("price"))
    # ret=Book.objects.all().aggregate(Sum("price"))
    # ret=Book.objects.filter(authors__name="alex").aggregate(alex_money=Sum("price"))
    # ret=Book.objects.filter(authors__name="alex").aggregate(Count("price"))
    # print(ret)

    # ret=Book.objects.values("authors__name").annotate(Sum("price"))
    # print(ret)

    # ret=Publish.objects.values("name").annotate(abc=Min("book__price"))
    # print(ret)

    return HttpResponse("添加成功")

def update():pass
def delete():pass
def select():pass

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <script src="jquery-3.1.1.js"></script>
    <title>Title</title>

    <style>
        * {
            margin: 0;
            padding: 0
        }
        .head{
            line-height: 40px;
            background-color: green;
            color: white;
            text-align: center;

        }

    </style>
</head>
<body>

<div class="outer">
    <div class="head">標題</div>
    <div class="content">
        <a href="/addbook/">添加書籍</a>
        <a href="/update/">修改書籍</a>
        <a href="/delete/">刪除書籍</a>
        <a href="/select/">查詢書籍</a>
    </div>
    <hr>
    <div class="queryResult">
         {% for book in book_list %}
         <div>
              <p>{{ book.name }} {{ book.author }} {{ book.price }}</p>
         </div>
         {% endfor %}
    </div>
</div>

</body>
</html>

urls.py

"""ORM_multi URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.10/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
from django.conf.urls import url
from django.contrib import admin

from app01 import views

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^index/', views.index),
    url(r'^addbook/', views.addbook),
    url(r'^update/', views.update),
    url(r'^delete/', views.delete),
    url(r'^select/', views.delete),
]

  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM