django学习之Model(一)

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

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

1-新建一个models.py

1 from django.db import models
2 
3 class Person(models.Model):
4     first_name = models.CharField(max_length=50)
5     last_name = models.CharField(max_length=50)

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

1 CREATE TABLE myapp_person (
2     "id" serial NOT NULL PRIMARY KEY,
3     "first_name" varchar(30) NOT NULL,
4     "last_name" varchar(30) NOT NULL
5 );

注释:

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等。

 1 from django.db import models
 2 
 3 class Musician(models.Model):
 4     first_name = models.CharField(max_length=50)
 5     last_name = models.CharField(max_length=50)
 6     instrument = models.CharField(max_length=100)
 7 
 8 class Album(models.Model):
 9     artist = models.ForeignKey(Musician)
10     name = models.CharField(max_length=100)
11     release_date = models.DateField()
12     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

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

原文地址:https://www.cnblogs.com/ee2213/p/3910178.html