django 文档参考模型
2012-10-26 15:10
501 查看
def():
Modelreference
模型参考
Amodelisthesingle,definitivesourceofdataaboutyourdata.Itcontainstheessentialfieldsandbehaviorsofthedatayou'restoring.Generally,eachmodelmapstoasingledatabasetable.Thebasics:
EachmodelisaPythonclassthatsubclassesdjango.db.models.Model.
Eachattributeofthemodelrepresentsadatabasefield.
Modelmetadata(non-fieldinformation)goesinaninnerclassnamed
Meta.
MetadatausedforDjango'sadminsitegoesintoaninnerclassnamed
Admin.
Withallofthis,Djangogivesyouanautomatically-generateddatabase-accessAPI,whichisexplainedinthe
Acompaniontothisdocumentisthe
officialrepositoryofmodelexamples.(IntheDjangosourcedistribution,theseexamplesareinthe
tests/modeltestsdirectory.)
Quickexample
ThisexamplemodeldefinesaPerson,whichhasafirst_nameand
last_name:
fromdjango.dbimportmodels
classPerson(models.Model):
first_name=models.CharField(maxlength=30)
last_name=models.CharField(maxlength=30)
first_nameand
last_namearefieldsofthemodel.Eachfieldisspecifiedasaclassattribute,andeachattributemapstoadatabasecolumn.
TheabovePersonmodelwouldcreateadatabasetablelikethis:
CREATETABLEmyapp_person(
"id"serialNOTNULLPRIMARYKEY,
"first_name"varchar(30)NOTNULL,
"last_name"varchar(30)NOTNULL
);
Sometechnicalnotes:
Thenameofthetable,myapp_person,isautomaticallyderivedfromsomemodelmetadatabutcanbeoverridden.See
Tablenamesbelow.
表名myapp_person从模型的元数据自动产生,但也可以被重写。
Anidfieldisaddedautomatically,butthisbehaviorcanbeoverriden.See
Automaticprimarykeyfieldsbelow.
id字段是自动附加的,也可以被重写。
TheCREATE
TABLESQLinthisexampleisformattedusingPostgreSQLsyntax,butit'sworthnotingDjangousesSQLtailoredtothedatabasebackendspecifiedinyour
settingsfile.
Fields
Themostimportantpartofamodel--andtheonlyrequiredpartofamodel--isthelistofdatabasefieldsitdefines.Fieldsarespecifiedbyclassattributes.Example:
classMusician(models.Model):
first_name=models.CharField(maxlength=50)
last_name=models.CharField(maxlength=50)
instrument=models.CharField(maxlength=100)
classAlbum(models.Model):
artist=models.ForeignKey(Musician)#定义外键
name=models.CharField(maxlength=100)
release_date=models.DateField()#日期字段
num_stars=models.IntegerField()
Fieldnamerestrictions
Djangoplacesonlytworestrictionsonmodelfieldnames:AfieldnamecannotbeaPythonreservedword,becausethatwouldresultinaPythonsyntaxerror.Forexample:
字段名不能是Python保留字。
classExample(models.Model):
pass=models.IntegerField()#'pass'isareservedword!
Afieldnamecannotcontainmorethanoneunderscoreinarow,duetothewayDjango'squerylookupsyntaxworks.Forexample:
字段名不能包含多于一个下划线。因为Django的query查找语法。
classExample(models.Model):
foo__bar=models.IntegerField()'foo__bar'hastwounderscores!
Theselimitationscanbeworkedaround,though,becauseyourfieldnamedoesn'tnecessarilyhavetomatchyourdatabasecolumnname.See
db_columnbelow.
SQLreservedwords,suchasjoin,
whereor
select,areallowedasmodelfieldnames,becauseDjangoescapesalldatabasetablenamesandcolumnnamesineveryunderlyingSQLquery.Itusesthequotingsyntaxofyourparticulardatabaseengine.
SQL保留字,如join,where,select,可以被用作模型的字段名。
Fieldtypes
EachfieldinyourmodelshouldbeaninstanceoftheappropriateFieldclass.Djangousesthefieldclasstypestodetermineafewthings:
Thedatabasecolumntype(e.g.INTEGER,
VARCHAR).
ThewidgettouseinDjango'sadmininterface,ifyoucaretouseit(e.g.
<inputtype="text">,
<select>).
Theminimalvalidationrequirements,usedinDjango'sadminandinmanipulators.
Hereareallavailablefieldtypes:
AutoField
自增字段
AnIntegerFieldthatautomaticallyincrementsaccordingtoavailableIDs.Youusuallywon'tneedtousethisdirectly;aprimarykeyfieldwillautomaticallybeaddedtoyourmodelifyoudon'tspecifyotherwise.See
Automaticprimarykeyfields.
是自增的IntegerField.一般不需要直接操作它。如果除此之外未指定其他的字段为主键,则自增字段会被设置为主键。
BooleanField
布尔型字段
Atrue/falsefield.Theadminrepresentsthisasacheckbox.
CharField
字符串型字段
Astringfield,forsmall-tolarge-sizedstrings.Forlargeamountsoftext,useTextField.
大文本用TextField.
Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
CharFieldhasanextrarequiredargument,
maxlength,themaximumlength(incharacters)ofthefield.ThemaxlengthisenforcedatthedatabaselevelandinDjango'svalidation.
CharField的构造器需要额外提供maxlength参数,这是必须的。
CommaSeparatedIntegerField
逗号分割的整数字段
Afieldofintegersseparatedbycommas.AsinCharField,themaxlengthargumentisrequired.
和CharField一样,必须向其构造器传递maxlength参数。
DateField
日期字段
Adatefield.Hasafewextraoptionalarguments:Argument | Description |
---|---|
auto_now | Automaticallysetthefieldtonoweverytimetheobjectissaved.Usefulfor"last-modified"timestamps.Notethatthecurrentdateis alwaysused;it'snotjustadefaultvaluethatyoucanoverride. 当对象被保存时,自动设置为现在时间。可用于表示最后修改时间的时间戳。注意:当前日期总是会被使用,而不是仅仅一个默认值。 |
auto_now_add | Automaticallysetthefieldtonowwhentheobjectisfirstcreated.Usefulforcreationoftimestamps.Notethatthecurrentdateis alwaysused;it'snotjustadefaultvaluethatyoucanoverride. 当对象被初次创建的时候,自动设置为现在时间。可用于表示创建时间的时间戳。注意:当前日期总是被使用,而不仅仅是一个默认值。 |
type="text">withaJavaScriptcalendarandashortcutfor"Today."
DateTimeField
时间日期字段
Adateandtimefield.TakesthesameextraoptionsasDateField.
拥有和DateField一样的两个额外选项(auto_now,auto_now_add).
Theadminrepresentsthisastwo<input
type="text">fields,withJavaScriptshortcuts.
EmailField
ACharFieldthatchecksthatthevalueisavalide-mailaddress.Thisdoesn'tacceptmaxlength.
能够验证是合法的email的CharField字段。不接受maxlength.
FileField
Afile-uploadfield.文件上传字段
Hasanextrarequiredargument,upload_to,alocalfilesystempathtowhichfilesshouldbeupload.Thispathmaycontain
strftimeformatting,whichwillbereplacedbythedate/timeofthefileupload(sothatuploadedfilesdon'tfillupthegivendirectory).
有一个额外的参数,upload_to,表示一个本地文件路径,用于存放文件。此路径可以包含strftime格式化。
Theadminrepresentsthisasan<input
type="file">(afile-uploadwidget).
UsingaFileFieldoran
ImageField(seebelow)inamodeltakesafewsteps:
在模型中使用FileField或ImageField需要下列步骤:
Inyoursettingsfile,you'llneedtodefineMEDIA_ROOTasthefullpathtoadirectorywhereyou'dlikeDjangotostoreuploadedfiles.(Forperformance,thesefilesarenotstoredinthedatabase.)
DefineMEDIA_URLasthebasepublicURLofthatdirectory.MakesurethatthisdirectoryiswritablebytheWebserver'suseraccount.
在settings文件中,定义MEDIA_ROOT为保存上传文件的目录的全路径。
AddtheFileFieldor
ImageFieldtoyourmodel,makingsuretodefinethe
upload_tooptiontotellDjangotowhichsubdirectoryof
MEDIA_ROOTitshoulduploadfiles.
向模型中添加FileField或ImageField字段。设置upload_to选项,指示Django将文件上传到MEDIA_ROOT的哪个子目录中。
Allthatwillbestoredinyourdatabaseisapathtothefile(relativeto
MEDIA_ROOT).You'llmustlikelywanttousetheconvenience
get_<fieldname>_urlfunctionprovidedbyDjango.Forexample,ifyour
ImageFieldiscalled
mug_shot,youcangettheabsoluteURLtoyourimageinatemplatewith
{{object.get_mug_shot_url
}}.
存储于数据库中的是文件的相对路径(相对于目录MEDIA_ROOT).可利用get_<fieldname>_url函数。举例来说,如果ImageField字段名为mug_shot,则可以在模版中通过{{object.get_mug_shot_url}}字段获取图片的绝对路径。
FilePathField
文件路径字段
Afieldwhosechoicesarelimitedtothefilenamesinacertaindirectoryonthefilesystem.Hasthreespecialarguments,ofwhichthefirstisrequired:该字段的值被限制为某个目录下的文件名。它有3个特殊参数,其中第一个参数是必要的。
Argument | Description |
---|---|
path | Required.Theabsolutefilesystempathtoadirectoryfromwhichthis FilePathFieldshouldgetitschoices.Example: "/home/images". 必填。指向可选的文件名所在目录的名称。如:"/home/images". |
match | Optional.Aregularexpression,asastring,that FilePathFieldwillusetofilterfilenames.Notethattheregexwillbeappliedtothebasefilename,notthefullpath.Example: "foo.*/.txt^",whichwillmatchafilecalled foo23.txtbutnot bar.txtorfoo23.gif. 可选。是一个正则表达式,FilePathField用来过滤文件名。该正则表达式用于文件名的base部分,而不是全名。如:"foo.*/.txt^",能够匹配foo23.txt而不能匹配bar.txt或foo23.gif. |
recursive | Optional.EitherTrueor False.Defaultis False.Specifieswhetherallsubdirectoriesof pathshouldbeincluded. 可选,默认值为False.表示path的子目录是否包括在内。 |
Theonepotentialgotchaisthatmatchappliestothebasefilename,notthefullpath.So,thisexample:
注意:下列代码中
FilePathField(path="/home/images",match="foo.*",recursive=True)
...willmatch/home/images/foo.gifbutnot
/home/images/foo/bar.gifbecausethe
matchappliestothebasefilename(foo.gifand
bar.gif).
能匹配/home/images/foo.gif但不匹配/home/images/foo/bar.gif(因为匹配的是文件名的base部分)
FloatField
浮点数字段
Afloating-pointnumber.Hastworequiredarguments有两个必须的字段:
Argument | Description |
---|---|
max_digits | Themaximumnumberofdigitsallowedinthenumber. 数字长度 |
decimal_places | Thenumberofdecimalplacestostorewiththenumber. 十进制位的数目,即有效位数 |
models.FloatField(...,max_digits=5,decimal_places=2)
Andtostorenumbersuptoapproximatelyonebillionwitharesolutionof10decimalplaces:
models.FloatField(...,max_digits=19,decimal_places=10)
Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
ImageField
图片字段
LikeFileField,butvalidatesthattheuploadedobjectisavalidimage.Hastwoextraoptionalarguments,height_fieldand
width_field,which,ifset,willbeauto-populatedwiththeheightandwidthoftheimageeachtimeamodelinstanceissaved.
类似于FileField,但会验证上传的对象是否为图片。有两个额外的可选字段:height_field和width_field
Requiresthe
PythonImagingLibrary.
IntegerField
整数字段
Aninteger.Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
IPAddressField
IP地址字段
AnIPaddress,instringformat(i.e."24.124.1.30").Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
NullBooleanField
允许为空的布尔型字段
LikeaBooleanField,butallowsNULLasoneoftheoptions.Usethisinsteadofa
BooleanFieldwith
null=True.
可以用这个字段类型代替设置了null=True属性的BooleanField.
Theadminrepresentsthisasa<select>boxwith"Unknown","Yes"and"No"choices.
PhoneNumberField
电话号码字段
ACharFieldthatchecksthatthevalueisavalidU.S.A.-stylephonenumber(intheformatXXX-XXX-XXXX).
表示美国电话号码的格式的字段(xxx-xxx-xxxx)
PositiveIntegerField
正整数字段
LikeanIntegerField,butmustbepositive.PositiveSmallIntegerField
小的正整数字段
LikeaPositiveIntegerField,butonlyallowsvaluesunderacertain(database-dependent)point.最大值取决于具体的数据库特性
SlugField
"Slug"isanewspaperterm.Aslugisashortlabelforsomething,containingonlyletters,numbers,underscoresorhyphens.They'regenerallyusedinURLs."Slug"是报纸的术语。表示一个短的标签,仅包含字母,数字,下划线或连字符。一般用于URL中。
IntheDjangodevelopmentversion,youcanspecify
maxlength.Ifmaxlengthisnotspecified,Djangowilluseadefaultlengthof50.InpreviousDjangoversions,there'snowaytooverridethelengthof50.
在Django开发版中,可指定maxlength.默认的长度是50.在低版本的Django中,没有办法可以覆盖长度为50的限制。
Impliesdb_index=True.
隐含db_index=True
Acceptsanextraoption,prepopulate_from,whichisalistoffieldsfromwhichtoauto-populatetheslug,viaJavaScript,intheobject'sadminform:
接受一个额外选项prepopulate_from,用于指示在admin表单中的可选值。
models.SlugField(prepopulate_from=("pre_name","name"))
prepopulate_fromdoesn'tacceptDateTimeFields.
prepopulate_from不接受DateTimeField字段
TheadminrepresentsSlugFieldasan
<inputtype="text">(asingle-lineinput).
SmallIntegerField
小整数字段
LikeanIntegerField,butonlyallowsvaluesunderacertain(database-dependent)point.TextField
大文本字段
Alargetextfield.Theadminrepresentsthisasa<textarea>(amulti-lineinput).
TimeField
时间字段
Atime.Acceptsthesameauto-populationoptionsasDateFieldandDateTimeField.
和DateField以及DateTimeField一样也有两个时间戳字段。
Theadminrepresentsthisasan<input
type="text">withsomeJavaScriptshortcuts.
URLField
AfieldforaURL.Iftheverify_existsoptionisTrue(default),theURLgivenwillbecheckedforexistence(i.e.,theURLactuallyloadsanddoesn'tgivea404response).
表示URL的字段。如果verify_exists选项为True(默认),则会检查URL的可用性(比方说,URL能够加载,并且反馈404错误)。
Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
USStateField
两个字母表示的美国州名字段
Atwo-letterU.S.stateabbreviation.Theadminrepresentsthisasan<input
type="text">(asingle-lineinput).
XMLField
XML字段
ATextFieldthatchecksthatthevalueisvalidXMLthatmatchesagivenschema.Takesonerequiredargument,schema_path,whichisthefilesystempathtoa
表示XML文档的TextField.会针对指定的schema验证其有效性。接受一个必选参数schema_path.
Fieldoptions
Thefollowingargumentsareavailabletoallfieldtypes.Allareoptional.下面两个是对所有字段都有效的选项,两者都是可选值。
null
IfTrue,DjangowillstoreemptyvaluesasNULLinthedatabase.Defaultis
False.
如果为True,Django会保存空字符串为NULL到数据库,默认是False.
Notethatemptystringvalueswillalwaysgetstoredasemptystrings,notas
NULL--sousenull=Truefornon-stringfieldssuchasintegers,booleansanddates.
注意空字符串会保存为空字符串,而不是NULL,所以对于非字符串类型的字段,比如整数,布尔值以及日期,需要设定null=True.
Avoidusingnullonstring-basedfieldssuchas
CharFieldand
TextFieldunlessyouhaveanexcellentreason.Ifastring-basedfieldhas
null=True,thatmeansithastwopossiblevaluesfor"nodata":
NULL,andtheemptystring.Inmostcases,it'sredundanttohavetwopossiblevaluesfor"nodata;"Djangoconventionistousetheemptystring,not
NULL.
对于基于字符串类型的字段如CharField,TextField要避免使用null.除非有特别的理由。如果一个基于字符串的字段类型设置了null=True,这就意味着有两种可能的值用于表示“没有数据”:NULL和空字符串。在大多数情况下,用两种值表示没有数据是冗余的,所以Django的惯例是使用空字符串,而不是NULL.
blank
IfTrue,thefieldisallowedtobeblank.如果为True,该字段允许留空。
Notethatthisisdifferentthannull.
nullispurelydatabase-related,whereas
blankisvalidation-related.Ifafieldhas
blank=True,validationonDjango'sadminsitewillallowentryofanemptyvalue.Ifafieldhas
blank=False,thefieldwillberequired.
和null的区别:null是完全相对数据库的概念,而blank是对数据校验(validation)而言的。如果blank=True,则Django的admin后台校验功能会允许空值,否则字段为必填。
choices
Aniterable(e.g.,alistortuple)of2-tuplestouseaschoicesforthisfield.由二元组的可枚举集合(list或tuple或其他)所代表的字段可选值。
Ifthisisgiven,Django'sadminwilluseaselectboxinsteadofthestandardtextfieldandwilllimitchoicestothechoicesgiven.
Django的admin会使用下拉框代替文本框,限制可选值的范围。
Achoiceslistlookslikethis:
YEAR_IN_SCHOOL_CHOICES=(
('FR','Freshman'),
('SO','Sophomore'),
('JR','Junior'),
('SR','Senior'),
('GR','Graduate'),
)
Thefirstelementineachtupleistheactualvaluetobestored.Thesecondelementisthehuman-readablenamefortheoption.
每个tuple的第一个元素是选项值,第二个是方便阅读的选项名称。
Thechoiceslistcanbedefinedeitheraspartofyourmodelclass:
可选值的列表可以定义在模型类里面:
classFoo(models.Model):
GENDER_CHOICES=(
('M','Male'),
('F','Female'),
)
gender=models.CharField(maxlength=1,choices=GENDER_CHOICES)
oroutsideyourmodelclassaltogether:
也可以定义在外部:
GENDER_CHOICES=(
('M','Male'),
('F','Female'),
)
classFoo(models.Model):
gender=models.CharField(maxlength=1,choices=GENDER_CHOICES)
Finally,notethatchoicescanbeanyiterableobject--notnecessarilyalistortuple.Thisletsyouconstructchoicesdynamically.Butifyoufindyourselfhacking
choicestobedynamic,you'reprobablybetteroffusingaproperdatabasetablewitha
ForeignKey.
choicesismeantforstaticdatathatdoesn'tchangemuch,ifever.
最后一点,请注意可选值可以是任意可枚举的对象:不一定要是list或tuple.这使得我们可以动态的构建选项集合对象。但是,如果你发现你需要动态构建选项列表对象时,也许使用一个外键表会更好,搭配ForeignKey字段设定。choices是为那些几乎从来不发生变化的静态选项集合而设定的。
core
Forobjectsthatareeditedinlinetoarelatedobject.为了以内联的方式编辑对象,设定到一个关联对象的需要而设定。
IntheDjangoadmin,ifall"core"fieldsinaninline-editedobjectarecleared,theobjectwillbedeleted.
在Djangoadmin中,如果某个内联编辑(inline-edited)的对象的所有"core"字段都被清空,则该对象会被删除。
Itisanerrortohaveaninline-editablerelationwithoutatleastone
core=Truefield.
如果设定了内联编辑关系,却不设置至少一个core=True字段,这是做错误的。
Pleasenotethateachfieldmarked"core"istreatedasarequiredfieldbytheDjangoadminsite.Essentially,thismeansyoushouldput
core=Trueonallrequiredfieldsinyourrelatedobjectthatisbeingeditedinline.
注意,所有被标注为"core"的字段都会被DjangoAdmin当作必填字段。本质上,这就是说你需要对所有内联编辑的相关对象上加core=True字段。
db_column
Thenameofthedatabasecolumntouseforthisfield.Ifthisisn'tgiven,Djangowillusethefield'sname.用于标注对应于字段属性的数据库列名称。如果不提供,则会直接使用字段属性的名称。
IfyourdatabasecolumnnameisanSQLreservedword,orcontainscharactersthataren'tallowedinPythonvariablenames--notably,thehyphen--that'sOK.Djangoquotescolumnandtablenamesbehindthescenes.
一般可以用这个办法来应付数据库字段和SQL保留字冲突的情况,或者和Python变量名冲突的情况(比如连字符不允许出现在Python变量名中)。
db_index
IfTrue,django-admin.pysqlindexeswilloutputa
CREATEINDEXstatementforthisfield.
如果为True,django-admin.pysqlindexes会为此语句输出一个CREATEINDEX语句。
default
Thedefaultvalueforthefield.字段的默认值
editable
IfFalse,thefieldwillnotbeeditableintheadmin.DefaultisTrue.
如果为False,该字段在admin中不能被编辑。默认是True.
help_text
Extra"help"texttobedisplayedunderthefieldontheobject'sadminform.It'susefulfordocumentationevenifyourobjectdoesn'thaveanadminform.用于显示在admin表单中的额外的帮助信息。即使不使用admin表单,这个字段也非常适合与文档功能。
primary_key
IfTrue,thisfieldistheprimarykeyforthemodel.如果是True,该字段为主键。
Ifyoudon'tspecifyprimary_key=Trueforanyfieldsinyourmodel,Djangowillautomaticallyaddthisfield:
如果在某个模型中没有设置任何字段为primary_key=True,则Django会自动生成一个id字段:
id=models.AutoField('ID',primary_key=True)
Thus,youdon'tneedtosetprimary_key=Trueonanyofyourfieldsunlessyouwanttooverridethedefaultprimary-keybehavior.
一般不需要在任何字段上设置primary_key=True,除非你要覆盖自动产生id的行为。
primary_key=Trueimplies
blank=False,
null=Falseandunique=True.Onlyoneprimarykeyisallowedonanobject.
primary_key=True暗示着blank=False,null=False并且unique=True.一个对象只能有一个主键。
radio_admin
Bydefault,Django'sadminusesaselect-boxinterface(<select>)forfieldsthatareForeignKeyorhave
choicesset.Ifradio_adminissetto
True,Djangowillusearadio-buttoninterfaceinstead.
默认情况下,Djangoadmin用下拉框来选择ForeignKey或choices.如果设定radio_admin=True,则会用但旋钮代替。
Don'tusethisforafieldunlessit'saForeignKeyorhas
choicesset.
如果字段不是ForeignKey或choices,不要用这个属性。
unique
IfTrue,thisfieldmustbeuniquethroughoutthetable.如果为True,则该字段值在表中是唯一的。
ThisisenforcedatthedatabaselevelandattheDjangoadmin-formlevel.
这个选项同时约束在数据库级别和Djangoadmin表单中。
unique_for_date
SetthistothenameofaDateFieldorDateTimeFieldtorequirethatthisfieldbeuniqueforthevalueofthedatefield.
将这个属性值设定为某个DateField或DateTimeField字段的名称,使得此字段值相关的日期唯一。
Forexample,ifyouhaveafieldtitlethathas
unique_for_date="pub_date",thenDjangowouldn'tallowtheentryoftworecordswiththesame
titleand
pub_date.
举例来说,如果你有个字段title,在其上设定了unique_for_date="pub_date",那么Django就不会允许产生两条title和pub_date都相同的记录。
ThisisenforcedattheDjangoadmin-formlevelbutnotatthedatabaselevel.
这个限制仅在Djangoadmin-form上起作用,而不约束数据库。
unique_for_month
Likeunique_for_date,butrequiresthefieldtobeuniquewithrespecttothemonth.和unique_for_date类似,但要求字段相对月份是唯一的。
unique_for_year
Likeunique_for_dateandunique_for_month.
和unique_for_date以及unique_for_month类似。
validator_list
Alistofextravalidatorstoapplytothefield.Eachshouldbeacallablethattakestheparametersfield_data,
all_dataandraisesdjango.core.validators.ValidationErrorforerrors.(Seethe
validatordocs.)
针对该字段的一系列额外的验证器的列表。其中每个验证器都应该是callable,其参数为field_data,all_data,错误时抛出的异常为django.core.validators.ValidationError.
Djangocomeswithquiteafewvalidators.They'rein
django.core.validators.
Django自带了很多验证器,都在django.core.validators下。
Verbosefieldnames
Eachfieldtype,exceptforForeignKey,ManyToManyFieldand
OneToOneField,takesanoptionalfirstpositionalargument--averbosename.Iftheverbosenameisn'tgiven,Djangowillautomaticallycreateitusingthefield'sattributename,convertingunderscorestospaces.
每个字段,除了ForeignKey,ManyToManyField和OneToOneField之外,可以接受第一个可选参数:即此字段的描述名称。如果没有提供,Django会根据属性名称自动创建一个,在此过程中,会把下划线转化为空格。
Inthisexample,theverbosenameis"Person's
firstname":
first_name=models.CharField("Person'sfirstname",maxlength=30)
Inthisexample,theverbosenameis"first
name":
first_name=models.CharField(maxlength=30)
ForeignKey,
ManyToManyFieldandOneToOneFieldrequirethefirstargumenttobeamodelclass,sousethe
verbose_namekeywordargument:
ForeignKey,ManyToManyField和OneToOneField要求第一个参数是一个Model类,因此需要用verbose_name这个关键字参数:
poll=models.ForeignKey(Poll,verbose_name="therelatedpoll")
sites=models.ManyToManyField(Site,verbose_name="listofsites")
place=models.OneToOneField(Place,verbose_name="relatedplace")
Conventionisnottocapitalizethefirstletterofthe
verbose_name.Djangowillautomaticallycapitalizethefirstletterwhereitneedsto.
惯例是verbose_name的首字母不需要大写。因为Django会在需要的时候把它自动转化为大写形式。
Relationships
关系
Clearly,thepowerofrelationaldatabasesliesinrelatingtablestoeachother.Djangoofferswaystodefinethethreemostcommontypesofdatabaserelationships:Many-to-one,many-to-manyandone-to-one.很显然,关系型数据库的威力就在于表之间的相互关联。Django提供了办法来定义最常见的三种表间关联的类型:多对一,多对多,一对一。
Many-to-onerelationships
多对一关联
Todefineamany-to-onerelationship,useForeignKey.YouuseitjustlikeanyotherFieldtype:byincludingitasaclassattributeofyourmodel.
要定义多对一关联,使用ForeignKey.只要像其他字段类型一样使用它即可:将它定义为Model类的一个属性。
ForeignKeyrequiresapositionalargument:Theclasstowhichthemodelisrelated.
ForeignKey需要一个位置确定的参数:和当前Model相关联的类。
Forexample,ifaCarmodelhasa
Manufacturer--thatis,a
Manufacturermakesmultiplecarsbuteach
Caronlyhasone
Manufacturer--usethefollowingdefinitions:
举例来说,如果一个汽车(Car)模型对应一个制造商(Manufacturer),也就是说,一个制造商生产多个汽车,但一个汽车只有一个制造商。可以使用如下方式定义这种关系:
classManufacturer(models.Model):
#...
classCar(models.Model):
manufacturer=models.ForeignKey(Manufacturer)
#...
Tocreatearecursiverelationship--anobjectthathasamany-to-onerelationshipwithitself--use
models.ForeignKey('self').
如果要创建递归的关系:即一个对象和它自身有多对一的关系,使用models.ForeignKey('self')
Ifyouneedtocreatearelationshiponamodelthathasnotyetbeendefined,youcanusethenameofthemodel,ratherthanthemodelobjectitself:
如果要创建一个关系,而它所依赖的模型还未被创建,你可以用模型的名称(字符串形式),而不是模型对象自身:
classCar(models.Model):
manufacturer=models.ForeignKey('Manufacturer')
#...
classManufacturer(models.Model):
#...
Note,however,thatsupportforstringsaroundmodelnamesin
ForeignKeyisquitenew,anditcanbebuggyinsomecases.
但是需要注意的是,这种用字符串形式的ForeignKey支持是比较新的特性,在某些情况下也许会产生bug.
Behindthescenes,Djangoappends"_id"tothefieldnametocreateitsdatabasecolumnname.Intheaboveexample,thedatabasetableforthe
Carmodelwillhavea
manufacturer_idcolumn.(Youcanchangethisexplicitlybyspecifying
db_column;see
db_columnbelow.)However,yourcodeshouldneverhavetodealwiththedatabasecolumnname,unlessyouwritecustomSQL.You'llalwaysdealwiththefieldnamesofyourmodelobject.
在幕后,Django向字段属性名称上附加"_id"来构成数据库的列名称。在上面的例子中,数据库中对应于Car模型的表会产生一个名为manufacturer_id的字段。(你也可以显式的指定它,通过db_column)。但是,你的代码应该从来不直接处理数据库列名称,除非你要写自定义的SQL.你应该总是操作模型对象的字段属性名。
It'ssuggested,butnotrequired,thatthenameofa
ForeignKeyfield(manufacturerintheexampleabove)bethenameofthemodel,lowercase.Youcan,ofcourse,callthefieldwhateveryouwant.Forexample:
有一个建议,但不是必须的:ForeignKey字段的名称(上述例子中的manufacturer)是对应模型类名称的小写。但你也可以将它取为任意的名称,比如:
classCar(models.Model):
company_that_makes_it=models.ForeignKey(Manufacturer)
#...
Seethe
Many-to-onerelationshipmodelexampleforafullexample.
ForeignKeyfieldstakeanumberofextraargumentsfordefininghowtherelationshipshouldwork.Allareoptional:
ForeignKey字段有一些额外的参数可以定义关系的具体形式,它们都是可选的:
Argument | Description |
---|---|
edit_inline | IfnotFalse,thisrelatedobjectisedited"inline"ontherelatedobject'spage.Thismeansthattheobjectwillnothaveitsownadmininterface.Useeither models.TABULARor models.STACKED,which,respectively,designatewhethertheinline-editableobjectsaredisplayedasatableorasa"stack"offieldsets. 如果不是False,则此对象会用内联的形式在相关对象页面直接编辑。这表示此对象没有它自己独立的管理界面。使用models.TABULAR或models.STACKED来标注,分别表示内联编辑的对象显示为表格还是fieldsets的stack. |
limit_choices_to | Adictionaryoflookupargumentsandvalues(seethe DatabaseAPIreference)thatlimittheavailableadminchoicesforthisobject.Usethiswith models.LazyDatetolimitchoicesofobjectsbydate.Forexample: 一个包含查找参数及其值的字典,用于限制对象可用的adminchoices,和models.LazyDate联用,用于按日期限制不同的选项,如: limit_choices_to={'pub_date__lte':models.LazyDate()} onlyallowsthechoiceofrelatedobjectswitha pub_datebeforethecurrentdate/timetobechosen. 这个语句使得仅允许选择pub_date字段值在当前时间之前的那些日期。 InsteadofadictionarythiscanalsobeaQobject(anobjectwitha get_sql()method)formorecomplexqueries. 和字典不同的是,在负责的查询中,这个也可以是一个Q对象(含有get_sql()方法的对象) Notcompatiblewithedit_inline. 和edit_inline不相容。 |
max_num_in_admin | Forinline-editedobjects,thisisthemaximumnumberofrelatedobjectstodisplayintheadmin.Thus,ifapizzacouldonlyhaveupto10toppings, max_num_in_admin=10wouldensurethatauserneverentersmorethan10toppings. 对于内联编辑的对象,这是显示在admin界面中相关对象的最大数目。 Notethatthisdoesn'tensuremorethan10relatedtoppingsevergetcreated.Itsimplycontrolstheadmininterface;itdoesn'tenforcethingsatthePythonAPIlevelordatabaselevel. 仅控制admin界面,对PythonAPI或数据库层次没有限制。 |
min_num_in_admin | Theminimumnumberofrelatedobjectsdisplayedintheadmin.Normally,atthecreationstage, num_in_admininlineobjectsareshown,andattheeditstage num_extra_on_changeblankobjectsareshowninadditiontoallpre-existingrelatedobjects.However,nofewerthan min_num_in_adminrelatedobjectswilleverbedisplayed. 在admin中显示的内联编辑对象的最少数目。通常,在创建阶段,会显示num_in_admin个内联对象,而在编辑阶段显示num_extra_on_change个额外的空对象。(排除已有的一些相关对象),然而,少于min_num_in_admin个相关对象的从来不被显示。 |
num_extra_on_change | Thenumberofextrablankrelated-objectfieldstoshowatthechangestage. 对象在修改状态时,显示的额外的空白关联对象的数目。 |
num_in_admin | Thedefaultnumberofinlineobjectstodisplayontheobjectpageattheaddstage. 对象在添加状态时,显示的内联编辑的相关对象数目。 |
raw_id_admin | Onlydisplayafieldfortheintegertobeenteredinsteadofadrop-downmenu.Thisisusefulwhenrelatedtoanobjecttypethatwillhavetoomanyrowstomakeaselectboxpractical. 仅显示一个可输入的整数值字段,而不是下拉列表。当关联对象在下拉框里显示会显得太多时,这很有用。 Notusedwithedit_inline. 不能和edit_inline选项一起设定。 |
related_name | Thenametousefortherelationfromtherelatedobjectbacktothisone.Seethe relatedobjectsdocumentationforafullexplanationandexample. 设定从关联对象到自身的关系名称。 |
to_field | Thefieldontherelatedobjectthattherelationisto.Bydefault,Djangousestheprimarykeyoftherelatedobject. 关联到的对象的字段名称。默认情况下,Django使用关联对象的主键字段。 |
Many-to-manyrelationships
多对多关联
Todefineamany-to-manyrelationship,useManyToManyField.YouuseitjustlikeanyotherFieldtype:byincludingitasaclassattributeofyourmodel.
要定义多对多关联,用ManyToManyField.
ManyToManyFieldrequiresapositionalargument:Theclasstowhichthemodelisrelated.
ManyToManyField需要一个位置确定的参数:关联的模型的类名称。
Forexample,ifaPizzahasmultiple
Toppingobjects--thatis,a
Toppingcanbeonmultiplepizzasandeach
Pizzahasmultipletoppings--here'showyou'drepresentthat:
举例来说,假如一个Pizza可以有多个Topping对象:也就是说,每个Topping可以在多个pizza上面,并且每个Pizza可以有多个toppings.那么你可以用如下的办法来定义模型:
classTopping(models.Model):
#...
classPizza(models.Model):
#...
toppings=models.ManyToManyField(Topping)
AswithForeignKey,arelationshiptoselfcanbedefinedbyusingthestring
'self'insteadofthemodelname,andyoucanrefertoas-yetundefinedmodelsbyusingastringcontainingthemodelname.
和ForeignKey的设置一样,指向自身的多对多关联,可以用'self'来代替模型名称;指向尚未定义的模型时,可以用字符串形式表示。
It'ssuggested,butnotrequired,thatthenameofa
ManyToManyField(toppingsintheexampleabove)beapluraldescribingthesetofrelatedmodelobjects.
建议将ManyToManyField设置为复数形式,但这不是必须的。
Behindthescenes,Djangocreatesanintermediaryjointabletorepresentthemany-to-manyrelationship.
在幕后,Django会创建一个中间表来管理多对多关联。
Itdoesn'tmatterwhichmodelgetstheManyToManyField,butyouonlyneeditinoneofthemodels--notinboth.
在多对多关联的哪一方模型中定义ManyToManyField并不重要,但你只需要定义一次,而不是两边都定义。
Generally,ManyToManyFieldinstancesshouldgointheobjectthat'sgoingtobeeditedintheadmininterface,ifyou'reusingDjango'sadmin.Intheaboveexample,
toppingsisin
Pizza(ratherthanToppinghavinga
pizzas
ManyToManyField)becauseit'smorenaturaltothinkabouta
Pizzahavingtoppingsthanatoppingbeingonmultiplepizzas.Thewayit'ssetupabove,the
Pizzaadminformwouldletusersselectthetoppings.
一般的,ManyToManyField实例在admin界面中,会显示在其所属的对象的编辑界面,如果你使用Django的admin界面的话。在上述例子中,toppings显示在Pizza中,因为,我们说“一个Pizza有多个toppings"要比"一个topping在多个pizzas上面"来的更自然。按照上面的设置,在Pizza的管理界面上将会让你选择toppings来编辑。
Seethe
Many-to-manyrelationshipmodelexampleforafullexample.
ManyToManyFieldobjectstakeanumberofextraargumentsfordefininghowtherelationshipshouldwork.Allareoptional:
ManyToManyField的一些可选参数:
Argument | Description |
---|---|
related_name | SeethedescriptionunderForeignKeyabove. 同ForeignKey的情形 |
filter_interface | UseaniftyunobtrusiveJavascript"filter"interfaceinsteadoftheusability-challenged <selectmultiple>intheadminformforthisobject.Thevalueshouldbe models.HORIZONTALor models.VERTICAL(i.e.shouldtheinterfacebestackedhorizontallyorvertically). 在管理界面中,使用好看实用的JavaScript"filter"界面代替可用性受到挑战的<selectmultiple>.其值可以是models.HORIZONTAL或models.VERTICAL(指界面排序的方向)。 |
limit_choices_to | SeethedescriptionunderForeignKeyabove. 同ForeignKey的情形 |
symmetrical 对称的 | OnlyusedinthedefinitionofManyToManyFieldsonself.Considerthefollowingmodel: 仅在对自身有多对多关联时定义此选项。考虑下列模型: classPerson(models.Model):friends=models.ManyToManyField("self") WhenDjangoprocessesthismodel,itidentifiesthatithasa ManyToManyFieldonitself,andasaresult,itdoesn'tadda person_setattributetothe Personclass.Instead,the ManyToManyFieldisassumedtobesymmetrical--thatis,ifIamyourfriend,thenyouaremyfriend. 当Django处理这个模型时,它发现Person类有一个指向自身的ManyToManyField多对多关联,因此,它不会添加person_set属性到Person类中。相反的是,ManyToManyField被假定是对称的:也就是说,如果我是你的朋友,则你一定是我的朋友。 IfyoudonotwantsymmetryinManyToManyrelationshipswith self,set symmetricaltoFalse.ThiswillforceDjangotoaddthedescriptorforthereverserelationship,allowing ManyToManyrelationshipstobenon-symmetrical. 如果你不想把指向自身的多对多关联定义为对称的,设置symmetrical=False即可。这会让Django为反向关系添加descriptor,已实现不对称的多对多关系。 |
One-to-onerelationships
一对一关联
Thesemanticsofone-to-onerelationshipswillbechangingsoon,sowedon'trecommendyouusethem.Ifthatdoesn'tscareyouaway,keepreading.在未来的Django版本中,一对一关联的语义即将发生变化,因此我们不建议使用一对一关联。如果这没把你吓坏,继续阅读吧。
Todefineaone-to-onerelationship,useOneToOneField.Youuseitjustlikeanyother
Fieldtype:byincludingitasaclassattributeofyourmodel.
定义一对一关联使用OneToOneField字段即可。
Thisismostusefulontheprimarykeyofanobjectwhenthatobject"extends"anotherobjectinsomeway.
这对于通过和主键建立关联,扩展对象的属性为另一个对象的情形比较有用。
OneToOneFieldrequiresapositionalargument:Theclasstowhichthemodelisrelated.
一对一字段需要一个位置确定的参数:关联模型的类名称。
Forexample,ifyou'rebuildingadatabaseof"places",youwouldbuildprettystandardstuffsuchasaddress,phonenumber,etc.inthedatabase.Then,ifyouwantedtobuildadatabaseofrestaurantsontopoftheplaces,insteadofrepeatingyourself
andreplicatingthosefieldsintheRestaurantmodel,youcouldmake
Restauranthavea
OneToOneFieldtoPlace(becausearestaurant"is-a"place).
举例来说,如果你在建立一个关于“地点”信息的数据库,那么,你一定会建立一些很标准的信息,比如地址,电话号码等。那么如果你要建立另一个餐馆信息的数据库,而这些餐馆是基于上述“地点”信息的,你不需要通过复制地点信息的相关字段到“餐馆”模型中,而只要让“餐馆“建立到“地点”的一对一关联即可(OneToOneField).(因此“餐馆”是“地点”的一种)。
AswithForeignKey,arelationshiptoselfcanbedefinedbyusingthestring
"self"insteadofthemodelname;referencestoas-yetundefinedmodelscanbemadebyusingastringcontainingthemodelname.
和ForeignKey的情形一样,指向自身的一对一关联也可以用"self"来设定指向的模型名称;指向尚未定义的模型时,用字符串形式表示。
ThisOneToOneFieldwillactuallyreplacetheprimarykey
idfield(sinceone-to-onerelationssharethesameprimarykey),andwillbedisplayedasaread-onlyfieldwhenyoueditanobjectintheadmininterface:
OneToOneField会覆盖主键id字段(因此一对一关联共享一个主键),并且会在admin界面中会显示为一个只读字段。
Seethe
One-to-onerelationshipmodelexampleforafullexample.
Metaoptions
在模型类中添加内嵌的classMeta可以定义一些元数据信息:classFoo(models.Model):
bar=models.CharField(maxlength=30)
classMeta:
#...
模型的元数据是除了字段声明之外的其他一些信息,比如排序选项等。
下面是所有Meta选项的列表,所有都不是必须的。
db_table
对应于模型的数据库表的名字:db_table='music_album'
如果不给出这个选项,Django用下列格式自动生成一个表名:app_label
+'_'+
model_class_name.详细的参见下面的"Tablenames"部分。
如果你的表名是SQL保留字,或者包含Python中不允许出现在变量名中的字符(比如连字符),这不要紧。Django会在背后自动处理表名和列名的转换。
get_latest_by
是模型中某个DateField或DateTimeField字段的名称。用于指定在模型的管理器中latest()方法会使用的默认字段。
例子:
get_latest_by="order_date"
Seethe
docsforlatest()formore.
order_with_respect_to
标注当前对象对给定的字段是可排序的。几乎总是被使用在允许按照某个父对象排序的关联对象中,比如,一个Answer对应于一个Question对象,而一个Question可以有多个Answer,而我们关心答案的次序。你可以这样写:classAnswer(models.Model):
question=models.ForeignKey(Question)
#...
classMeta:
order_with_respect_to='question'
ordering
对象的默认排序规则。在获取对象列表时使用:ordering=['-order_date']
这是一个字符串的list或tuple.每个字符串是一个字段名,它们可以有一个可选的前缀'-'字符,表示倒序排列。如果要随机次序排序,可以用"?"前缀。
例如,按pub_date字段升序排列:
ordering=['pub_date']
倒序:
ordering=['-pub_date']
先按pub_date降序,然后按author升序:
ordering=['-pub_date','author']
See
Specifyingorderingformoreexamples.
注意:不管在ordering中写了多少个字段,admin后台只用第一个。
permissions
创建对象时需要写到权限表中的额外的权限。对每一个有admin设置的对象,添加、修改、删除权限会自动创建。下面的例子定义了一个额外的权限:can_deliver_pizzas:permissions=(("can_deliver_pizzas","Candeliverpizzas"),)
Thisisalistortupleof2-tuplesintheformat
(permission_code,human_readable_permission_name).
unique_together
(译注:类似于联合主键)定义哪些字段组合后是必须唯一的:unique_together=(("driver","restaurant"),)
这个被用在Djangoadmin中,同时数据库中也会创建相关的约束。
Thisisalistoflistsoffieldsthatmustbeuniquewhenconsideredtogether.It'susedintheDjangoadminandisenforcedatthedatabaselevel(i.e.,theappropriate
UNIQUEstatementsareincludedinthe
CREATETABLEstatement).
verbose_name
Ahuman-readablenamefortheobject,singular:verbose_name="pizza"
Ifthisisn'tgiven,Djangowilluseamungedversionoftheclassname:
CamelCasebecomescamel
case.
verbose_name_plural
Thepluralnamefortheobject:verbose_name_plural="stories"
Ifthisisn'tgiven,Djangowilluseverbose_name
+"s".
Tablenames
Tosaveyoutime,Djangoautomaticallyderivesthenameofthedatabasetablefromthenameofyourmodelclassandtheappthatcontainsit.Amodel'sdatabasetablenameisconstructedbyjoiningthemodel's"applabel"--thenameyouusedinmanage.py
startapp--tothemodel'sclassname,withanunderscorebetweenthem.
Forexample,ifyouhaveanappbookstore(ascreatedby
manage.py
startappbookstore),amodeldefinedas
classBookwillhaveadatabasetablenamed
bookstore_book.
Tooverridethedatabasetablename,usethedb_tableparameterin
classMeta.
Automaticprimarykeyfields
Bydefault,Djangogiveseachmodelthefollowingfield:id=models.AutoField(primary_key=True)
Thisisanauto-incrementingprimarykey.
Ifyou'dliketospecifyacustomprimarykey,justspecify
primary_key=Trueononeofyourfields.IfDjangoseesyou'veexplicitlyset
primary_key,itwon'taddtheautomatic
idcolumn.
Eachmodelrequiresexactlyonefieldtohaveprimary_key=True.
Adminoptions
IfyouwantyourmodeltobevisibletoDjango'sadminsite,giveyourmodelaninner"classAdmin",likeso:
classPerson(models.Model):
first_name=models.CharField(maxlength=30)
last_name=models.CharField(maxlength=30)
classAdmin:
#Adminoptionsgohere
pass
TheAdminclasstellsDjangohowtodisplaythemodelintheadminsite.
Here'salistofallpossibleAdminoptions.Noneoftheseoptionsarerequired.Touseanadmininterfacewithoutspecifyinganyoptions,use
pass,likeso:
classAdmin:
pass
Addingclass
Admintoamodeliscompletelyoptional.
date_hierarchy
Setdate_hierarchytothenameofaDateFieldor
DateTimeFieldinyourmodel,andthechangelistpagewillincludeadate-baseddrilldownnavigationbythatfield.
Example:
date_hierarchy='pub_date'
fields
Setfieldstocontrolthelayoutofadmin"add"and"change"pages.fieldsisalistoftwo-tuples,inwhicheachtwo-tuplerepresentsa
<fieldset>ontheadminformpage.(A
<fieldset>isa"section"oftheform.)
Thetwo-tuplesareintheformat(name,
field_options),where
nameisastringrepresentingthetitleofthefieldsetand
field_optionsisadictionaryofinformationaboutthefieldset,includingalistoffieldstobedisplayedinit.
Afullexample,takenfromthedjango.contrib.flatpages.FlatPagemodel:
classAdmin:
fields=(
(None,{
'fields':('url','title','content','sites')
}),
('Advancedoptions',{
'classes':'collapse',
'fields':('enable_comments','registration_required','template_name')
}),
)
Thisresultsinanadminpagethatlookslike:
Iffieldsisn'tgiven,Djangowilldefaulttodisplayingeachfieldthatisn'tan
AutoFieldandhas
editable=True,inasinglefieldset,inthesameorderasthefieldsaredefinedinthemodel.
Thefield_optionsdictionarycanhavethefollowingkeys:
fields
Atupleoffieldnamestodisplayinthisfieldset.Thiskeyisrequired.Example:
{
'fields':('first_name','last_name','address','city','state'),
}
Todisplaymultiplefieldsonthesameline,wrapthosefieldsintheirowntuple.Inthisexample,the
first_nameand
last_namefieldswilldisplayonthesameline:
{
'fields':(('first_name','last_name'),'address','city','state'),
}
classes
AstringcontainingextraCSSclassestoapplytothefieldset.Example:
{
'classes':'wide',
}
Applymultipleclassesbyseparatingthemwithspaces.Example:
{
'classes':'wideextrapretty',
}
Twousefulclassesdefinedbythedefaultadmin-sitestylesheetare
collapseandwide.Fieldsetswiththe
collapsestylewillbeinitiallycollapsedintheadminandreplacedwithasmall"clicktoexpand"link.Fieldsetswiththe
widestylewillbegivenextrahorizontalspace.
description
Astringofoptionalextratexttobedisplayedatthetopofeachfieldset,undertheheadingofthefieldset.It'susedverbatim,soyoucanuseanyHTMLandyoumustescapeanyspecialHTMLcharacters(suchasampersands)yourself.js
AlistofstringsrepresentingURLsofJavaScriptfilestolinkintotheadminscreenvia<scriptsrc="">tags.ThiscanbeusedtotweakagiventypeofadminpageinJavaScriptortoprovide"quicklinks"tofillindefaultvaluesforcertainfields.
list_display
Setlist_displaytocontrolwhichfieldsaredisplayedonthechangelistpageoftheadmin.Example:
list_display=('first_name','last_name')
Ifyoudon'tsetlist_display,theadminsitewilldisplayasinglecolumnthatdisplaysthe
__str__()representationofeachobject.
Afewspecialcasestonoteaboutlist_display:
IfthefieldisaForeignKey,Djangowilldisplaythe
__str__()oftherelatedobject.
ManyToManyFieldfieldsaren'tsupported,becausethatwouldentail
executingaseparateSQLstatementforeachrowinthetable.
IfthefieldisaBooleanField,Djangowilldisplayapretty"on"or"off"iconinsteadof
Trueor
False.
Ifthestringgivenisamethodofthemodel,Djangowillcallitanddisplaytheoutput.Thismethodshouldhavea
short_descriptionfunctionattribute,foruseastheheaderforthefield.
Here'safullexamplemodel:
classPerson(models.Model):
name=models.CharField(maxlength=50)
birthday=models.DateField()
classAdmin:
list_display=('name','decade_born_in')
defdecade_born_in(self):
returnself.birthday.strftime('%Y')[:3]+"0's"
decade_born_in.short_description='Birthdecade'
Ifthestringgivenisamethodofthemodel,DjangowillHTML-escapetheoutputbydefault.Ifyou'drathernotescapetheoutputofthemethod,givethemethodan
allow_tagsattributewhosevalueis
True.
Here'safullexamplemodel:
classPerson(models.Model):
first_name=models.CharField(maxlength=50)
last_name=models.CharField(maxlength=50)
color_code=models.CharField(maxlength=6)
classAdmin:
list_display=('first_name','last_name','colored_name')
defcolored_name(self):
return'<spanstyle="color:#%s;">%s%s</span>'%(self.color_code,self.first_name,self.last_name)
colored_name.allow_tags=True
list_display_links
Setlist_display_linkstocontrolwhichfieldsinlist_displayshouldbelinkedtothe"change"pageforanobject.
Bydefault,thechangelistpagewilllinkthefirstcolumn--thefirstfieldspecifiedin
list_display--tothechangepageforeachitem.But
list_display_linksletsyouchangewhichcolumnsarelinked.Set
list_display_linkstoalistortupleoffieldnames(inthesameformatas
list_display)tolink.
list_display_linkscanspecifyoneormanyfieldnames.Aslongasthefieldnamesappearin
list_display,Djangodoesn'tcarehowmany(orhowfew)fieldsarelinked.Theonlyrequirementis:Ifyouwanttouse
list_display_links,youmustdefine
list_display.
Inthisexample,thefirst_nameand
last_namefieldswillbelinkedonthechangelistpage:
classAdmin:
list_display=('first_name','last_name','birthday')
list_display_links=('first_name','last_name')
Finally,notethatinordertouselist_display_links,youmustdefine
list_display,too.
list_filter
Setlist_filtertoactivatefiltersintherightsidebarofthechangelistpageoftheadmin.Thisshouldbealistoffieldnames,andeachspecifiedfieldshouldbeeitheraBooleanField,
DateField,DateTimeFieldor
ForeignKey.
Thisexample,takenfromthedjango.contrib.auth.models.Usermodel,showshowboth
list_displayand
list_filterwork:
classAdmin:
list_display=('username','email','first_name','last_name','is_staff')
list_filter=('is_staff','is_superuser')
Theabovecoderesultsinanadminchangelistpagethatlookslikethis:
(Thisexamplealsohassearch_fieldsdefined.Seebelow.)
list_per_page
Setlist_per_pagetocontrolhowmanyitemsappearoneachpaginatedadminchangelistpage.Bydefault,thisissetto100.
list_select_related
Setlist_select_relatedtotellDjangotouseselect_related()inretrievingthelistofobjectsontheadminchangelistpage.Thiscansaveyouabunchofdatabasequeries.
ThevalueshouldbeeitherTrueor
False.Defaultis
False.
NotethatDjangowilluseselect_related(),regardlessofthissetting,ifoneofthe
list_displayfieldsisa
ForeignKey.
Formoreonselect_related(),see
theselect_related()docs.
ordering
Setorderingtospecifyhowobjectsontheadminchangelistpageshouldbeordered.Thisshouldbealistortupleinthesameformatasamodel'sorderingparameter.
Ifthisisn'tprovided,theDjangoadminwillusethemodel'sdefaultordering.
save_as
Setsave_astoenablea"saveas"featureonadminchangeforms.Normally,objectshavethreesaveoptions:"Save","Saveandcontinueediting"and"Saveandaddanother".If
save_asis
True,"Saveandaddanother"willbereplacedbya"Saveas"button.
"Saveas"meanstheobjectwillbesavedasanewobject(withanewID),ratherthantheoldobject.
Bydefault,save_asissetto
False.
save_on_top
Setsave_on_toptoaddsavebuttonsacrossthetopofyouradminchangeforms.Normally,thesavebuttonsappearonlyatthebottomoftheforms.Ifyouset
save_on_top,thebuttonswillappearbothonthetopandthebottom.
Bydefault,save_on_topissetto
False.
search_fields
Setsearch_fieldstoenableasearchboxontheadminchangelistpage.Thisshouldbesettoalistoffieldnamesthatwillbesearchedwheneversomebodysubmitsasearchqueryinthattextbox.Thesefieldsshouldbesomekindoftextfield,suchas
CharFieldorTextField.
Whensomebodydoesasearchintheadminsearchbox,Djangosplitsthesearchqueryintowordsandreturnsallobjectsthatcontaineachofthewords,caseinsensitive,whereeachwordmustbeinatleastoneof
search_fields.Forexample,if
search_fieldsissetto
['first_name',
'last_name']andausersearchesforjohn
lennon,DjangowilldotheequivalentofthisSQL
WHEREclause:
WHERE(first_nameILIKE'%john%'ORlast_nameILIKE'%john%')
AND(first_nameILIKE'%lennon%'ORlast_nameILIKE'%lennon%')
Managers
AManageristheinterfacethroughwhichdatabasequeryoperationsareprovidedtoDjangomodels.AtleastoneManagerexistsforeverymodelinaDjangoapplication.
ThewayManagerclassesworkisdocumentedinthe
RetrievingobjectssectionofthedatabaseAPIdocs,butthissectionspecificallytouchesonmodeloptionsthatcustomize
Managerbehavior.
Managernames
Bydefault,DjangoaddsaManagerwiththenameobjectstoeveryDjangomodelclass.However,ifyouwanttouse
objectsasafieldname,orifyouwanttouseanameotherthan
objectsforthe
Manager,youcanrenameitonaper-modelbasis.Torenamethe
Managerforagivenclass,defineaclassattributeoftype
models.Manager()onthatmodel.Forexample:
fromdjango.dbimportmodels
classPerson(models.Model):
#...
people=models.Manager()
Usingthisexamplemodel,Person.objectswillgeneratean
AttributeErrorexception,but
Person.people.all()willprovidealistofall
Personobjects.
CustomManagers
YoucanuseacustomManagerinaparticularmodelbyextendingthebaseManagerclassandinstantiatingyourcustom
Managerinyourmodel.
Therearetworeasonsyoumightwanttocustomizea
Manager:toaddextra
Managermethods,and/ortomodifytheinitial
QuerySettheManagerreturns.
AddingextraManagermethods
AddingextraManagermethodsisthepreferredwaytoadd"table-level"functionalitytoyourmodels.(For"row-level"functionality--i.e.,functionsthatactonasingleinstanceofamodelobject--useModelmethods,notcustom
Managermethods.)
AcustomManagermethodcanreturnanythingyouwant.Itdoesn'thavetoreturna
QuerySet.
Forexample,thiscustomManageroffersamethod
with_counts(),whichreturnsalistofall
OpinionPollobjects,eachwithanextra
num_responsesattributethatistheresultofanaggregatequery:
classPollManager(models.Manager):
defwith_counts(self):
fromdjango.dbimportconnection
cursor=connection.cursor()
cursor.execute("""
SELECTp.id,p.question,p.poll_date,COUNT(*)
FROMpolls_opinionpollp,polls_responser
WHEREp.id=r.poll_id
GROUPBY1,2,3
ORDERBY3DESC""")
result_list=[]
forrowincursor.fetchall():
p=self.model(id=row[0],question=row[1],poll_date=row[2])
p.num_responses=row[3]
result_list.append(p)
returnresult_list
classOpinionPoll(models.Model):
question=models.CharField(maxlength=200)
poll_date=models.DateField()
objects=PollManager()
classResponse(models.Model):
poll=models.ForeignKey(Poll)
person_name=models.CharField(maxlength=50)
response=models.TextField()
Withthisexample,you'duseOpinionPoll.objects.with_counts()toreturnthatlistof
OpinionPollobjectswith
num_responsesattributes.
Anotherthingtonoteaboutthisexampleisthat
Managermethodscanaccess
self.modeltogetthemodelclasstowhichthey'reattached.
ModifyinginitialManagerQuerySets
AManager'sbaseQuerySetreturnsallobjectsinthesystem.Forexample,usingthismodel:
classBook(models.Model):
title=models.CharField(maxlength=100)
author=models.CharField(maxlength=50)
...thestatementBook.objects.all()willreturnallbooksinthedatabase.
YoucanoverrideaManager'sbase
QuerySetbyoverridingthe
Manager.get_query_set()method.
get_query_set()shouldreturna
QuerySetwiththepropertiesyourequire.
Forexample,thefollowingmodelhastwo
Managers--onethatreturnsallobjects,andonethatreturnsonlythebooksbyRoaldDahl:
#First,definetheManagersubclass.
classDahlBookManager(models.Manager):
defget_query_set(self):
returnsuper(DahlBookManager,self).get_query_set().filter(author='RoaldDahl')
#ThenhookitintotheBookmodelexplicitly.
classBook(models.Model):
title=models.CharField(maxlength=100)
author=models.CharField(maxlength=50)
objects=models.Manager()#Thedefaultmanager.
dahl_objects=DahlBookManager()#TheDahl-specificmanager.
Withthissamplemodel,Book.objects.all()willreturnallbooksinthedatabase,but
Book.dahl_objects.all()willonlyreturntheoneswrittenbyRoaldDahl.
Ofcourse,becauseget_query_set()returnsa
QuerySetobject,youcanuse
filter(),
exclude()andalltheother
QuerySetmethodsonit.Sothesestatementsarealllegal:
Book.dahl_objects.all() Book.dahl_objects.filter(title='Matilda') Book.dahl_objects.count()
Thisexamplealsopointedoutanotherinterestingtechnique:usingmultiplemanagersonthesamemodel.Youcanattachasmany
Manager()instancestoamodelasyou'dlike.Thisisaneasywaytodefinecommon"filters"foryourmodels.
Forexample:
classMaleManager(models.Manager):
defget_query_set(self):
returnsuper(MaleManager,self).get_query_set().filter(sex='M')
classFemaleManager(models.Manager):
defget_query_set(self):
returnsuper(FemaleManager,self).get_query_set().filter(sex='F')
classPerson(models.Model):
first_name=models.CharField(maxlength=50)
last_name=models.CharField(maxlength=50)
sex=models.CharField(maxlength=1,choices=(('M','Male'),('F','Female')))
people=models.Manager()
men=MaleManager()
women=FemaleManager()
ThisexampleallowsyoutorequestPerson.men.all(),
Person.women.all(),and
Person.people.all(),yieldingpredictableresults.
IfyouusecustomManagerobjects,takenotethatthefirst
ManagerDjangoencounters(inorderbywhichthey'redefinedinthemodel)hasaspecialstatus.Djangointerpretsthefirst
Managerdefinedinaclassasthe"default"
Manager.Certainoperations--suchasDjango'sadminsite--usethedefault
Managertoobtainlistsofobjects,soit'sgenerallyagoodideaforthefirst
Managertoberelativelyunfiltered.Inthelastexample,the
people
Managerisdefinedfirst--soit'sthedefault
Manager.
Modelmethods
Definecustommethodsonamodeltoaddcustom"row-level"functionalitytoyourobjects.WhereasManagermethodsareintendedtodo"table-wide"things,modelmethodsshouldactonaparticularmodelinstance.
Thisisavaluabletechniqueforkeepingbusinesslogicinoneplace--themodel.
Forexample,thismodelhasafewcustommethods:
classPerson(models.Model):
first_name=models.CharField(maxlength=50)
last_name=models.CharField(maxlength=50)
birth_date=models.DateField()
address=models.CharField(maxlength=100)
city=models.CharField(maxlength=50)
state=models.USStateField()#Yes,thisisAmerica-centric...
defbaby_boomer_status(self):
"Returnstheperson'sbaby-boomerstatus."
importdatetime
ifdatetime.date(1945,8,1)<=self.birth_date<=datetime.date(1964,12,31):
return"Babyboomer"
ifself.birth_date<datetime.date(1945,8,1):
return"Pre-boomer"
return"Post-boomer"
defis_midwestern(self):
"ReturnsTrueifthispersonisfromtheMidwest."
returnself.statein('IL','WI','MI','IN','OH','IA','MO')
def_get_full_name(self):
"Returnstheperson'sfullname."
return'%s%s'%(self.first_name,self.last_name)
full_name=property(_get_full_name)
Thelastmethodinthisexampleisaproperty.
Readmoreaboutproperties.
Afewobjectmethodshavespecialmeaning:
__str__
__str__()isaPython"magicmethod"thatdefineswhatshouldbereturnedifyoucallstr()ontheobject.Djangouses
str(obj)inanumberofplaces,mostnotablyasthevaluedisplayedtorenderanobjectintheDjangoadminsiteandasthevalueinsertedintoatemplatewhenitdisplaysanobject.Thus,youshould
alwaysreturnanice,human-readablestringfortheobject's
__str__.Althoughthisisn'trequired,it'sstronglyencouraged.
Forexample:
classPerson(models.Model):
first_name=models.CharField(maxlength=50)
last_name=models.CharField(maxlength=50)
def__str__(self):
return'%s%s'%(self.first_name,self.last_name)
get_absolute_url
Defineaget_absolute_url()methodtotellDjangohowtocalculatetheURLforanobject.Forexample:defget_absolute_url(self):
return"/people/%i/"%self.id
Djangousesthisinitsadmininterface.Ifanobjectdefines
get_absolute_url(),theobject-editingpagewillhavea"Viewonsite"linkthatwilljumpyoudirectlytotheobject'spublicview,accordingto
get_absolute_url().
Also,acoupleofotherbitsofDjango,suchasthesyndication-feedframework,use
get_absolute_url()asaconveniencetorewardpeoplewho'vedefinedthemethod.
It'sgoodpracticetouseget_absolute_url()intemplates,insteadofhard-codingyourobjects'URLs.Forexample,thistemplatecodeisbad:
<ahref="/people/{{object.id}}/">{{object.name}}</a>
Butthistemplatecodeisgood:
<ahref="{{object.get_absolute_url}}">{{object.name}}</a>
(Yes,weknowget_absolute_url()couplesURLstomodels,whichviolatestheDRYprinciple,becauseURLsaredefinedbothinaURLconfandinthemodel.Thisisararecaseinwhichwe'veintentionally
violatedthatprincipleforthesakeofconvenience.Withthatsaid,we'reworkingonanevencleanerwayofspecifyingURLsinamoreDRYfashion.)
ExecutingcustomSQL
FeelfreetowritecustomSQLstatementsincustommodelmethodsandmodule-levelmethods.Theobjectdjango.db.connectionrepresentsthecurrentdatabaseconnection.Touseit,call
connection.cursor()togetacursorobject.Then,call
cursor.execute(sql,
[params])toexecutetheSQLandcursor.fetchone()or
cursor.fetchall()toreturntheresultingrows.Example:
defmy_custom_sql(self):
fromdjango.dbimportconnection
cursor=connection.cursor()
cursor.execute("SELECTfooFROMbarWHEREbaz=%s",[self.baz])
row=cursor.fetchone()
returnrow
connectionand
cursorsimplyusethestandard
PythonDB-API.Ifyou'renotfamiliarwiththePythonDB-API,notethattheSQLstatementin
cursor.execute()usesplaceholders,
"%s",ratherthanaddingparametersdirectlywithintheSQL.Ifyouusethistechnique,theunderlyingdatabaselibrarywillautomaticallyaddquotesandescapingtoyourparameter(s)asnecessary.
(AlsonotethatDjangoexpectsthe"%s"placeholder,
notthe"?"placeholder,whichisusedbytheSQLitePythonbindings.Thisisforthesakeofconsistencyandsanity.)
Afinalnote:IfallyouwanttodoisacustomWHEREclause,youcanjustjustthe
where,
tablesandparamsargumentstothestandardlookupAPI.See
Otherlookupoptions.
Overridingdefaultmodelmethods
AsexplainedinthedatabaseAPIdocs,eachmodelgetsafewmethodsautomatically--mostnotably,
save()and
delete().Youcanoverridethesemethodstoalterbehavior.
Aclassicuse-caseforoverridingthebuilt-inmethodsisifyouwantsomethingtohappenwheneveryousaveanobject.Forexample:
classBlog(models.Model):
name=models.CharField(maxlength=100)
tagline=models.TextField()
defsave(self):
do_something()
super(Blog,self).save()#Callthe"real"save()method.
do_something_else()
Youcanalsopreventsaving:
classBlog(models.Model):
name=models.CharField(maxlength=100)
tagline=models.TextField()
defsave(self):
ifself.name=="YokoOno'sblog":
return#Yokoshallneverhaveherownblog!
else:
super(Blog,self).save()#Callthe"real"save()method.
Modelsacrossfiles
It'sperfectlyOKtorelateamodeltoonefromanotherapp.Todothis,justimporttherelatedmodelatthetopofthemodelthatholdsyourmodel.Then,justrefertotheothermodelclasswhereverneeded.Forexample:frommysite.geography.modelsimportZipCode
classRestaurant(models.Model):
#...
zip_code=models.ForeignKey(ZipCode)
Usingmodels
Onceyouhavecreatedyourmodels,thefinalstepistotellDjangoyou'regoingtousethosemodels.
Dothisbyeditingyoursettingsfileandchangingthe
INSTALLED_APPSsettingtoaddthenameofthemodulethatcontainsyour
models.py.
Forexample,ifthemodelsforyourapplicationliveinthemodule
mysite.myapp.models(thepackagestructurethatiscreatedforanapplicationbythe
manage.py
startappscript),INSTALLED_APPSshouldread,inpart:
INSTALLED_APPS=(
#...
'mysite.myapp',
#...
)
ProvidinginitialSQLdata
DjangoprovidesahookforpassingthedatabasearbitrarySQLthat'sexecutedjustaftertheCREATETABLEstatements.Usethishook,forexample,ifyouwanttopopulatedefaultrecords,orcreateSQLfunctions,automatically.Thehookissimple:Djangojustlooksforafilecalled
<appname>/sql/<modelname>.sql,where
<appname>isyourappdirectoryand
<modelname>isthemodel'snameinlowercase.
InthePersonexamplemodelatthetopofthisdocument,assumingitlivesinanappcalled
myapp,youcouldaddarbitrarySQLtothefile
myapp/sql/person.sql.Here'sanexampleofwhatthefilemightcontain:
INSERTINTOmyapp_person(first_name,last_name)VALUES('John','Lennon');
INSERTINTOmyapp_person(first_name,last_name)VALUES('Paul','McCartney');
EachSQLfile,ifgiven,isexpectedtocontainvalidSQL.TheSQLfilesarepipeddirectlyintothedatabaseafterallofthemodels'table-creationstatementshavebeenexecuted.
TheSQLfilesarereadbythesqlinitialdata,
sqlreset,
sqlallandresetcommandsin
manage.py.Refertothe
manage.pydocumentationformoreinformation.
NotethatifyouhavemultipleSQLdatafiles,there'snoguaranteeoftheorderinwhichthey'reexecuted.Theonlythingyoucanassumeisthat,bythetimeyourcustomdatafilesareexecuted,allthedatabasetablesalreadywillhavebeencreated.
Database-backend-specificSQLdata
There'salsoahookforbackend-specificSQLdata.Forexample,youcanhaveseparateinitial-datafilesforPostgreSQLandMySQL.Foreachapp,Djangolooksforafilecalled<appname>/sql/<modelname>.<backend>.sql,where
<appname>isyourappdirectory,
<modelname>isthemodel'snameinlowercaseand
<backend>isthevalueof
DATABASE_ENGINEinyoursettingsfile(e.g.,
postgresql,
mysql).
Backend-specificSQLdataisexecutedbeforenon-backend-specificSQLdata.Forexample,ifyourappcontainsthefiles
sql/person.sqland
sql/person.postgresql.sqlandyou'reinstallingtheapponPostgreSQL,Djangowillexecutethecontentsof
sql/person.postgresql.sqlfirst,then
sql/person.sql.
相关文章推荐
- Django文档翻译:模型参考(Model Reference)
- django官方文档——模型字段关系参考
- Django文档翻译:模型参考(Model Reference)
- django 1.8 官方文档翻译: 2-3-1 模型实例参考
- Django文档翻译:模型参考(Model Reference)
- Django 事务(参考文档与博客)
- django官方文档——模型与数据库
- Django 2.0 之Models(模型) 官方文档翻译(一)
- Django1.10中文文档—模型
- Django 模型字段参考
- Django 1.10 中文文档------3.2.1 模型Models
- Django 1.0 中文文档-----查询方法参考 value_list
- Django 1.0 中文文档-----查询方法参考
- django 1.8 官方文档翻译: 2-1-4 Model 类参考
- 关于Django出现CSRF token missing or incorrect.问题解决办法(参考官方文档)
- Django 1.10中文文档-第一个应用Part2-模型和管理站点
- Django Rest Framework--oauth实验笔记--参考官方文档
- django 1.8 官方文档翻译: 2-3-2 关联对象参考
- Django,数据模型创建之数据库API参考(转载)
- Django,数据模型创建之数据库API参考