1、什麼是web框架css
框架,即framework,特指爲解決一個開放性問題而設計的具備必定約束性的支撐結構,使用框架能夠幫你快速開發特定的系統,簡單地說,就是你用別人搭建好的舞臺來作表演。 對於全部的Web應用,本質上其實就是一個socket服務端,用戶的瀏覽器其實就是一個socket客戶端。html
示例:本身寫一個框架前端
myWeb.pypython
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()
show_time.htmlmysql
<!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>
login.htmljquery
<!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>
index1.htmllinux
<!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>
index2.htmlnginx
<!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>
最簡單的Web應用就是先把HTML用文件保存好,用一個現成的HTTP服務器軟件,接收用戶請求,從文件中讀取HTML,返回。 若是要動態生成HTML,就須要把上述步驟本身來實現。不過,接受HTTP請求、解析HTTP請求、發送HTTP響應都是苦力活,若是咱們本身來寫這些底層代碼,還沒開始寫動態HTML呢,就得花個把月去讀HTTP規範。 正確的作法是底層代碼由專門的服務器軟件實現,咱們用Python專一於生成HTML文檔。由於咱們不但願接觸到TCP鏈接、HTTP原始請求和響應格式,因此,須要一個統一的接口,讓咱們專心用Python編寫Web業務。 這個接口就是WSGI:Web Server Gateway Interface。git
2、MVC和MTV模式web
著名的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 #安裝: 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-admin.py 是Django的一個用於管理任務的命令行工具,manage.py是對django-admin.py的簡單包裝,每個Django Project裏都會有一個mannage.py。
<1> 建立一個django工程 : django-admin.py startproject mysite
當前目錄下會生成mysite的工程,目錄結構以下:
<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 能夠看到詳細的列表,在忘記子名稱的時候特別有用。
<!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})
<!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")
1、概述: #靜態文件交由Web服務器處理,Django自己不處理靜態文件。簡單的處理邏輯以下(以nginx爲例): # URI請求-----> 按照Web服務器裏面的配置規則先處理,以nginx爲例,主要求配置在nginx. #conf裏的location |---------->若是是靜態文件,則由nginx直接處理 |---------->若是不是則交由Django處理,Django根據urls.py裏面的規則進行匹配 # 以上是部署到Web服務器後的處理方式,爲了便於開發,Django提供了在開發環境的對靜態文件的處理機制,方法是這樣: #一、在INSTALLED_APPS裏面加入'django.contrib.staticfiles', #二、在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}), ) # 三、這樣就能夠在開發階段直接使用靜態文件了。 2、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的資料。 3、STATIC_ROOT和STATIC_URL、 STATIC主要指的是如css,js,images這樣文件,在settings裏面能夠配置STATIC_ROOT和STATIC_URL, 配置方式與MEDIA_ROOT是同樣的,可是要注意 #STATIC文件通常保存在如下位置: #一、STATIC_ROOT:在settings裏面設置,通常用來放一些公共的js,css,images等。 #二、app的static文件夾,在每一個app所在文夾都可以創建一個static文件夾,而後當運行collectstatic時, # Django會遍歷INSTALL_APPS裏面全部app的static文件夾,將裏面全部的文件複製到STATIC_ROOT。所以, # 若是你要創建可複用的app,那麼你要將該app所須要的靜態文件放在static文件夾中。 # 也就是說一個項目引用了不少app,那麼這個項目所須要的css,images等靜態文件是分散在各個app的static文件的,比 # 較典型的是admin應用。當你要發佈時,須要將這些分散的static文件收集到一個地方就是STATIC_ROOT。 #三、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.
URL配置(URLconf)就像Django 所支撐網站的目錄。它的本質是URL模式以及要爲該URL模式調用的視圖函數之間的映射表;你就是以這種方式告訴Django,對於這個URL調用這段代碼,對於那個URL調用那段代碼。
urlpatterns = [ url(正則表達式, views視圖函數,參數,別名), ]
參數說明:
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').
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.
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.
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> #######################
#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>
http請求中產生兩個核心對象:
http請求:HttpRequest對象
http響應:HttpResponse對象
所在位置:django.http
以前咱們用到的參數request就是HttpRequest 檢測方法:isinstance(request,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
對於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/,因此當刷新後 # 又得從新登陸.
模板系統的組成:HTML代碼和邏輯控制代碼
邏輯控制代碼能夠理解是django模板語言
變量(使用雙大括號來引用變量):
語法:
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操做差很少
語法格式
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,就替換成設置的默認值,不然就使用原本的值
|
語法格式
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 %}
後面引入其餘的標籤庫在一一列出
咱們自定義過濾器和簡單的標籤咱們須要
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)
|
在使用自定義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> sqlite
django默認使用sqlite的數據庫,默認自帶sqlite的數據庫驅動 , 引擎名稱:django.db.backends.sqlite3
<2> mysql
引擎名稱:django.db.backends.mysql
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()
四、經過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', }, } }
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等於十一、2二、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>
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), ]