原文地址:https://docs.djangoproject.com/en/1.11/topics/db/models/#fields
文章目录
1.简介
一个model 对应于数据中的一个表(A model class represents a database table, and an instance of that class represents a particular record in the database table.)
示例:
from django.db import models
class Person(models.Model): # 定义的模型需要继承 models.Model类
first_name = models.CharField(max_length=30)
last_name = models.CharField(max_length=30)
其中,first_name与last_name都是模型中的字段,也就是对应数据库中表的域。上述模型对应与数据库中入下表结构:
CREATE TABLE myapp_person ( #该表的名称 “myapp_person” 是自动从某些模型元数据中派生出来
"id" serial NOT NULL PRIMARY KEY, #一个 id 字段会被自动添加,但是这种行为可以被改写
"first_name" varchar(30) NOT NULL,
"last_name" varchar(30) NOT NULL
);
2.字段
2.1 字段类型
在model中的每个域都是某种Field类的实例。Django使用Filed类型来定义如下信息:
- 在数据库中表字段的存储类型,例如:integer,varchar,text;
- 默认的HTML widget类型,例如:
<input type="text"> 或<select>
- 校验的最低要求;
Django内置的field 完整列表:https://docs.djangoproject.com/en/1.11/ref/models/fields/#model-field-types
当然,Django 也支持自定义类型:参考:https://docs.djangoproject.com/en/1.11/howto/custom-model-fields/
2.1.1 filed 选项
每种field 都有一定的可选参数。例如对于CharFiled,可指定该字符串的最大长度。例如:
name=models.CharField(max_length=255)
可选参数包括:
- null :是否存储空值;
- blank: 是否允许空值;
- choices: 定义field值的范围。如果指定该值,对form默认绑定的widget为select box;
- default :定义默认值;
- help_text :显示的帮助信息;
- primary_key:
- unique
2.1.2 自增主键字段
如果你不指定主键的化,Django 默认为每个model 增加如下字段,作为主键:
id = models.AutoField(primary_key=True)
3. 定义多表之间的关系
Django支持如下几种关系:
- 多对一
- 多对多
- 一对一
下面分别说明:
3.1 多对一关系
在多的一端,增加一个ForeignKey域来参数关系。例如:
from django.db import models
class Manufacturer(models.Model):
# ...
pass
class Car(models.Model):
manufacturer = models.ForeignKey(Manufacturer, on_delete=models.CASCADE)
# ...
建议将该字段的名字定义成对应的model名的小写形式。
3.2 多对多关系
使用ManyToManyField来定义。建议将多对多关系字段名字使用对应模型名称的复数形式。将该字段放在多对多的那一端都无所谓,但是你只能将其放在一端模型中。一般来说,将该字段放在可以经常编辑的一端。例如,你可以定义你的pizza上有多上配料。
例如:
每种披萨上会有多种配料,每种配料也对应多种披萨,则可定义如下模型:
from django.db import models
class Topping(models.Model):
# ...
pass
class Pizza(models.Model):
# ...
toppings = models.ManyToManyField(Topping)
另外,在多对多关系中,如果关联关系也有特定的属性,如会员、俱乐部场景中,会员入会,在建立关系时,也需要存储入会的关系属性,如入会时间等。这时,可以通过第三个模型来描述,例如:
from django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self): # __unicode__ on Python 2
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self): # __unicode__ on Python 2
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)
这时,需要通过through
字段指明关系中间表模型。
3.3 一对一关系
通过 OneToOneField字段声明字段。例如:
from django.db import models
class Place(models.Model):
name = models.CharField(max_length=50)
address = models.CharField(max_length=80)
def __str__(self): # __unicode__ on Python 2
return "%s the place" % self.name
class Restaurant(models.Model):
place = models.OneToOneField(
Place,
on_delete=models.CASCADE,
primary_key=True,
)
serves_hot_dogs = models.BooleanField(default=False)
serves_pizza = models.BooleanField(default=False)
def __str__(self): # __unicode__ on Python 2
return "%s the restaurant" % self.place.name
class Waiter(models.Model):
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE)
name = models.CharField(max_length=50)
def __str__(self): # __unicode__ on Python 2
return "%s the waiter at %s" % (self.name, self.restaurant)
4.model 操作
实例模型:
from django.db import models
class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField()
def __str__(self):
return self.name
class Author(models.Model):
name = models.CharField(max_length=200)
email = models.EmailField()
def __str__(self):
return self.name
class Entry(models.Model):
blog = models.ForeignKey(Blog, on_delete=models.CASCADE)
headline = models.CharField(max_length=255)
body_text = models.TextField()
pub_date = models.DateField()
mod_date = models.DateField()
authors = models.ManyToManyField(Author)
n_comments = models.IntegerField()
n_pingbacks = models.IntegerField()
rating = models.IntegerField()
def __str__(self):
return self.headline
通过objects,你可以做:
1. 创建、保存对象到数据库
(执行insert 语句)
p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
或是:
b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
b.save()
2. 对数据库中的数据进行修改
(执行update语句)
b5.name = 'New name'
b5.save()
3. 对model中负责数据进行修改
对model的Foreign key类型或是 ManyToManyField字段的update操作
(1)对于Foreign key的update和普通字段是一样的操作。
>>> from blog.models import Blog, Entry
>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()
(2)对于ManyToManyField的update:
>>> john = Author.objects.create(name="John")
>>> paul = Author.objects.create(name="Paul")
>>> george = Author.objects.create(name="George")
>>> ringo = Author.objects.create(name="Ringo")
>>> entry.authors.add(john, paul, george, ringo)
4. 查询语句
通过QuerySet来构建查询,获取数据。
关于Query Set,可查看:https://blog.csdn.net/youyou1543724847/article/details/85940565
在Django中,QuerySet表示数据库中数据的集合。QuerySet可包括0个或多个filter,用于缩小数据范围。QuerySet表示一个select语句,而filter表示where或是limit。
(1)直接获取所有元素
all_entries = Entry.objects.all()
(2)过滤数据
Entry.objects.filter(pub_date__year=2006)
常用的过滤函数包括:
filter(**kwargs):返回满足条件的
exclude(**kwargs):返回不满足条件的
get(**kargs):返回满足条件的记录。当记录不存在或是多条都满足时,会抛出异常
其中**kwargs参数形式如下:
field__lookuptype=value (field为model中的字段名字;当field为外键时,可以添加 _id后缀)
例如:
Entry.objects.filter(pub_date__lte='2006-01-01')
等价于:
SELECT * FROM blog_entry WHERE pub_date <= '2006-01-01';
支持的lookuptype包括:exact,iexact, contains,icontians, startswith, endwith等。
当需要在多表关系中进行查询搜索时(对于sql的join),字段名字格式为本model的字段名字__相关连的model中的字段名字(field name of related fields across models, separated by double underscores, until you get to the field you want)。例如:
Entry.objects.filter(blog__name='Beatles Blog')
该关系扩展可以是多级的(即多表联合查询)
另外,也支持反向搜索(使用小写的model名称)。例如:获取所有的blog,该blog至少有一个entry的headline包含‘Lennon’(blog和author通过entry表存储管理关系)
Blog.objects.filter(entry__headline__contains='Lennon')
另外,需要注意的是对QuerySet进行filter处理后返回的还是一个QuerySet对象,因此,可将filter 连着使用,形成filter 链。如:
>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime.date(2005, 1, 30)
... )
注意:某次对QuerySet进行filter时,都会重新构建一个新的QuerySet。
Django中的QuerySet是懒加载的,即构建一个QuerySet不会立即导致数据中的操作(不会立即和数据库交互,完成数据查询),直到QuerySet 被Evaluate,才会导致数据库查询操作(关于什么操作导致QuerySet被evaluate,请查看:https://docs.djangoproject.com/zh-hans/2.1/ref/models/querysets/#when-querysets-are-evaluated)。
5. 删除对象
delete语句
e.delete()
批量删除:
Entry.objects.filter(pub_date__year=2005).delete()
5. 其他
5.1 model 元数据
通过使用内部类的形式来给model 添加元数据。例如:
from django.db import models
class Ox(models.Model):
horn_length = models.IntegerField()
class Meta:
ordering = ["horn_length"]
verbose_name_plural = "oxen"
db_table =“ox_info"
更多信息,请查看:https://docs.djangoproject.com/zh-hans/2.1/ref/models/options/
5.2 model 属性
5.2.1 model.objects
model的最重要的属性就是Manager。Django通过Manager接口和来数据库进行交互,完成从数据库中获取数据实例的能力。如果没有自定义新的Manager的话,默认的Manger属性名字就是objects。
5.3 model 方法
通过自定义一些模型方法(行级别的)来对表中的某条数据进行操作(相对而言,Manager的方法是表级别的,即对某张表进行整体操作,如表数据过滤)