Django是一個web框架,python編寫的。
MTV模式
Django的MTV模式本質上和MVC是一樣的,也是為了各元件間保持鬆耦合關係,只是定義上有些許不同 -M代表模型(Model ):負責業務物件和資料庫的關係對映(ORM) -T代表模板(Template):負責如何把頁面展示給使用者(html) -V代表檢視(View ) :負責業務邏輯,並在適當時候呼叫Model和Template
client(客戶端)-->請求(url)--> server(伺服器的urlconf)-->views(檢視,相當於函式,客戶機訪問url,每次的訪問都有相應的函式對應)-->model(資料庫,增刪改查)-->views(修改資料庫後再返回資訊給檢視,資料互動)-->Template(web頁面)-->client
一、建立python的虛擬環境
(一)配置pip檔案
(django_env) [root@django ~]# cat .pip/pip.conf [global] index-url = http://pypi.douban.com/simple [install] trusted-host=pypi.douban.com
(二)虛擬環境安裝
mkdir pyproject cd pyproject/ python3 -m venv django_env #在當前目錄建立虛擬環境(Django_env 名字可以變) source django_env/bin/activate #啟用虛擬環境 pip install django==1.11.6 #在虛擬環境中安裝Django==1.11.6 (django_env) [root@localhost pyproject]# python #驗證 Python 3.6.4 (default, Apr 27 2018, 08:26:23) [GCC 4.8.5 20150623 (Red Hat 4.8.5-16)] on linux Type "help", "copyright", "credits" or "license" for more information. >>> import django >>> django.__version__ '1.11.6'
二 、Django專案建立
django-admin startproject mysite #建立專案 (django_env) [root@localhost pyproject]# cd mysite #Django的目錄結構 (django_env) [root@localhost mysite]# tree . ├── manage.py └── mysite ├── __init__.py ├── settings.py ├── urls.py └── wsgi.py
mysite:專案的容器。
manage.py:一個使用的命令列工具,可讓你以各種方式與該django專案進行互動(專案的管理目錄)
mysite/__init__.py:一個空檔案,告訴python該目錄是一個python包。(專案的初始化檔案)
mysite/settings.py:該django專案的設定/配置。(專案的配置檔案)
mysite/urls.py:該django專案的URL宣告;一份由django驅動的網站“目錄”。(專案的路由檔案)
mysite/wsgi.py:一個WSGI相容的Web伺服器的入口,以便執行你的專案。(將網站部署到web伺服器時使用的檔案)
python manage.py runserver 0.0.0.0:8000 #執行專案
127.0.0.1:8000 #檢視專案
三、Django配置
(一)建立資料庫
CREATE DATABASE django DEFAULT CHARSET 'UTF8';
(二)配置 setting.py(配置完成後頁面變成中文)
ALLOWED_HOSTS = ['*'] # 允許所有的客戶端訪問 DATABASES = { 'default': {'ENGINE': 'django.db.backends.mysql', 'NAME': 'django', 'USER': 'root', 'PASSWORD': '資料庫root密碼', 'HOST': '127.0.0.1', 'PORT': '3306', } } LANGUAGE_CODE ='zh-hans' #中文 TIME_ZONE ='Asia/Shanghai' USE_TZ = False
(三)配置__init__.py(要先安裝pymysql模組)
import pymysql pymysql.install_as_MySQLdb()
執行檢視
# 重新執行測試伺服器,監聽在0.0.0.0的80埠。注意:如果不是root,不能監聽1024以下埠 [root@room8pc16 mysite]# python manage.py runserver 0:80
(四)生成資料
[root@room8pc16 mysite]#python manage.py makemigrations #會生成一些相應的sql語句 [root@room8pc16 mysite]# python manage.py migrate #生成表
(五)建立管理員
[root@room8pc16 mysite]# python manage.py createsuperuser #密碼要求複雜度和長度
檢視頁面
四、使用Django建立應用
(一)建立應用(對應的一個個的功能模組,使用一個投票為例子)
[root@room8pc16 mysite]# python manage.py startapp polls #建立應用(可以整合到任何的一個專案中)
(二)在settings配置檔案中宣告應用(把應用整合在專案中)
INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'polls' #新增的應用 ]
(三)授權,把應用的url交給投票應用處理,都在專案下的urls.py的這個檔案就會特別大
polls/urls.py from django.conf.urls import url, include from django.contrib import adminurlpatterns = [ # 正則匹配時,從http://x.x.x.x/後面開始算起 # 正則匹配時,從http://x.x.x.x/polls url(r'^admin/', admin.site.urls), url(r'^polls/', include('polls.urls')), #其中r意思真實字串相當於shell中的單引號 ]
在polls目錄下沒有urls.py檔案就建立一個
[root@django polls]# touch urls.py vim polls/urls.py
from django.conf.urls import url
urlpatterns = [
]
五、建立投票首頁
(一)編寫url
from django.conf.urls import url,include from django.contrib import admin
from . import views #.是當前目錄的意思(和urls.py同級,也可以from polls import views) urlpatterns = [ url(r'^$', views.index,name='index'), #匹配到空白,都用views.index函式進行響應,那麼為函式名字 ]
(二)編寫views檢視函式
def index(request): # 使用者發起的請求將會作為第一個引數傳給函式 (客戶端發起請求時可能是 get,put,post,攜帶的引數或者資料等等 都會作為第一個引數 傳給request) # 所以函式至少要定義一個引數來接收使用者的請求 # render負責找尋模板檔案傳送給使用者 return render(request, 'index.html')
(三)編寫頁面(確定templates模板的位置)
TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [os.path.join(BASE_DIR, 'templates')], #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', ],
index.html
<html lang="en"> <head> <meta charset="UTF-8"> <title>polls</title> </head> <body> <div class="container"> <h1>polls</h1> </div> </body> </html>
六、編寫問題頁面
(一)編寫urls.py
urlpatterns = [ url(r'^$', views.index,name='index'), url(r'(\d+)/$', views.a,name='a'), #\d+為匹配數字(+為至少匹配到一個數字) # ()為傳參(把匹配到的數字作為檢視函式a的引數 ) ]
(二)編寫views.py
from django.shortcuts import render def index(request): return render(request,'index.html') def a(request,id): #在urls.py中匹配到的引數的值用變數id接受 return render(request,'a.html',{'id':id}) # 字典的內容將會成為模板檔案的變數,字典的key是變數名,value是變數值(字典的值成為html的引數)
(三)編寫a.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <div class="container"> <h1>{{id}}question</h1> #在views.py檔案中接受的引數,用{{}}表示 </div> </body> </html>
七、編寫結果頁面
(一)編寫urls.py
urlpatterns = [ url(r'^$', views.index,name='index'), #r‘’單引號裡面什麼也不填寫那麼就是匹配空串(在任何字元之間都有空串),不管在ip/polls/後面填寫什麼都將匹配首頁 url(r'(\d+)/$', views.a,name='a'), url(r'(\d+)/result/$', views.result,name='result') ]
(二)編寫views.py
from django.shortcuts import render # Create your views here. def index(request): return render(request,'index.html') def a(request,id): return render(request,'a.html',{'id':id}) def result(request,id): return render(request,'result.html',{'id':id})
(三)編寫result.html
<meta charset="UTF-8"> <title>Title</title> </head> <body> <div> <h1>{{id}}result</h1> </div> </body> </html>
八、model模型
ORM object :物件﹐對應django模型中的class Relationship:關係﹐對應關係型資料庫 Mapping:對映 一個class對應資料庫中的一張表 表中的欄位與class中的類變數對應 資料庫中的資料型別也與django模型中的類對映 表中的每個記錄都與class的例項對應
(一)編寫models.py
from django.db import models # Create your models here. class Question(models.Model): question_text = models.CharField(max_length=200, unique=True) pub_date = models.DateTimeField() #不加Field,沒有時分秒 class Chioce(models.Model): chioce_text = models.CharField(max_length=200, unique=True) votes = models.IntegerField(default=0) question = models.ForeignKey(Question) #如果想要修改欄位名,在配置檔案中修改之後,重新生成表
(二)生成表
python manage.py makemigrations python manage.py migrate
(三)將模型加入到後臺頁面
# polls/admin.py from django.contrib import admin# 在當前目錄下的models模組中匯入模型 from .models import Question, Choice # Register your models here. admin.site.register(Question) admin.site.register(Choice)
解決辦法
class Question(models.Model): question_text = models.CharField(max_length=200, unique=True) pub_date = models.DateTimeField() def __str__(self): return 'question:%s' % self.question_text class Chioce(models.Model): chioce_text = models.CharField(max_length=200, unique=True) votes = models.IntegerField(default=0) question = models.ForeignKey(Question) def __str__(self): return '%s:%s' % return '%s:%s' % (self.question,self.chioce_text)
九、Django API(首頁)
(一)在views檔案中把問題取出來傳給html
# polls/views.py from django.shortcuts import render from .models import Question def index(request): questions = Question.objects.order_by('-pub_date') returnrender(request, 'index.html', {'questions': questions})
(二)編輯index.html
<!DOCTYPEhtml> <htmllang="en"> <head> <metacharset="UTF-8"> <title>投票首頁</title> </head> <body> <div class="container"> <div class="content"> <h1>投票首頁</h1> <ol> {% for question in questions %} <li> <a href="{% url 'a' question.id %}" target="_blank">
#question_id是views.py中的\d+這個引數,資料庫中沒有指定主鍵時Django會自動建立主鍵,question_id就是問題的id號 {{ question.question_text }}</a> {{ question.pub_date }} </li> {%endfor%} </ol> </div> </div> </body> </html>
(三)可以新增輪播圖
<div class="container"> <div id="linux-carousel" class="carousel slide"> <ol class="carousel-indicators"> <li class="active" data-target="#linux-carousel" data-slide-to="0"></li> #輪播圖下面的小圓點 <li data-target="#linux-carousel" data-slide-to="1"></li> <li data-target="#linux-carousel" data-slide-to="2"></li> </ol> <div class="carousel-inner"> <div class="item active"> <a href="http://www.sogou.com" target="_blank"> <img src="{% static 'imgs/first.jpg' %}"> </a> </div> <div class="item"> <img src="{% static 'imgs/second.jpg' %}"> </div> <div class="item"> <img src="{% static 'imgs/third.jpg' %}"> </div> </div> <a href="#linux-carousel" data-slide="prev" class="carousel-control left"> <span class="glyphicon glyphicon-chevron-left"></span> #向左翻 製作投票詳情頁 </a> <a href="#linux-carousel" data-slide="next" class="carousel-control right"> <span class="glyphicon glyphicon-chevron-right"></span> #向右翻 </a> </div> <script src="{% static 'js/jquery.min.js' %}"></script> #要有JS程式碼才能實現輪播圖 <script src="{% static 'js/bootstrap.min.js' %}"></script> <script type="text/javascript">
(四)模板繼承(為了避免一些網頁的重複程式碼)
1.複製index.html一本命令為bak.html
# 在basic.html中,將個性(不相同)內容用block替代 {% load static %} <!DOCTYPE html> <html lang="en"> <head><meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <meta name="viewport" content="width=device-width, initial-scale=1"> <link rel="stylesheet" href="{% static 'css/bootstrap.min.css' %}"> </head> <body> <div class="container"> <div id="linux-carousel" class="carousel slide"> <ol class="carousel-indicators"> <li class="active" data-target="#linux-carousel" data-slide-to="0"></li> <li data-target="#linux-carousel" data-slide-to="1"></li> <li data-target="#linux-carousel" data-slide-to="2"></li> </ol> <div class="carousel-inner"> <div class="item active"> <a href="http://www.sogou.com" target="_blank"> <img src="{% static 'imgs/first.jpg' %}"> #圖片放在polls下static目錄的imgs目錄中 </a> </div> <div class="item"> <img src="{% static 'imgs/second.jpg' %}"> </div> <div class="item"> <img src="{% static 'imgs/third.jpg' %}"> </div> </div> <a href="#linux-carousel" data-slide="prev" class="carousel-control left"> <span class="glyphicon glyphicon-chevron-left"></span> 製作投票詳情頁 </a> <a href="#linux-carousel" data-slide="next" class="carousel-control right"> <span class="glyphicon glyphicon-chevron-right"></span> </a> </div> {% block content %}{% endblock %} <script src="{% static 'js/jquery.min.js' %}"></script> <script src="{% static 'js/bootstrap.min.js' %}"></script> <script type="text/javascript"></script> </body> </html>
2.index.html
# 修改index.html,把共性內容刪除,個性內容寫到對應的block中 {% extends 'bak.html' %} #繼承 {% load static %} {% block title %}投票首頁{% endblock %} {% block content %} <div class="content h4"> <h1 class="text-center text-warning">投票首頁</h1> <ol style="margin: 20px 0"> {% for question in questions %} <li><a href="{% url 'detail' question.id %}" target="_blank"> {{ question.question_text }} </a> {{ question.pub_date }} </li> {% endfor %} </ol> </div> {% endblock %}
十、製作a.html(第二個頁面)
(一)編輯views.py
from django.shortcuts import render from .models import Question, Chioce # Create your views here. def index(request): d = Question.objects.order_by('-pub_date') return render(request,'index.html',{'d':d}) def a(request,question_id): c = Question.objects.get(id=question_id) return render(request,'a.html',{'id':c}) def result(request,id): return render(request,'result.html',{'id':id})
(二)編輯a.html(取出選項)
{% extends 'bak.html'%} {% load static %} {% block title%}polls{%endblock%} {% block content%} <div class="container"> <h1>{{ id.id }}</h1> </div> <div class="content h4 text-warning" > <h1 class="text-center">chioce</h1> <h2>{{ id }}</h2> <form action="">
{% csrf_token %} #安全選項 {% for i in id.chioce_set.all %} <div class="radio"> <label > <input type="radio" name="chioce_id" value="{{ chioce_id }}"> {{ i.chioce_text }} </label> </div> {% endfor %} </form> </div> <div class="group"> <input class="btn btn-primary" tpye="submit" value="submit"> </div> {%endblock%}
十一、實現投票功能(資料庫新增刪除)
實現資料庫的增刪改查。執行函式對model模型的操作(url-->views-->model)
(一)配置urls.py
from django.conf.urls import url,include from django.contrib import admin from . import views urlpatterns = [ url(r'^$', views.index,name='index'), url(r'(\d+)/$', views.a,name='a'), url(r'(\d+)/result/$', views.result,name='result'), url(r'(\d+)/vote/$', views.vote,name='vote'), ]
(二)配置views.py
from django.shortcuts import render, redirect from .models import Question, Chioce # Create your views here. def index(request): d = Question.objects.order_by('-pub_date') return render(request,'index.html',{'d':d}) def a(request,question_id): c = Question.objects.get(id=question_id) return render(request,'a.html',{'id':c}) def result(request,id): return render(request,'result.html',{'id':id}) def vote(request,id): d = Question.objects.get(id=id) #取出問題 # 當使用者提交表單時,request.POST是一個字典,裡面記錄了與POST相關的資料 # choice_id是detail.html頁面中單選按鈕的name,值是選項的id(value的值) chioce_id = request.POST.get('chioce_id') #取出name的值 chioce = d.chioce_set.get(id=chioce_id) #取出對用id的項 chioce.votes += 1 chioce.save() # 這裡返回使用的不是render,因為render直接返回頁面,URL不變,也就是http://x.x.x.x/polls/2/vote顯示的是2號問題的投票結果,這是不合理的應該由http://x.x.x.x/polls/2/result/顯示投票結果。所以使用redirect return redirect('result',id)
(三)配置a.html
{% extends 'bak.html'%} {% load static %} {% block title%}polls{%endblock%} {% block content%} <div class="container"> <h1>{{ id.id }}</h1> </div> <div class="content h4 text-warning" > <h1 class="text-center">chioce</h1> <h2>{{ id }}</h2> <form action="{% url 'vote' id.id %}" method="post"> {% csrf_token %} {% for i in id.chioce_set.all %} <div class="radio"> <label > <input type="radio" name="chioce_id" value="{{ i.id }}"> {{ i.chioce_text }} </label> </div> {% endfor %} <div class="form-group"> <input class="btn btn-primary" type="submit" value="submit"> </div> </form> </div> {%endblock%}
十二、配置result.html
(一)views.py
from django.shortcuts import render, redirect from .models import Question, Chioce # Create your views here. def index(request): d = Question.objects.order_by('-pub_date') return render(request,'index.html',{'d':d}) def a(request,question_id): c = Question.objects.get(id=question_id) return render(request,'a.html',{'id':c}) def result(request,id): d = Question.objects.get(id=id) return render(request,'result.html',{'id':d}) def vote(request,id): d = Question.objects.get(id=id) chioce_id = request.POST.get('chioce_id') chioce = d.chioce_set.get(id=chioce_id) chioce.votes += 1 chioce.save() return redirect('result',id)
(二)配置resul.html
{% extends 'bak.html'%} {% load static %} {% block title%}投票結果{%endblock%} {% block content%} <div> <h1 class="text-center">{{ id.id }}投票結果</h1> <table class="table table-striped table-hover"> <thead class="bg-primary"> <tr> <td colspan="2">{{ id.question_text }}</td> </tr> </thead> {% for i in id.chioce_set.all %} <tr> <td>{{ i.chioce_text }}</td> <td >{{ i.votes }}</td> </tr> {%endfor%} </table> </div> {%endblock%}