Django(投票程式)

zsh~發表於2021-01-13

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%}

 

相關文章