筆記6:Django基礎

Django-MVT

(1)查看python版本號:css

python -m django --version

(2) 建立Django項目html

django-admin startproject mysite

(3)測試開發服務器是否成功python

Desktop\bncDjango\mysite>python manage.py runserver

Django 自帶一個用純 Python 寫的輕量級的 Web 服務器。爲了讓你能快速的開發出想要的東西,由於你不須要進行配置生產級別的服務器(好比 Apache)方面的工做,除非你已經準備好投入生產環境了。千萬不要 將這個服務器用於和生產環境相關的任何地方。這個服務器只是爲了開發而設計的。(咱們在 Web 框架方面是專家,在 Web 服務器方面並非。)mysql

(4)建立應用模塊算法

python manage.py startapp polls

Application definition

INSTALLED_APPS = [
'django.contrib.admin', # 管理員站點
'django.contrib.auth', # 認證受權系統
'django.contrib.contenttypes', # 內容類型框架
'django.contrib.sessions', # 會話框架
'django.contrib.messages', # 消息框架
'django.contrib.staticfiles', #管理靜態文件的框架
'polls', # 投票模塊]
sql

(5)polls模型下編輯視圖view數據庫


from django.shortcuts import render
django

Create your views here.

from django.http import HttpResponse瀏覽器

def index(request):
return HttpResponse("Hello,this is my frist polls index.")
服務器

(6)polls模塊下映射url


from django.urls import path
from . import views

urlpatterns = [
path('', views.index,name='index'),]

(7)mysite主模塊下配置url


from django.contrib import admin
from django.urls import path,include # 注意導入include模塊

urlpatterns = [
path('polls/', include('polls.urls')), # 配置polls子模板url,支持正則
path('admin/', admin.site.urls),]

(8)網頁查詢http://localhost:8000/polls/

1560157077719

(9)數據庫配置與遷移

DATABASES = {
'default': {
# 'django.db.backends.sqlite3',
# 'django.db.backends.postgresql',
# 'django.db.backends.mysql',
# 'django.db.backends.oracle'
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
},
# MySQL數據庫配置
# 'mysql': {
# 'ENGINE': 'django.db.backends.mysql',
# 'NAME': 'all_news', # 數據庫名
# 'USER': 'root',
# 'PASSWORD': 'root',
# 'HOST': '127.0.0.1',
# 'PORT': '3306',
# }
}

python manage.py migrate

(10)編寫模型M


from django.db import models

Create your models here.

class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_data = models.DateField('date published')

def __str__(self):
    return self.question_text

class Choice(models.Model):
question = models.ForeignKey(Question,on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)

def __str__(self):
    return self.choice_text

(11)激活模型

爲模型的改變生成遷移文件

python manage.py makemigrations polls

1560158954875

另外一種查看,選擇執行接收一個遷移的名稱,而後返回對應的 SQL

python manage.py sqlmigrate polls 0001

應用數據庫遷移

python manage.py migrate

(12)全自動後臺管理頁面

12.1 建立一個能登陸管理頁面的用戶,均爲admin

python manage.py createsuperuser

12.2 啓動開發服務器:

python manage.py runserver

http://127.0.0.1:8000/admin/login/?next=/admin/

12.3 進入站點

1560159957646

12.4 管理頁面中加入配置應用


from django.contrib import admin

Register your models here.

from .models import Question,Choice

admin.site.register(Question)
admin.site.register(Choice)

(13)編寫更多視圖

13.1 polls下的views

from django.shortcuts import render
from django.http import HttpResponse

問題索引頁

def index(request):
return HttpResponse("Hello,this is my frist polls index.")

問題詳情頁

def detail(request,question_id):
return HttpResponse("You're looking at question %s." % question_id)

問題結果頁

def results(request,question_id):
return HttpResponse("You're looking at the results of question %s." % question_id)

投票處理器

def vote(request,question_id):
return HttpResponse("You're voting on question %s." % question_id)

13.2 polls下的urls記得添加命名空間


from django.urls import path
from . import views
app_name = 'polls' #添加命名空間
urlpatterns = [
# ex: /polls/
path('', views.index,name='index'),
# ex: /polls/5/
path(' /', views.detail, name='detail'),
# ex: /polls/5/results/
path(' /results/', views.results, name='results'),
# ex: /polls/5/vote/
path(' /vote/', views.vote, name='vote'),]

13.3 查詢數據庫信息並頁面顯示

問題索引頁

def index(request):
latest_question_list = Question.objects.order_by('pub_data')[:3]
output = '
'.join([q.question_text for q in latest_question_list])
HttpResponse(template.render(context,request))
return HttpResponse(output)

1560224171794

(14)編寫模板T

14.1 在mysite下建立templates,並建立polls文件夾下建立index.html


<!DOCTYPE html>


投票頁面


{% if latest_question_list %}


{% else %}

No polls are available.


{% endif %}


能夠修改成(經常使用).想改爲 polls/specifics/12/ ,你不用在模板裏修改任何東西(包括其它模板),只要在 polls/urls.py 裏稍微修改一下就行:

{% for question in latest_question_list %}

  • {{ question.question_text }}

  • {% endfor %}

    14.2 在mysite的settings修改DIRS


    TEMPLATES = [
    {
    'BACKEND': 'django.template.backends.django.DjangoTemplates',
    'DIRS': [os.path.join(BASE_DIR,'template/')],
    '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',
    ],
    },
    },]

    14.3 polls/views.py 修改


    from django.shortcuts import render
    from django.http import HttpResponse
    from django.template import loader

    from polls.models import Question

    問題索引頁

    def index(request):
    latest_question_list = Question.objects.order_by('pub_data')[:5]
    # output = '
    '.join([q.question_text for q in latest_question_list])
    template = loader.get_template('polls/index.html')
    context = {
    'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context,request))

    進一步能夠修改成(經常使用):

    問題索引頁

    def index(request):
    latest_question_list = Question.objects.order_by('pub_data')[:5]
    context = {'latest_question_list': latest_question_list}
    return render(request,'polls/index.html',context)

    14.4 在瀏覽器訪問 "/polls/" 查看:

    1560225187403

    (15)查看詳細頁面

    15.1 polls下views.py


    from django.http import Http404

    問題詳情頁

    def detail(request,question_id):
    try:
    question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
    raise Http404("Question does not exist")
    return render(request,'polls/detail.html', {'question':question,'question_id':question_id})

    優化後的算法(經常使用)


    from django.shortcuts import render,get_object_or_404

    問題詳情頁

    def detail(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question,'question_id':question_id})

    15.2 template下detail.html


    <!DOCTYPE html>


    詳細問題頁面


    {{ question.question_text }}



      {% for choice in question.choice_set.all %}
    • {{ choice.choice_text }}

    • {% endfor %}

    15.3 運行結果

    1560232295937

    (16)polls/detail.html詳細頁面添加一個表單form



    {{ question.question_text }}

    {% if error_message %}

    {{ error_message }}


    {% endif %}

    {% csrf_token %} {% for choice in question.choice_set.all %}
    {% endfor %}

    • 每一個單選按鈕的 value 屬性是對應的各個 Choice 的 ID。每一個單選按鈕的 name"choice" 。這意味着,當有人選擇一個單選按鈕並提交表單提交時,它將發送一個 POST 數據 choice=# ,其中# 爲選擇的 Choice 的 ID。這是 HTML 表單的基本概念。

    • 咱們設置表單的 action{% url 'polls:vote' question.id %} ,並設置 method="post" 。使用 method="post"是很是重要的,由於這個提交表單的行爲會改變服務器端的數據。當你須要建立一個改變服務器端數據的表單時,請使用`method="post" 。這不是 Django 的特定技巧;這是優秀的網站開發技巧。
    • forloop.counter 指示 for 標籤已經循環多少次。
    • 因爲咱們建立一個 POST 表單(它具備修改數據的做用),因此咱們須要當心跨站點請求僞造。 謝天謝地,你沒必要太過擔憂,由於 Django 已經擁有一個用來防護它的很是容易使用的系統。 簡而言之,全部針對內部 URL 的 POST 表單都應該使用{% csrf_token %} 模板標籤。

    (17) polls/views.py 視圖編輯

    投票處理器

    def vote(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
    selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
    return render(request, 'polls/detail.html', {
    'question': question,
    'error_message': "You didn't select a choice.",})
    else:
    selected_choice.votes +=1
    selected_choice.save()
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    • request.POST 是一個類字典對象,讓你能夠經過關鍵字的名字獲取提交的數據。 這個例子中, request.POST['choice'] 以字符串形式返回選擇的 Choice 的 ID。 request.POST 的值永遠是字符串。
    • 若是在 request.POST['choice'] 數據中沒有提供 choice , POST 將引起一個 KeyError 。上面的代碼檢查 KeyError ,若是沒有給出 choice 將從新顯示 Question 表單和一個錯誤信息。
    • 在增長 Choice 的得票數以後,代碼返回一個 HttpResponseRedirect 而不是經常使用的 HttpResponseHttpResponseRedirect 只接收一個參數:用戶將要被重定向的 URL。構造函數中使用 reverse()函數。這個函數避免了咱們在視圖函數中硬編碼 URL。重定向的 URL 將調用 'results' 視圖來顯示最終的頁面。

    (18) 重定向results.html


    from django.shortcuts import get_object_or_404, render

    def results(request, question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

    (19)通用視圖,代碼重構

    19.1 detail() 視圖幾乎如出一轍。惟一的不一樣是模板的名字。

    問題索引頁

    def index(request):
    latest_question_list = Question.objects.order_by('pub_data')[:5]
    return render(request,'polls/index.html',{'latest_question_list': latest_question_list})

    問題詳情頁

    def detail(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/detail.html', {'question': question,'question_id':question_id})

    問題結果頁

    def results(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    return render(request, 'polls/results.html', {'question': question})

    19.2 建立一個 polls/results.html 模板


    {{ question.question_text }}

      {% for choice in question.choice_set.all %}
    • {{ choice.choice_text }} -- {{ choice.votes }} vote{{ choice.votes|pluralize }}
    • {% endfor %}

    Vote again?

    19.3 通用視圖系統

    通用視圖將常見的模式抽象化,可使你在編寫應用時甚至不須要編寫Python代碼。將咱們的投票應用轉換成使用通用視圖系統,這樣咱們能夠刪除許多咱們的代碼。咱們僅僅須要作如下幾步來完成轉換,

    • 轉換 URLconf。
    • 刪除一些舊的、再也不須要的視圖。
    • 基於 Django 的通用視圖引入新的視圖

    1 改良URLconf

    打開 polls/urls.py 這個 URLconf 並將它修改爲:路徑字符串中匹配模式的名稱已經由 <question_id> 改成 <pk>


    from django.urls import path
    from . import views

    app_name = 'polls'
    urlpatterns = [
    path('', views.IndexView.as_view(), name='index'),
    path(' /', views.DetailView.as_view(), name='detail'),
    path(' /results/', views.ResultsView.as_view(), name='results'),
    path(' /vote/', views.vote, name='vote'),]

    2 改良視圖

    刪除舊的 index, detail, 和 results 視圖,並用 Django 的通用視圖代替。打開 polls/views.py 文件,並將它修改爲:


    from django.http import HttpResponseRedirect
    from django.shortcuts import get_object_or_404, render
    from django.urls import reverse
    from django.views import generic

    from .models import Choice, Question

    class IndexView(generic.ListView):
    template_name = 'polls/index.html'
    context_object_name = 'latest_question_list'

    def get_queryset(self):
        return Question.objects.order_by('pub_date')[:5]

    class DetailView(generic.DetailView):
    model = Question
    template_name = 'polls/detail.html'

    class ResultsView(generic.DetailView):
    model = Question
    template_name = 'polls/results.html'

    def vote(request,question_id):
    question = get_object_or_404(Question, pk=question_id)
    try:
    selected_choice = question.choice_set.get(pk=request.POST['choice'])
    except (KeyError, Choice.DoesNotExist):
    return render(request, 'polls/detail.html', {
    'question': question,
    'error_message': "You didn't select a choice.",
    })
    else:
    selected_choice.votes +=1
    selected_choice.save()
    return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))

    • 每一個通用視圖須要知道它將做用於哪一個模型。 這由 model 屬性提供。
    • DetailView 指望從 URL 中捕獲名爲 "pk" 的主鍵值,因此咱們爲通用視圖把 question_id 改爲 pk

    19.4 運行程序

    主頁面

    1560238410789

    子頁面

    1560238566648

    詳情頁面

    1560238740884

    (20)自動化測試

    20.1 測試的策略

    • 測試驅動:寫代碼以前先寫測試。「測試驅動」的開發方法只是將問題的描述抽象爲了 Python 的測試樣例。
    • 更廣泛的狀況是,一個剛接觸自動化測試的新手更傾向於先寫代碼,而後再寫測試。
    • 若是你才寫了幾千行 Python 代碼,選擇從哪裏開始寫測試確實不怎麼簡單。若是是這種狀況,那麼在你下次修改代碼(好比加新功能,或者修復 Bug)以前寫個測試是比較合理且有效的。

    20.2 第一個測試

    需求:咱們的要求是若是 Question 是在一天以內發佈,was_published_recently()方法將會返回True,然而如今這個方法在Questionpub_date` 字段比當前時間還晚時也會返回 True

    編寫測試代碼:


    from django.test import TestCase

    Create your tests here.

    from django.utils import timezone
    from .models import Question

    class QuestionModelTests(TestCase):
    def test_was_published_recently_with_future_question(self):
    """
    was_published_recently() returns False for questions whose pub_date
    is in the future.
    """
    time = timezone.now() + datetime.timedelta(days=30)
    future_question = Question(pub_date=time)
    self.assertIs(future_question.was_published_recently(), False)

    運行代碼:$ python manage.py test polls

    1560239307381

    測試結果:

    • python manage.py test polls 將會尋找 polls 應用裏的測試代碼
    • 它找到了 django.test.TestCase 的一個子類
    • 它建立一個特殊的數據庫供測試使用
    • 它在類中尋找測試方法——以 test 開頭的方法。
    • test_was_published_recently_with_future_question 方法中,它建立了一個 pub_date 值爲 30 天后的 Question 實例。
    • 接着使用 assertls() 方法,發現 was_published_recently() 返回了 True,而咱們指望它返回 False

    測試系統通知咱們哪些測試樣例失敗了,和形成測試失敗的代碼所在的行號。

    (21)靜態文件(圖片/腳本/樣式)

    對於小項目來講,靜態文件隨便放在哪,只要服務程序可以找到它們就行。然而在大項目中,處理不一樣應用所須要的靜態文件的工做就顯得有點麻煩了。這就是 django.contrib.staticfiles 存在的意義

    建立的 static 文件夾中建立 polls 的文件夾,再在 polls 文件夾中建立一個名爲 style.css 的文件。樣式表路徑應是 polls/static/polls/style.css。由於 AppDirectoriesFinder 的存在,你能夠在 Django 中簡單地使用以 polls/style.css 的形式引用此文件,相似你引用模板路徑的方式。

    li a {
        color: green;
    }

    polls的index.html引用



    投票頁面
    {% load static %}


    添加圖片

    咱們會建立一個用於存在圖像的目錄。在 polls/static/polls 目錄下建立一個名爲 images 的子目錄。在這個目錄中,放一張名爲 background.gif 的圖片。換言之,在目錄 polls/static/polls/images/background.jpg 中放一張圖片。


    body {
    background: white url("images/background.gif") no-repeat;
    }

    1560241682953

    更多關於設置和框架的資料,參考 靜態文件解惑靜態文件指南部署靜態文件 介紹瞭如何在真實服務器上使用靜態文件。

    (22) 編寫第一個django應用

    22.1 polls/admin定義後臺表單,列表爲字段顯示順序


    from django.contrib import admin

    Register your models here.

    from .models import Question,Choice

    class QuestionAdmin(admin.ModelAdmin):
    # fieldsets = [
    # ('問題內容', {'fields': ['question_text']}),
    # ('發佈時間', {'fields': ['pub_data']}),
    # ]
    # fields = ['pub_data', 'question_text']
    list_display = ('question_text', 'pub_data')

    admin.site.register(Question, QuestionAdmin)

    class ChoiceAdmin(admin.ModelAdmin):
    # fields = ['question','choice_text', 'votes']
    list_display = ('question','choice_text', 'votes')

    admin.site.register(Choice, ChoiceAdmin)

    22.2 字段過濾器


    class QuestionAdmin(admin.ModelAdmin):
    list_display = ('question_text', 'pub_data')
    list_filter = ['pub_data'] # 過濾器
    admin.site.register(Question, QuestionAdmin)

    1560245385467

    22.3 自定義後臺界面與風格

    • 打開你的設置文件(mysite/settings.py,牢記),在 TEMPLATES 設置中添加 DIRS 選項:
    • templates 目錄內建立名爲 admin 的目錄,隨後,將存放 Django 默認模板的目錄(django/contrib/admin/templates)內的模板文件 admin/base_site.html 複製到這個目錄內。Django 的源文件在哪裏?$ python -c "import django; print(django.__path__)"1560246196010

    • 接着,用你站點的名字替換文件內的 [](https://docs.djangoproject.com/zh-hans/2.2/intro/tutorial07/#id1){{ site_header|default:_('Django administration') }}(包含大括號)。完成後,你應該看到以下代碼:


    {% block branding %}

    Polls Administration


    {% endblock %}

    1560246347716

    相關文章
    相關標籤/搜索