Django Tutorial Part 3: ä½¿ç¨æ¨¡å
è¿ç¯æç« å±ç¤ºäºå¦ä½ä¸ºæä»¬ç LocalLibrayï¼æ¬å°å¾ä¹¦é¦ï¼ç½ç«å®ä¹ modelsãå®è§£éäºä¸ä¸ªæ¨¡åæ¯ä»ä¹ï¼å®æ¯æä¹è¢«å£°æçï¼åå ¶ä¸çä¸äºä¸»è¦åç±»åã
| Prerequisites: | Django Tutorial Part 2: Creating a skeleton website. |
|---|---|
| Objective: | è½å¤è®¾è®¡å¹¶åå»ºä½ èªå·±çæ°æ®æ¨¡åï¼å¹¶ä¸ºå ¶åéå°éæ©åã |
æ¦è¦
Django ç½ç»åºç¨éè¿ä½ä¸ºæ¨¡å被åç §ç Python 对象访é®å¹¶ç®¡çæ°æ®ã模åå®ä¹äºå¨åæ°æ®çç»æï¼å æ¬åç±»ååå¯è½çæå¤§å¼ï¼é»è®¤å¼ï¼å¯éæ©çå表ï¼å¸®å©çè§£ææ¡£çææ¬ï¼è¡¨æ ¼å çæ ç¾ææ¬ï¼ççãæ¨¡åçå®ä¹æ¯ç¬ç«äºæ°æ®åºçââä½ å¯ä»¥ä¸ºä½ èªå·±ç项ç®è®¾ç½®éæ©ä¸ç§ã䏿¦ä½ å·²ç»éæ©äºä½ æ³ç¨çæ°æ®åºï¼ä½ ä¸éè¦ç´æ¥è°è®ºå®ââä½ åªæ¯ååºä½ çæ¨¡åç»æåå ¶ä»ä»£ç ï¼ç¶å Django ä¼ä¸ºä½ å¤çææç¹ççåæ°æ®åºæäº¤éçå·¥ä½ã
è¿ä¸ªæç¨å±ç¤ºäºå¦ä½å®ä¹å¹¶è®¿é® LocalLibrary website çæ¨¡åã
设计 LocalLibaray 模å
å¨ä½ ç»§ç»å¼å§ä¸ºæ¨¡åå代ç åï¼ç¨å åéèèä¸ä¸æä»¬éè¦å¨åä»ä¹æ°æ®åä¸å对象ä¹é´çå ³ç³»æ¯å¾æä»·å¼çã
æä»¬ç¥éæä»¬éè¦åå¨ä¹¦ç±ï¼ä¹¦åï¼ç®ä»ï¼ä½è ï¼åä½è¯è¨ï¼ç±»å«ï¼ISBN ç¼å·ï¼åæä»¬å¯è½æçå¯è·åç坿¬æ°éï¼å ¨å±ç¬ç« IDï¼å¯è·åç¶æï¼ççï¼ãæä»¬å¯è½éè¦å卿´å¤çå ³äºä½è çä¿¡æ¯èä¸ä» ä» æ¯å¥¹ä»¬çååãæä»¬å¸æè½å¤å°ä¿¡æ¯æ ¹æ®ä¹¦åï¼ä½è ï¼åä½è¯è¨åç±»å«åç±»ã
å½è®¾è®¡ä½ çæ¨¡åæ¶ï¼ç»äºæ¯ä¸ªâ对象âï¼ä¸ç»å ³èä¿¡æ¯ï¼ç¬ç«ç模å似乿ºè¯´å¾éçãå½åæ åµä¸ï¼æä¸ºææ¾ç对象就æ¯ä¹¦ç±åä½è ã
ä½ å¯è½å¨æ³ç¸æ¯ç¡¬ç¼ç ææçé项å°ç½ç«ä¸ï¼ç¨æ¨¡åæ¥åç°éæ©å表ï¼ä¾å¦å æ¬äºè®¸å¤é项ç䏿èåï¼ââæä»¬æ¨èè¿æ ·ï¼å°¤å ¶æ¯å½é项æªç¥æè å¯è½æ¹åæ¶ãæ¾ç¶ï¼ç®å模åçåéè å æ¬äºä¹¦çæµæ´¾ï¼ä¾å¦ç§å¹»å°è¯´ï¼æ³å½è¯æï¼ççï¼åè¯è¨ï¼è±è¯ï¼æ³è¯ï¼æ¥è¯ï¼ã
䏿¦æä»¬å³å®äºæ¨¡åååï¼æä»¬éè¦èèä»ä»¬çå
³ç³»ãDjango å
è®¸ä½ å®ä¹ä¸å¯¹ä¸ (OneToOneField)ï¼ä¸å¯¹å¤ (ForeignKey) åå¤å¯¹å¤ (ManyToManyField) çå
³ç³»ãï¼è¯è
æ³¨ï¼æ¤å¤æä»¬ä»¥å
³ç³»åæ°æ®åºä¸ºåºåï¼å¦æéç¨ NoSQLï¼å¦ MangoDB åæ æ³å¦æ¤èèï¼
æèç以ä¸å
容ï¼ä»¥ä¸ç UML å
³ç³»è¡¨æ¾ç¤ºäºæä»¬å¨è¯¥ä¾åéå®ä¹ç模åãå¦ä¸æè¿°å¦ï¼æä»¬å·²ç»ä¸ºä¹¦ç±ï¼å¤§æ¦çç»èï¼ï¼ä¹¦ç±å®ä¾ï¼ç©ç坿¬æ¯å¦å¯è·åç¶æï¼åä½è
åå»ºäºæ¨¡åãæä»¬ä¹å³å®äºä¸ºæµæ´¾èåå»ºçæ¨¡åï¼æä»¥åéå¼å¯ä»¥éè¿ç®¡ççé¢è·åãæ¤å¤ï¼æä»¬å³å®äºä¸å建 BookInstance:statusçæ¨¡åââæä»¬å·²ç»ç¡¬ç¼ç äºè¿ä¸ªå¼ (LOAN_STATUS) å 为æä»¬ä¸ææè¿äºè¢«æ¹åãéè¿æ¯ä¸ªæ¹æ¡ä½ å¯ä»¥çå°æ¨¡åååï¼å¼åååç±»åï¼è¿ææ¹æ³åè¿åçç±»åã
è¿ä¸ªå¾è¡¨ä¹æ¾ç¤ºäºæ¨¡åä¹é´çå ³ç³»ï¼including their multiplicities. è¿äºå¨å¾è¡¨éæ¯ä¸ªæ¨¡åè¾¹ä¸çæ°åï¼æå¤§åæå°ï¼æ¾ç¤ºäºä»ä»¬çå ³ç³»ãä¾å¦ï¼é¾æ¥ Book å Genre 两个çåç线表示å®ä»¬æ¯å ³èçãé è¿ Book 模åçæ°åæ¾ç¤ºä¸æ¬ä¹¦å¿ é¡»æä¸ä¸ªæå¤ä¸ª Genreï¼è¦å¤å°æå¤å°ï¼ï¼ç¶èå¦ä¸ç«¯é è¿ Genre çæ°åæ¾ç¤ºäºå®å¯ä»¥æé¶ææ æ°æ¬ç¸å ³ç书ç±ã

