django從入門到入坑(二)
-
建立模型
Django通過自定義Python類的形式來定義具體的模型,每個模型的實體存在方式就是一個Python的類Class,每個模型代表資料庫中的一張表,每個類的執行個體代表資料表中的一行資料,類中的每個變量代表資料表中的一列字段。Django通過模型,将Python代碼和資料庫操作結合起來,實作對SQL查詢語言的封裝。也就是說,你可以不會管理資料庫,可以不會SQL語言,你同樣能通過Python的代碼進行資料庫的操作。Django通過ORM對資料庫進行操作,奉行代碼優先的理念,将Python程式員和資料庫管理者進行分工解耦。
在這個簡單的投票應用中,我們将建立兩個模型:Question和Choice。Question包含一個問題和一個釋出日期。Choice包含兩個字段:該選項的文本描述和該選項的投票數。每一條Choice都關聯到一個Question。這些都是由Python的類來展現,編寫的全是Python的代碼,不接觸任何SQL語句。現在,編輯polls/models.py檔案:
from django.db import models class Question(models.Model): question_text = models.CharField(max_length=200) pub_date = models.DateTimeField('date published') class Choice(models.Model): question = models.ForeignKey(Question, on_delete=models.CASCADE) choice_text = models.CharField(max_length=200) votes = models.IntegerField(default=0)
-
啟用模型
上面的代碼看着有點少,其實包含了大量的資訊,據此,Django會做下面兩件事:
- 建立該app對應的資料庫表結構
- 為Question和Choice對象建立基于Python的資料庫通路API
然後需要将其加入到整個項目中,執行一條指令即可:# mysite/settings.py INSTALLED_APPS = [ 'polls.apps.PollsConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]
python manage.py makemigrations polls
-
使用模型API
通過指令進入python的shell環境:
進入shell後,就可以開始嘗試以下的API了:python manage.py shell
>>> from polls.models import Question, Choice # 導入我們寫的模型類 # 現在系統内還沒有questions對象 >>> Question.objects.all() <QuerySet []> # 建立一個新的question對象 # Django推薦使用timezone.now()代替python内置的datetime.datetime.now() # 這個timezone就來自于Django的依賴庫pytz from django.utils import timezone >>> q = Question(question_text="What's new?", pub_date=timezone.now()) # 你必須顯式的調用save()方法,才能将對象儲存到資料庫内 >>> q.save() # 預設情況,你會自動獲得一個自增的名為id的主鍵 >>> q.id 1 # 通過python的屬性調用方式,通路模型字段的值 >>> q.question_text "What's new?" >>> q.pub_date datetime.datetime(2012, 2, 26, 13, 0, 0, 775217, tzinfo=<UTC>) # 通過修改屬性來修改字段的值,然後顯式的調用save方法進行儲存。 >>> q.question_text = "What's up?" >>> q.save() # objects.all() 用于查詢資料庫内的所有questions >>> Question.objects.all() <QuerySet [<Question: Question object>]>
這裡等一下:上面的<Question: Question object>是一個不可讀的内容展示,你無法從中獲得任何直覺的資訊,為此我們需要一點小技巧,讓Django在列印對象時顯示一些我們指定的資訊。
回到polls/models.py檔案,修改一下question和Choice這兩個類:
然後可以再次使用shell:from django.db import models class Question(models.Model): # ... def __str__(self): return self.question_text def was_published_recently(self): return self.pub_date >= timezone.now() - datetime.timedelta(days=1) class Choice(models.Model): # ... def __str__(self): return self.choice_text
>>> from polls.models import Question, Choice # 先看看__str__()的效果,直覺多了吧? >>> Question.objects.all() <QuerySet [<Question: What's up?>]> # Django提供了大量的關鍵字參數查詢API >>> Question.objects.filter(id=1) <QuerySet [<Question: What's up?>]> >>> Question.objects.filter(question_text__startswith='What') <QuerySet [<Question: What's up?>]> # 擷取今年釋出的問卷 >>> from django.utils import timezone >>> current_year = timezone.now().year >>> Question.objects.get(pub_date__year=current_year) <Question: What's up?> # 查詢一個不存在的ID,會彈出異常 >>> Question.objects.get(id=2) Traceback (most recent call last): ... DoesNotExist: Question matching query does not exist. # Django為主鍵查詢提供了一個縮寫:pk。下面的語句和Question.objects.get(id=1)效果一樣. >>> Question.objects.get(pk=1) <Question: What's up?> # 看看我們自定義的方法用起來怎麼樣 >>> q = Question.objects.get(pk=1) >>> q.was_published_recently() True # 讓我們試試主鍵查詢 >>> q = Question.objects.get(pk=1) # 顯示所有與q對象有關系的choice集合,目前是空的,還沒有任何關聯對象。 >>> q.choice_set.all() <QuerySet []> # 建立3個choices. >>> q.choice_set.create(choice_text='Not much', votes=0) <Choice: Not much> >>> q.choice_set.create(choice_text='The sky', votes=0) <Choice: The sky> >>> c = q.choice_set.create(choice_text='Just hacking again', votes=0) # Choice對象可通過API通路和他們關聯的Question對象 >>> c.question <Question: What's up?> # 同樣的,Question對象也可通過API通路關聯的Choice對象 >>> q.choice_set.all() <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]> >>> q.choice_set.count() 3 # API會自動進行連表操作,通過雙下劃線分割關系對象。連表操作可以無限多級,一層一層的連接配接。 # 下面是查詢所有的Choices,它所對應的Question的釋出日期是今年。(重用了上面的current_year結果) >>> Choice.objects.filter(question__pub_date__year=current_year) <QuerySet [<Choice: Not much>, <Choice: The sky>, <Choice: Just hacking again>]> # 使用delete方法删除對象 >>> c = q.choice_set.filter(choice_text__startswith='Just hacking') >>> c.delete()
-
建立admin
很多時候,我們不光要開發針對客戶使用的前端頁面,還要給背景管理人員提供相應的管理界面。但是大多數時候為你的團隊或客戶編寫用于增加、修改和删除内容的背景管理站點是一件非常乏味的工作并且沒有多少創造性,而且也需要花不少的時間和精力。Django最大的優點之一,就是體貼的為你提供了一個基于項目model建立的一個背景管理站點admin。這個界面隻給站點管理者使用,并不對大衆開放。雖然admin的界面可能不是那麼美觀,功能不是那麼強大,内容不一定符合你的要求,但是它是免費的、現成的,并且還是可定制的,有完善的幫助文檔,那麼,你還要什麼自行車?
建立管理者使用者:
python manage.py createsuperuser
接着輸入郵箱位址和密碼就行,當輸入密碼的時候不會顯示,是以請大家注意密碼别亂輸。
在實際環境中,為了站點的安全性,我們一般不能将管理背景的url随便暴露給他人,不能用/admin/這麼簡單的路徑。
打開根url路由檔案mysite/urls.py,修改其中admin.site.urls對應的表達式,換成你想要的,比如:
from django.contrib import admin from django.urls import path urlpatterns = [ path('polls/', include('polls.urls')), path('what/', admin.site.urls), ]
-
進入admin站點
進入網站:http://127.0.0.1:233/what/
會發現進入了admin管理背景,諸如下列情況:
此處發現隻有groups和users,這是django.contrib.auth子產品提供的身份認證架構,我們還需把自己寫的Question導入進來:django學習路程-2
如果發現整個頁面的爆出error,那麼一定是出現了些許問題,諸如資料庫沒上傳成功導緻的問題。#mysite/polls/admin.py from django.contrib import admin from .models import Question admin.site.register(Question)
解決辦法是輸入指令django學習路程-2
後再執行python manage.py makemigrations
,即可完美解決這類問題。python manage.py migrate