认认真真学Django,从现在开始。

学习资料来源于官方网站:https://docs.djangoproject.com/en/1.6/

1-新建一个models.py

 from django.db import models

 class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)

first_name 和 last_name 是 model 的 fields,对应于生成的数据库中的 column. 上述的Pesron model可以创建如下的数据库的表:

 CREATE TABLE myapp_person (
"id" serial NOT NULL PRIMARY KEY,
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);

注释:

1)-表的名称 myapp_person是从模型元数据中自动生成的,但是可以被重写。详见表的名称。

2)-id这个field也是被自动添加的,也是可以重写的。详见下文中的自动生成基本的key fields.

3)-例子中的CREATE TABLE 语句是用的PostgreSQL 语法,主要还是看你settings.py文件中的settings是怎么写的。

2-使用models

定义了models之后,需要告诉django你要使用它。如果你的例子model是在myapp.models,则在settings.py文件中的settings中的INSTALLED_APPS中添加如下:

INSTALLED_APPS = (
#...
'myapp',
#...
)

添加后,请运行python manage.py syncdb, 这个语句实际上就是创建了数据的表(table),如前所述的CREATE TABLE。

3-Fields

fields 是 models中最重要,也是唯一的必须部分。注意避免跟models API重名了,例如clean, save等。

 from django.db import models

 class Musician(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
instrument = models.CharField(max_length=100) class Album(models.Model):
artist = models.ForeignKey(Musician)
name = models.CharField(max_length=100)
release_date = models.DateField()
num_stars = models.IntegerField()

Field Types:

django用fields来决定以下三件事情:

1)-数据表中的column的数据类型,例如 INTEGER, VARCHAR

2)-渲染一个表单form时默认的HTML中间件(widget)用到的,例如<input type="text">, <select>

3)-django'admin所有的最小的需求,当自动生成表单的时候。

model field reference 中有全部的field信息,也可以自己写field,参考writing custom model fields.

Field Options:

每个field都需要根据特点设定自己的一些参数,例如CharField需要有参数max_length,来规定database中的column的 VARCHAR的大小。

也有一些共同那个的参数:

null:如果True, django会把空值作为NULL存在database中。默认值为False

blank:如果True, 这个field允许是空,默认值为False。注意与null值的不同。null值是纯粹与database相关的,而blank是用来作确认用的,例如,如果一个 field 的 blank=True, 表单 form 的确认就会允许这个 field 不填东西,如果 False 则该处必须填写。(可以理解为,先由 blank 来规定此处是否必填, 再由 null 来取值是空存 NULL 给 database 还是非空)

choices:作为某个field的选项的二元数组。如果给出 choices ,默认的表单中间件就会是 select box, 而不是 text field 了,而且选项会被限制为 choices 中给出的值。

有如下的例子:

YEAR_IN_SCHOOL_CHOICES = (
('FR', 'Freshman'),
('SO', 'Sophomore'),
('JR', 'Junior'),
('SR', 'Senior'),
('GR', 'Graduate'),
)

数组中的第一个值(FR),是被存进 database 中的值,第二个值是在默认 form 或 自己写的ModelChoiceField 中显示的。假设已经写好一个 model 的对象(database中已经存入数据),get_F00_display方法会对有choices的field的数据显示进行处理,例如:

from django.db import models

class Person(models.Model):
SHIRT_SIZES = (
('S', 'Small'),
('M', 'Medium'),
('L', 'Large'),
)
name = models.CharField(max_length=60)
shirt_size = models.CharField(max_length=1, choices=SHIRT_SIZES)
>>> p = Person(name="Fred Flintstone", shirt_size="L")
>>> p.save()
>>> p.shirt_size
u'L'
>>> p.get_shirt_size_display()
u'Large'

default:

每个field的默认值。可以是一个值也可以是一个被调用的对象(callable object)。

help_text:

额外的help文字随着form中间件显示。即使你的这个field不会用在form表单上,这样对于文档也是有用的。

primary_key:

如果为True, 这个field是model的主关键字。如果你的model中没有primary_key=True的field,则django会自动给加上一个类型为IntegerField的field来存储主关键字。所以,除非你要重写默认的primary-key这个实现方法,那么就不需要设定primary_key=True。更多请参考Automatic primary key fields.

unique:

如果为True, 则这个field必须是整个table中的唯一的。

以上只是简单的一个介绍,完备的资料请参考common model field option reference.

Automatic primary key fields(自动生成主关键字的field):

默认的,django给每个model都会自动生成下面的field:

id = models.AutoField(primary_key=True)

这是一个自动增加的主关键字。

如果你要自己定义一个primary key,只要你在你需要的field中令primary_key=Ture,一旦django知道你设定了Field.primary_key, 它就不会自动创建id column了。

每个model都确切的需要有一个field , 其primary_key=True.不论是自己声明的,还是自动添加的。

Verbose field names:

除了ForeignKey, ManyToManyFiled, OneToOneField外,每个field类型,都有一个可选择的参数verbose name,它放在参数列表的第一个。如果verbose name没有指定,django会用field的名字自动生成一个,下面这个例子的verbose name是person's first name:

first_name = models.CharField("person's first name", max_length=30)

而下面的则是first name:

first_name = models.CharField(max_length=30)

ForeignKey, ManyToManyField, OneToOneField的第一个参数是model class的名字,所以他们的verbose_name用法如下:

poll = models.ForeignKey(Poll, verbose_name="the related poll")
sites = models.ManyToManyField(Site, verbose_name="list of sites")
place = models.OneToOneField(Place, verbose_name="related place")

转换不是把verbose_name的首字母大写,django会在需要的时候自动完成大写转换。

Relationships:

显然,相关联的database是依赖于相关联的tables的。django提供了常见的三种database关联方式:many-to-one, many-to-many, one-to-one。

Many-to-one relationships:

用djangol.db.models.ForeignKey来实现many-to-one关系的。像用其他的field类型一样,把ForeignKey当作你的model的类的属性。

ForeignKey需要一个位置的变量(即与谁建立关系)。例子如下:

from django.db import models

class Manufacturer(models.Model):
# ...
pass class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer)
# ...

the model field reference中有更详细的介绍。

一个建议(非必须),ForeignKey field的名字最好跟model的名字一样。也可以自己随便起名字,如下:

class Car(models.Model):
company_that_makes_it = models.ForeignKey(Manufacturer)
# ...

注释:ForeignKey field 接受很多别的变量(the model field reference),这些都是可选变量,可以定义这个relationships怎样工作。更多的db的API可以参照Making querise.

Many-to-many relationships:

用ManyToManyField来定义many-to-many关系,像前文所述来使用。也需要一个位置的变量(与谁建立关系)。例如,一个Pizza有多个Topping对象,也就是一个Topping对象对应多个Pizza,同时每个Pizza有多个topping对应,即多对多的关系,可以如下使用:

from django.db import models

class Topping(models.Model):
# ...
pass class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)

获取更多参考Making querise.

同样建议使用相同名字来命名field,如上例,toppings.

一般来讲,ManyToManyField实例应该是在form表单中编辑的,在上例中,toppings放在Pizza中(而不是Topping有一个pizzas这样的ManyToManyField),这是由于pizaa含有toppings更自然一些,像上例中这样设定,Pizza这个表单会让用户从中选择toppings.

同样有很多非必须的变量,请参照Making querise.

更多many-to-many relationships的fields:

标准的ManyToManyField 对于简单的处理够用了,如果需要在两个model之间进行data的一些联系的话,需要更多的方法。

例如,建立一个app来追踪音乐家和其所属群组间的关系。人与组之间是个多对多的关系,而还有很多的其他数据想要搜集,例如某人加入某组的日期。可以在Group中通过through方法来绑定进来一个Membership,建立起联系,如下:

from django.db import models

class Person(models.Model):
name = models.CharField(max_length=128) # On Python 3: def __str__(self):
def __unicode__(self):
return self.name class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership') # On Python 3: def __str__(self):
def __unicode__(self):
return self.name class Membership(models.Model):
person = models.ForeignKey(Person)
group = models.ForeignKey(Group)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)

注意,Membership中,用ForeignKey来建立与Person和Group的关系。

对于中间model有几个条件:

1)-中间model有且只有一个target model来做ForeignKey

2)-中间model有且只有一个source model来做ForeignKey

3)-唯一的例外是有一个model是他自身的many-to-many relationship, 这样的中间model就可以有2个一样的ForeignKey的model了,但是起作用不同,一个作为target,一个作为source.

4)-上一条情况下,要令symmetrical=False,见the model field reference

下面是一个实例来理解这个through是如何工作的:

>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
[<Person: Ringo Starr>]
>>> ringo.group_set.all()
[<Group: The Beatles>]
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
[<Person: Ringo Starr>, <Person: Paul McCartney>]

与正常的多对多fields不同,不能用add, create, assignment来建立关系:

# THIS WILL NOT WORK
>>> beatles.members.add(john)
# NEITHER WILL THIS
>>> beatles.members.create(name="George Harrison")
# AND NEITHER WILL THIS
>>> beatles.members = [john, paul, ringo, george]

因为用了through,写了一个中间model,所以就不能用add等方法来直接给多对多的关系来写入数据了,必须要用中间model来把target和source的数据连到一起(姑且这样理解),也就是说,没有额外数据->不用through->不用写中间model->可以用add等方法直接操作数据。

同样的原因导致remove()方法不能用,但是可以用clear()方法,如下:

>>> # Beatles have broken up
>>> beatles.members.clear()
>>> # Note that this deletes the intermediate model instances
>>> Membership.objects.all()
[]

一旦通过中间model(through)建立了多对多关系型数据库,就可以用query去访问了。

注意体会下面4段代码:

# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
[<Group: The Beatles>]
# Find all the members of the Beatles that joined after 1 Jan 1961
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
[<Person: Ringo Starr]
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
u'Needed a new drummer.'
>>> ringos_membership = ringo.membership_set.get(group=beatles)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
u'Needed a new drummer.'

One-to-one relationships(一对一关系):

用OneToOneField来定义这种关系。当利用主键(primarykey)来拓展另一个model的时候,这种一对一关系型就显得比较重要,也可以说是较常用的。

one-to-one也需要一个位置的参数(与谁连接)。例如你要建立一个places的database,可能包括address, phone等信息,然后在它之上想要加一个school的database,就可以在school的model中添加OneToOneFiled(Places),实际上就是一种继承,毫无疑问是one-to-one的了。

更多信息请参考 the model field reference

很多地方理解不深,代码照搬官方指南,如有错误热盼指正。

django学习之Model(一)的更多相关文章

  1. django学习之Model(二)

    继续(一)的内容: 1-跨文件的Models 在文件头部import进来,然后用ForeignKey关联上: from django.db import models from geography.m ...

  2. django学习之Model(五)MakingQuery

    接着上篇. 10-一次更新多个对象 有时想要对QuerySet中的所有对象的某一个field来设定一个值,这时候可以像下边这样用update(): # Update all the headlines ...

  3. django学习之Model(三)QuerySet

    接下来主要学习Models中的Making queries 写好models.py后,django会自动提供一个数据库的抽象API,来实现CRUD(create, retrieve, update, ...

  4. django学习之Model(四)MakingQuery

    上一篇写到MakingQuey中的filter,本篇接着来. 10)-扩展多值的关系 如果对一个ManyToManyField或ForeignKey的表进行filter过滤查询的话,有2中方法可以用. ...

  5. django 学习之model操作(想细化)

    一.Field选项 null=True 数据库为空 blank=True admin相关为空 choices:choices意味着静态数据的变化不会太大. db_column: 用于此字段的数据库的列 ...

  6. 07.Django学习之model进阶

    一 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句. >>> Entry.objects.all( ...

  7. Django学习之model进阶

    一 QuerySet 可切片 使用Python 的切片语法来限制查询集记录的数目 .它等同于SQL 的LIMIT 和OFFSET 子句.   >>> Entry.objects.al ...

  8. django学习之——Model

    打开 settings.py 找到 DATABASE  配置我们的数据库,(MySQL) # Database # https://docs.djangoproject.com/en/1.7/ref/ ...

  9. Django学习笔记(三)—— 型号 model

    疯狂暑期学习 Django学习笔记(三)-- 型号 model 參考:<The Django Book> 第5章 1.setting.py 配置 DATABASES = { 'defaul ...

随机推荐

  1. eclipse修改java代码后报错: java.lang.OutOfMemoryError: PermGen space

    由于在eclipse中运行项目后,我们又重新修改了某个java类,导致tomcat会重新加载这个项目所有的class.jar,多次加载后由于分配的存储空间有限,就导致了:java.lang.OutOf ...

  2. Oracle包Package调用Package

    Package左侧文件: create or replace package CALL_DETAILS is strdatarange varchar2(1) := '1'; numrow_num n ...

  3. How Many Answers Are Wrong(并查集)

    Description TT and FF are ... friends. Uh... very very good friends -________-b FF is a bad boy, he ...

  4. 杭电oj find your present (2)

    <span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255) ...

  5. Laravel 5.1 ACL权限控制 二 之策略类

    随着应用逻辑越来越复杂,要处理的权限越来越多,将所有权限定义在AuthServiceProvider显然不是一个明智的做法,因此Laravel引入了策略类,策略类是一些原生的PHP类,和控制器基于资源 ...

  6. APACHE的伪静态设置

    1.配置httpd.conf #LoadModule rewrite_module modules/mod_rewrite.so 开启 LoadModule rewrite_module module ...

  7. 使用BeautifulSoup解析XML文档

    有200多个XML文档,每个文档类似如下: <?xml version="1.0"?> <VehicleInfo> <FileHeader> & ...

  8. FPGA知识大梳理(三)verilogHDL语法入门(2)知识汇总

    1,时序逻辑.将上次的练习修改成时序逻辑会如何设计. always @ (posedge clock) 2,block 与unblocking  A,有clock的always中通常使用nonbloc ...

  9. cygwin org/apache/zookeeper/KeeperException

    以前用cdh3-0.20的hbase,在windows下面直接启动就行了,但是最近安装0.94以上的,就不行了. 报标题的错误,搜遍网络,几乎都是要加HBASE_CLASSPATH的,后来看老外的文章 ...

  10. Android 进程和线程

    进程和线程 如果某个应用程序组件是第一次被启动,且这时应用程序也没有其他组件在运行,则Android系统会为应用程序创建一个包含单个线程的linux进程.默认情况下,同一个应用程序的所有组件都运行在同 ...