夿³¨ï¼ä¸ä¸é¨åæä¾äºåºæ¬çå ³äºæ¨¡åå¦ä½è¢«å®ä¹å使ç¨çè§£éãè¾¹é 读ï¼è¾¹èè以䏿们æ¯å¦ä½æ ¹æ®ä»¥ä¸ç徿 æå»ºæ°æ®åºå çæ¨¡åçã
Model primer
This section provides a brief overview of how a model is defined and some of the more important fields and field arguments.
Model definition
Models are usually defined in an application's models.py file. They are implemented as subclasses of django.db.models.Model, and can include fields, methods and metadata. The code fragment below shows a "typical" model, named MyModelName:
from django.db import models
class MyModelName(models.Model):
"""
A typical class defining a model, derived from the Model class.
"""
# Fields
my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")
...
# Metadata
class Meta:
ordering = ["-my_field_name"]
# Methods
def get_absolute_url(self):
"""
Returns the url to access a particular instance of MyModelName.
"""
return reverse('model-detail-view', args=[str(self.id)])
def __str__(self):
"""
String for representing the MyModelName object (in Admin site etc.)
"""
return self.field_name
In the below sections we'll explore each of the features inside the model in detail:
å
ä¸ä¸ªæ¨¡åå¯ä»¥æä»»ææ°éçåï¼æä»»æçç±»åââæ¯ä¸ªç¨ä¸è¡åç°æä»¬æ³åå¨è¿æ°æ®åºçæ°æ®ã让æä»¬çä¸ä¸ä»¥ä¸çä¾åå§ o(â§vâ¦)oï¼
my_field_name = models.CharField(max_length=20, help_text="Enter field documentation")
ä¸é¢çä¾åæä¸ä¸ªååï¼å«å my_field_nameï¼ç±»åæ¯ models.CharFieldââè¿æå³çæ¤åä¼å å«çç±åæ¯ç»æçå符串们ãåç±»åè¢«ç¹æ®ç class èµå¼ï¼è¿ç¡®è®¤äºè®°å½çç±»åæ¯ç¨æ¥åå ¥æ°æ®åºçï¼ä»¥åå½ç¨æ·ä» HTML è¡¨æ ¼éæäº¤å¼åï¼æä»¬ç¨æ¥éªè¯æäº¤ç弿¯å¦ææçæ¡ä»¶ã
åæ®µç±»åè¿å¯ä»¥è·ååæ°ï¼è¿ä¸æ¥æå®å段å¦ä½åæ¾æå¦ä½è¢«ä½¿ç¨ãå¨è¿éçæ åµä¸ï¼æä»¬ç»äºåæ®µä¸¤ä¸ªåæ°ï¼
max_length=20â 表示æ¤å段ä¸å¼çæå¤§é¿åº¦ä¸º 20 个å符çç¶æãhelp_text="Enter field documentation"â æä¾ä¸ä¸ªå¸®å©ç¨æ·çææ¬æ ç¾ï¼è®©ç¨æ·ç¥éå½åéè¿ HTML 表åè¾å ¥æ¶è¦æä¾ä»ä¹å¼ã
åæ®µåç§°ç¨äºå¨è§å¾å模çä¸å¼ç¨å®ãåæ®µè¿æä¸ä¸ªæ ç¾ï¼å®è¢«æå®ä¸ä¸ªåæ°ï¼verbose_nameï¼ï¼æè
éè¿å¤§ååæ®µçåéåç第ä¸ä¸ªåæ¯ï¼å¹¶ç¨ç©ºæ ¼æ¿æ¢ä¸å线ï¼ä¾å¦my_field_nameçé»è®¤æ ç¾ä¸º My field nameï¼ã
å¦ææ¨¡åå¨è¡¨åä¸åç°ï¼ä¾å¦ï¼å¨ç®¡çç«ç¹ä¸ï¼ï¼å声æè¯¥å段ç顺åºï¼å°å½±åå ¶é»è®¤é¡ºåºï¼ä½å¯è½ä¼è¢«è¦çã
Common field arguments
å½å£°æå¾å¤ï¼å¤§å¤æ°ä¸åçåæ®µç±»åæ¶ï¼å¯ä»¥ä½¿ç¨ä»¥ä¸å¸¸ç¨åæ°ï¼
- help_text :æä¾ HTML è¡¨åææ¬æ ç¾ (eg i å¨ç®¡çç«ç¹ä¸),å¦ä¸æè¿°ã
- verbose_name :åæ®µæ ç¾ä¸çå¯è¯»æ§åç§°ï¼å¦ææ²¡æè¢«æå®ï¼Django å°ä»å段åç§°æ¨æé»è®¤ç详ç»åç§°ã
- default :è¯¥åæ®µçé»è®¤å¼ãè¿å¯ä»¥æ¯å¼æå¯å¼å«ç©ä»¶ (callable object)ï¼å¨è¿ç§æ åµä¸ï¼æ¯æ¬¡å建æ°çºªå½æ¶é½å°å¼å«è¯¥ç©ä»¶ã
- nullï¼å¦ä¸º
Trueï¼å³å 许 Django äºèµæåºè¯¥æ ä½åå ¥NULLï¼ä½æ ä½åæå¦ä¸ºCharFieldåä¼åå ¥ç©ºå串ï¼ãé¢è®¾å¼æ¯Falseã - blank :å¦ä¸º
Trueï¼è¡¨åä¸çåæ®µè¢«å 许为空ç½ãé»è®¤æ¯Falseï¼è¿æå³ç Django ç表åéªè¯å°å¼ºå¶ä½ è¾å ¥ä¸ä¸ªå¼ãè¿é常æé NULL=True使ç¨ï¼å ä¸ºå¦æè¦å 许空å¼ï¼ä½ è¿å¸ææ°æ®åºè½å¤éå½å°è¡¨ç¤ºå®ä»¬ã - choices :è¿æ¯ç»æ¤å段çä¸ç»é项ã妿æä¾è¿ä¸é¡¹ï¼é¢è®¾å¯¹åºç表åé¨ä»¶æ¯ã该ç»é项çå表ãï¼è䏿¯åå çæ åææ¬å段ã
- primary_key :å¦ææ¯ Trueï¼å°å½ååæ®µè®¾ç½®ä¸ºæ¨¡åç主é®ï¼ä¸»é®æ¯è¢«æå®ç¨æ¥å¯ä¸è¾¨è¯ææä¸å表记å½çç¹æ®æ°æ®åºæ ä½ (column)ï¼ãå¦ææ²¡ææå®å段ä½ä¸ºä¸»é®ï¼å Django å°èªå¨ä¸ºæ¤æ·»å ä¸ä¸ªå段ã
è¿æè®¸å¤å ¶ä»é项âä½ å¯ä»¥å¨è¿éçå°å®æ´çåæ®µé项ã
Common field types
以ä¸å表æè¿°äºä¸äºæ´å¸¸ç¨çåæ®µç±»åã
- CharField æ¯ç¨æ¥å®ä¹çå°ä¸çé¿åº¦çåæ®µå符串ãä½ å¿
é¡»æå®
max_lengthè¦åå¨çæ°æ®ã - TextField ç¨äºå¤§åä»»æé¿åº¦çå符串ãä½ å¯ä»¥
max_lengthä¸ºè¯¥åæ®µæå®ä¸ä¸ªå段ï¼ä½ä» å½è¯¥åæ®µä»¥è¡¨åæ¾ç¤ºæ¶æä¼ä½¿ç¨ï¼ä¸ä¼å¨æ°æ®åºçº§å«å¼ºå¶æ§è¡ï¼ã - IntegerField æ¯ä¸ä¸ªç¨äºå卿´æ°ï¼æ´æ°ï¼å¼çåæ®µï¼ç¨äºå¨è¡¨åä¸éªè¯è¾å ¥çå¼ä¸ºæ´æ°ã
- DateField åDateTimeField ç¨äºåå¨ï¼è¡¨ç¤ºæ¥æåæ¥æï¼æ¶é´ä¿¡æ¯ï¼å嫿¯
Python.datetime.dateådatetime.datetime对象ï¼ãè¿äºå段å¯ä»¥å¦å¤è¡¨æï¼äºæ¥ï¼åæ°auto_now=Tureï¼å¨æ¯æ¬¡ä¿åæ¨¡åæ¶å°è¯¥å段设置为å½åæ¥æï¼ï¼auto_now_addï¼ä» 设置模å馿¬¡å建æ¶çæ¥æï¼ådefaultï¼è®¾ç½®é»è®¤æ¥æï¼å¯ä»¥è¢«ç¨æ·è¦çï¼ã - EmailField ç¨äºåå¨åéªè¯çµåé®ä»¶å°åã
- FileField åImageField åå«ç¨äºä¸ä¼ æä»¶åå¾åï¼
ImageFieldåªéæ·»å ä¸ä¼ çæä»¶æ¯å¾åçéå éªè¯ï¼ãè¿äºåæ°ç¨äºå®ä¹ä¸ä¼ æä»¶çå卿¹å¼åä½ç½®ã - AutoField æ¯ä¸ç§ IntegerField èªå¨éå¢çç¹æ®ç±»åãå¦æä½ æ²¡ææç¡®æå®ä¸ä¸ªä¸»é®ï¼åæ¤ç±»åç主é®å°èªå¨æ·»å å°æ¨¡åä¸ã
- ForeignKey ç¨äºæå®ä¸å¦ä¸ä¸ªæ°æ®åºæ¨¡åçä¸å¯¹å¤å ³ç³»ï¼ä¾å¦ï¼æ±½è½¦æä¸ä¸ªå¶é åï¼ä½å¶é åå¯ä»¥å¶ä½è®¸å¤æ±½è½¦ï¼ãå ³ç³»çâä¸âä¾§æ¯å å«å¯é¥ç模åã
- ManyToManyField ç¨äºæå®å¤å¯¹å¤å
³ç³»ï¼ä¾å¦ï¼ä¸æ¬ä¹¦å¯ä»¥æå ç§ç±»åï¼æ¯ç§ç±»åå¯ä»¥å
å«å æ¬ä¹¦ï¼ã卿们çå¾ä¹¦é¦åºç¨ç¨åºä¸ï¼æä»¬å°é常类似å°ä½¿ç¨å®ä»¬ ForeignKeysï¼ä½æ¯å¯ä»¥ç¨æ´å¤æçæ¹å¼æ¥æè¿°ç»ä¹é´çå
³ç³»ãè¿äºå
·æåæ°
on_deleteæ¥å®ä¹å ³èè®°å½è¢«å 餿¶ä¼åçä»ä¹ï¼ä¾å¦ï¼å¼models.SET_NULLå°ç®åå°è®¾ç½®ä¸ºå¼ NULLï¼ã
è¿æè®¸å¤å ¶ä»ç±»åçåæ®µï¼å æ¬ä¸åç±»åæ°åçåæ®µï¼å¤§æ´æ°ï¼å°æ´æ°ï¼æµ®ç¹æ°ï¼ï¼å¸æå¼ï¼URLsï¼å¯ä¸ ids åå ¶ä»âæ¶é´ç¸å ³âçä¿¡æ¯ï¼æç»æ¶é´ï¼æ¶é´çï¼ãä½ å¯ä»¥æ¥é 宿´å表 .
å æ°æ® (Metadata)
ä½ å¯ä»¥éè¿å®£å class Meta æ¥å®£å模å级å«çå æ°æ®ï¼å¦å¾æç¤ºï¼
class Meta:
ordering = ['-my_field_name']
æ¤å
æ°æ®ææç¨çåè½ä¹ä¸æ¯æ§å¶å¨æ¥è¯¢æ¨¡åç±»åæ¶è¿åä¹è®°å½çé»è®¤æåºãä½ å¯ä»¥éè¿å¨ordering屿§çåæ®µåç§°åè¡¨ä¸æå®å¹é
é¡ºåºæ¥æ§è¡æ¤æä½ï¼å¦ä¸æç¤ºãæåºå°ä¾èµå段çç±»åï¼åç¬¦ä¸²åæ®µæåæ¯é¡ºåºæåºï¼èæ¥æåæ®µææ¶é´é¡ºåºæåºï¼ãå¦ä¸æç¤ºï¼ä½ å¯ä»¥ä½¿ç¨åå·ï¼-ï¼å¯¹å段åç§°è¿è¡åç¼ï¼ä»¥å转æåºé¡ºåºã
ä¾å¦ï¼å¦ææä»¬éæ©ä¾ç §æ¤é¢è®¾æ¥æå书åï¼
ordering = ['title', '-pubdate']
书åéè¿æ é¢ä¾æ®--忝æåº--æåï¼ä» A å° Zï¼ç¶åå便¯ä¸ªæ é¢çåºçæ¥æï¼ä»ææ°å°ææ§æåã
å¦ä¸ä¸ªå¸¸è§ç屿§æ¯ verbose_name,ä¸ä¸ª verbose_name说æåæ°å夿°å½¢å¼çç±»å«ã
verbose_name = 'BetterName'
å ¶ä»æç¨ç屿§å è®¸ä½ ä¸ºæ¨¡åå建ååºç¨æ°çâè®¿é®æéâï¼é¢è®¾æéä¼è¢«èªå¨å¥ç¨ï¼ï¼å 许åºäºå ¶ä»çåæ®µæåºï¼æå£°æè¯¥ç±»æ¯âæ½è±¡çâï¼ä½ æ æ³å建çè®°å½åºç±»ï¼å¹¶å°ç±å ¶ä»åå·æ´¾çï¼ã
许å¤å ¶ä»å æ°æ®é项æ§å¶æ¨¡åä¸å¿ 须使ç¨åªäºæ°æ®åºä»¥åæ°æ®çå卿¹å¼ãï¼å¦æä½ éè¦æ¨¡åæ å°ä¸ä¸ªç°ææ°æ®åºï¼è¿ä¼æç¨ï¼ã
宿´æç¨çå æ°æ®é项å¨è¿éModel metadata options (Django docs).
æ¹æ³
ä¸ä¸ªæ¨¡åä¹å¯ä»¥ææ¹æ³ã
æèµ·ç ï¼å¨æ¯ä¸ªæ¨¡åä¸ï¼ä½ åºè¯¥å®ä¹æ åç Python ç±»æ¹æ³ __str__()ï¼æ¥ä¸ºæ¯ä¸ªç©ä»¶è¿åä¸ä¸ªäººç±»å¯è¯»çåç¬¦ä¸²ãæ¤å符ç¨äºè¡¨ç¤ºç®¡çç«ç¹çå个记å½ï¼ä»¥åä½ éè¦å¼ç¨æ¨¡åå®ä¾çä»»ä½å
¶ä»ä½ç½®ï¼ãé常è¿å°è¿å模åä¸çæ 颿åç§°åæ®µã
def __str__(self):
return self.field_name
Django æ¹æ³ä¸å¦ä¸ä¸ªå¸¸ç¨æ¹æ³æ¯ get_absolute_url() ï¼è¿å½æ°è¿åä¸ä¸ªå¨ç½ç«ä¸æ¾ç¤ºä¸ªäººæ¨¡åè®°å½ç URLï¼å¦æä½ å®ä¹äºè¯¥æ¹æ³ï¼é£ä¹ Django å°èªå¨å¨â管çç«ç¹â䏿·»å âå¨ç«ç¹ä¸æ¥çâæé®å¨æ¨¡åçè®°å½ç¼è¾æ ï¼ãget_absolute_url()çå
¸å示ä¾å¦ä¸ï¼
def get_absolute_url(self):
"""Returns the url to access a particular instance of the model."""
return reverse('model-detail-view', args=[str(self.id)])
注æ :åè®¾ä½ å°ä½¿ç¨ URL /myapplication/mymodelname/2 æ¥æ¾ç¤ºæ¨¡åçå个记å½ï¼å
¶ä¸â2âæ¯ id ç¹å®è®°å½ï¼ï¼åéè¦å建ä¸ä¸ª URL æ å°å¨æ¥å°ååºå id ä¼ éç»â模å详ç»è§å¾â ï¼è¿å°ååºæ¾ç¤ºè®°å½æéçå·¥ä½ï¼ã以ä¸ç¤ºä¾ä¸ï¼reverse()彿°å¯ä»¥âå转âä½ ç url æ å°å¨ï¼å¨ä¸è¯å½å为âmodel-detail-viewâçæ¡ä¾ä¸ï¼ä»¥å建æ£ç¡®æ ¼å¼ç URLã
å½ç¶è¦åè¿ä¸ªå·¥ä½ï¼ä½ è¿æ¯è¦å URL æ å°ï¼è§å¾å模çï¼
ä½ å¯ä»¥å®ä¹ä¸äºä½ 忬¢çå ¶ä»æ¹æ³ï¼å¹¶ä»ä½ çä»£ç ææ¨¡çè°ç¨å®ä»¬ï¼åªè¦å®ä»¬ä¸å¸¦ä»»ä½åæ°ï¼ã
Model management
䏿¦ä½ å®ä¹äºæ¨¡åç±»ï¼ä½ å¯ä»¥ä½¿ç¨å®ä»¬æ¥åå»ºï¼æ´æ°æå é¤è®°å½ï¼å¹¶è¿è¡æ¥è¯¢è·åææè®°å½æç¹å®çè®°å½åéã彿们å®ä¹æä»¬çè§å¾ï¼æä»¬å°å±ç¤ºç»ä½ å¨è¿ä¸ªæç¨å¦ä½å»åã
å建åä¿®æ¹è®°å½
è¦å建ä¸ä¸ªè®°å½ï¼ä½ å¯ä»¥å®ä¹ä¸ä¸ªæ¨¡åå®ä¾ï¼ç¶åå¼å« save()ã
# Create a new record using the model's constructor.
a_record = MyModelName(my_field_name="Instance #1")
# Save the object into the database.
a_record.save()
夿³¨ï¼å¦ææ²¡æä»»ä½çæ ä½è¢«å®£å为主éµï¼è¿ç¬æ°ç纪å½ä¼è¢«èªå¨çèµäºä¸ä¸ªä¸»é®å¹¶å°ä¸»é®æ å½å为idãä¸ä¾çé£ç¬èµæè¢«å¨ååï¼è¯çæ¥è¯¢è¿ç¬çºªå½ä¼çå°å®è¢«èªå¨èµäº 1 çç¼å·ã
ä½ å¯ä»¥éè¿ãç¹ (dot) çè¯æ³ãå徿忴è¿ç¬æ°èµæçæ ä½ (åæ®µ)ãä½ éè¦å¼å«save()å°åæ´è¿çèµæåè¿èµæåºï¼
# Access model field values using Python attributes.
print(a_record.id) #should return 1 for the first record.
print(a_record.my_field_name) # should print 'Instance #1'
# Change record by modifying the fields, then calling save().
a_record.my_field_name="New Instance Name"
a_record.save()
æå¯»çºªå½
ä½ å¯ä»¥ä½¿ç¨æ¨¡åç objects 屿§ (ç± base class æä¾) æå¯»ç¬¦åæä¸ªæ¡ä»¶ç纪å½
夿³¨ï¼è¦ç¨"æ½è±¡ç"模åè¿ææ ä½è¯´ææä¹æå¯»çºªå½å¯è½ä¼æç¹ä»¤äººå°æãæä»¬ä¼ä»¥ä¸ä¸ª Book 模åï¼å
¶å
å«titleä¸genreåæ®µï¼è genre 乿¯ä¸ä¸ªä»
ænameä¸ä¸ªåæ®µçæ¨¡åã
æä»¬å¯ä»¥åå¾ä¸ä¸ªæ¨¡åçææçºªå½ï¼ä¸ºä¸ä¸ª QuerySet 使ç¨objects.all()ãQuerySet æ¯ä¸ä¸ªå¯è¿ä»£çç©ä»¶ï¼è¡¨ç¤ºä»å«æå¤ä¸ªç©ä»¶ï¼èæä»¬å¯ä»¥èç±è¿ä»£/ååå徿¯ä¸ªç©ä»¶ã
all_books = Book.objects.all()
Django ç filter()æ¹æ³è®©æä»¬å¯ä»¥éè¿ç¬¦åç¹å®æåææ°å¼çåæ®µçéåä¼ çQuerySetãä¾å¦çé书åéæ"wild"ç书并ä¸è®¡ç®æ»æ°ï¼å¦ä¸é¢æç¤ºã
wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = Book.objects.filter(title__contains='wild').count()
è¦æ¯å¯¹çåæ®µä¸æ¯å¯¹æ¹æ³é½è¦è¢«å®ä¹å¨çéçåæ°åç§°éï¼å¹¶ä¸ä½¿ç¨è¿ä¸ªæ ¼å¼ï¼æ¯å°å段__æ¯å°æ¹æ³ (请注æä¸æ¹èä¾ä¸ç title ä¸ contains ä¸é´éäºä¸¤ä¸ªåºçº¿å·)ãå¨ä¸é¢æä»¬ä½¿ç¨å¤§å°ååºåçæ¹å¼æ¯å¯¹titleãè¿æå¾å¤æ¯å¯¹æ¹å¼å¯ä»¥ä½¿ç¨ï¼ icontains(ä¸åºå大å°å), iexact(ä¸å¤§å°ååºåä¸å®å
¨ç¬¦å), exact(åºå大å°åä½å®å
¨ç¬¦å) è¿æ in, gt(大äº), startswith,ä¹ç±»çãå
¨é¨çç¨æ³å¨è¿éã
ææ¶åä½ ä¼é¡»è¦éè¿æä¸ªä¸å¯¹å¤çåæ®µæ¥çé (ä¾å¦ä¸ä¸ª å¤éµ)ãè¿æ ·çç¶åµä¸ï¼ä½ å¯ä»¥ä½¿ç¨ä¸¤ä¸ªåºçº¿æ¥æå®ç¸å
³æ¨¡åçåæ®µãä¾å¦éè¿æä¸ªç¹å®ç genre åç§°çé书ç±ï¼å¦ä¸æç¤ºï¼
books_containing_genre = Book.objects.filter(genre__name__icontains='fiction') # Will match on: Fiction, Science fiction, non-fiction etc.
夿³¨ï¼ä½ å¯ä»¥ç¨ä¸å线æ¥è¡¨ç¤ºä¸åå
³ç³» (ForeignKey/ManyToManyField) .ä¾å¦ï¼ä¸æ¬ä¹¦æä¸åçç±»åï¼ç¨âcoverâå
³ç³»å¯è½ä¼å¸®å©èµ·ä¸ä¸ªåæ°åå type__cover__name__exact='hard'.
è¿æå¾å¤æ¯ä½ å¯ä»¥ç¨ç´¢å¼ (queries) æ¥åçï¼å å«ä»ç¸å ³ç模ååååæ¥è¯¢ (backwards searches)ãè¿éè¿æ»¤å¨ (chaining filters)ãåä¼ ãå¼çå°éåãçãæ´å¤èµè®¯å¯ä»¥å° Making queries (Django Docs) æ¥è¯¢ã
Defining the LocalLibrary Models
In this section we will start defining the models for the library. Open models.py (in /locallibrary/catalog/). The boilerplate at the top of the page imports the models module, which contains the model base class models.Model that our models will inherit from.
from django.db import models
# Create your models here.
Genre model
Copy the Genre model code shown below and paste it into the bottom of your models.py file. This model is used to store information about the book category â for example whether it is fiction or non-fiction, romance or military history, etc. As mentioned above, we've created the Genre as a model rather than as free text or a selection list so that the possible values can be managed through the database rather than being hard coded.
class Genre(models.Model):
"""
Model representing a book genre (e.g. Science Fiction, Non Fiction).
"""
name = models.CharField(max_length=200, help_text="Enter a book genre (e.g. Science Fiction, French Poetry etc.)")
def __str__(self):
"""
String for representing the Model object (in Admin site etc.)
"""
return self.name
The model has a single CharField field (name), which is used to describe the genre (this is limited to 200 characters and has some help_text. At the end of the model we declare a __str__() method, which simply returns the name of the genre defined by a particular record. No verbose name has been defined, so the field will be called Name in forms.
Book model
Copy the Book model below and again paste it into the bottom of your file. The book model represents all information about an available book in a general sense, but not a particular physical "instance" or "copy" available for loan. The model uses a CharField to represent the book's title and isbn (note how the isbn specifies its label as "ISBN" using the first unnamed parameter because the default label would otherwise be "Isbn"). The model uses TextField for the summary, because this text may need to be quite long.
from django.urls import reverse #Used to generate URLs by reversing the URL patterns
class Book(models.Model):
"""
Model representing a book (but not a specific copy of a book).
"""
title = models.CharField(max_length=200)
author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)
# Foreign Key used because book can only have one author, but authors can have multiple books
# Author as a string rather than object because it hasn't been declared yet in the file.
summary = models.TextField(max_length=1000, help_text="Enter a brief description of the book")
isbn = models.CharField('ISBN',max_length=13, help_text='13 Character <a href="https://www.isbn-international.org/content/what-isbn">ISBN number</a>')
genre = models.ManyToManyField(Genre, help_text="Select a genre for this book")
# ManyToManyField used because genre can contain many books. Books can cover many genres.
# Genre class has already been defined so we can specify the object above.
def __str__(self):
"""
String for representing the Model object.
"""
return self.title
def get_absolute_url(self):
"""
Returns the url to access a particular book instance.
"""
return reverse('book-detail', args=[str(self.id)])
The genre is a ManyToManyField, so that a book can have multiple genres and a genre can have many books. The author is declared as ForeignKey, so each book will only have one author, but an author may have many books (in practice a book might have multiple authors, but not in this implementation!)
In both field types the related model class is declared as the first unnamed parameter using either the model class or a string containing the name of the related model. You must use the name of the model as a string if the associated class has not yet been defined in this file before it is referenced! The other parameters of interest in the author field are null=True, which allows the database to store a Null value if no author is selected, and on_delete=models.SET_NULL, which will set the value of the author to Null if the associated author record is deleted.
The model also defines __str__() , using the book's title field to represent a Book record. The final method, get_absolute_url() returns a URL that can be used to access a detail record for this model (for this to work we will have to define a URL mapping that has the name book-detail, and define an associated view and template).
BookInstance model
Next, copy the BookInstance model (shown below) under the other models. The BookInstance represents a specific copy of a book that someone might borrow, and includes information about whether the copy is available or on what date it is expected back, "imprint" or version details, and a unique id for the book in the library.
Some of the fields and methods will now be familiar. The model uses
ForeignKeyto identify the associated Book (each book can have many copies, but a copy can only have oneBook).CharFieldto represent the imprint (specific release) of the book.
import uuid # Required for unique book instances
class BookInstance(models.Model):
"""
Model representing a specific copy of a book (i.e. that can be borrowed from the library).
"""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text="Unique ID for this particular book across whole library")
book = models.ForeignKey('Book', on_delete=models.SET_NULL, null=True)
imprint = models.CharField(max_length=200)
due_back = models.DateField(null=True, blank=True)
LOAN_STATUS = (
('m', 'Maintenance'),
('o', 'On loan'),
('a', 'Available'),
('r', 'Reserved'),
)
status = models.CharField(max_length=1, choices=LOAN_STATUS, blank=True, default='m', help_text='Book availability')
class Meta:
ordering = ["due_back"]
def __str__(self):
"""
String for representing the Model object
"""
return '%s (%s)' % (self.id,self.book.title)
We additionally declare a few new types of field:
UUIDFieldis used for theidfield to set it as theprimary_keyfor this model. This type of field allocates a globally unique value for each instance (one for every book you can find in the library).DateFieldis used for thedue_backdate (at which the book is expected to come available after being borrowed or in maintenance). This value can beblankornull(needed for when the book is available). The model metadata (Class Meta) uses this field to order records when they are returned in a query.statusis aCharFieldthat defines a choice/selection list. As you can see, we define a tuple containing tuples of key-value pairs and pass it to the choices argument. The value in a key/value pair is a display value that a user can select, while the keys are the values that are actually saved if the option is selected. We've also set a default value of 'm' (maintenance) as books will initially be created unavailable before they are stocked on the shelves.
The model __str__() represents the BookInstance object using a combination of its unique id and the associated Book's title.
夿³¨ï¼A little Python:
-
The value returned by
__str__()is a formatted string. Within the string we use%sto declare "placeholders'. After the string we specify%and then a tuple containing the values to be inserted in the placeholders. If you just have one placeholder then you can omit the tuple â e.g.'My value: %s' % variable.Note also that although this approach is perfectly valid, please be aware that it is no longer prefered. Since Python 3 you should instead use the format method, eg. '{0} ({1})'.format(self.id,self.book.title). You can read more about it here.
Author model
Copy the Author model (shown below) underneath the existing code in models.py.
All of the fields/methods should now be familiar. The model defines an author as having a first name, last name, date of birth, and (optional) date of death. It specifies that by default the __str__() returns the name in last name, firstname order. The get_absolute_url() method reverses the author-detail URL mapping to get the URL for displaying an individual author.
class Author(models.Model):
"""
Model representing an author.
"""
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)
def get_absolute_url(self):
"""
Returns the url to access a particular author instance.
"""
return reverse('author-detail', args=[str(self.id)])
def __str__(self):
"""
String for representing the Model object.
"""
return '%s, %s' % (self.last_name, self.first_name)
Re-run the database migrations
All your models have now been created. Now re-run your database migrations to add them to your database.
python3 manage.py makemigrations
python3 manage.py migrate
Language model â challenge
Imagine a local benefactor donates a number of new books written in another language (say, Farsi). The challenge is to work out how these would be best represented in our library website, and then to add them to the models.
Some things to consider:
- Should "language" be associated with a
Book,BookInstance, or some other object? - Should the different languages be represented using model, a free text field, or a hard-coded selection list?
After you've decided, add the field. You can see what we decided on Github here.
Summary
In this article we've learned how models are defined, and then used this information to design and implement appropriate models for the LocalLibrary website.
At this point we'll divert briefly from creating the site, and check out the Django Administration site. This site will allow us to add some data to the library, which we can then display using our (yet to be created) views and templates.
åè§
- Writing your first Django app, part 2 (Django docs)
- Making queries (Django Docs)
- QuerySet API Reference (Django Docs)