Django里的模型是对数据库对表的一次封装,是应用业务与数据之间的桥梁。
python
在上一节,咱们在mysite/blog/models.py中建立了BlogPost这个Model。sql
from django.db import models class BlogPost(models.Model): title = models.CharField(max_length=150) body = models.TextField() timestamp = models.DateTimeField()
BlogPost里用了CharField,TextField, TextField域。难道就只有这三种,不可能!shell
以下,我列出了其它的Field,并代表了它们的继承关系:数据库
Field |--AutoField |--BooleanField |--CharField | |--EmailField | |--SlugField | `--URLField |--DateField | `--DateTimeField |--DecimalField |--FilePathField |--FloatField |--IntegerField | |--BigIntegerField | |--PositiveIntegerField | `--PositiveSmallIntegerField |--IPAddressField |--GenericIPAddressField |--NullBooleanField |--TextField |--TimeField `--BinaryField
别问我是怎么知道的。看源码呀~在 django/db/models/fields/__init__.py 中定义。
django
若是你是去看了这个文件,那么不难知道 Field类的__init__(self)函数带了不少参数吧。json
Field类在构造的时候能够指定如下参数:
verbose_name=None #显示名
name=None #域名
primary_key=False #是否为主键
max_length=None #在CharFiled中用到
unique=False #是否惟一
blank=False
null=False #是否容许为空
db_index=False
rel=None
default=NOT_PROVIDED
editable=True #是否可编辑
serialize=True
unique_for_date=None
unique_for_month=None
unique_for_year=None
choices=None
help_text=''
db_column=None
db_tablespace=None
auto_created=False
validators=[]
error_messages=None
models.ForeignKey
~~~~~~~~~~~~~~~~~
能够用models.ForeignKey()指定外键,如在models.py中:
_______________________________________________
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(Author) #定义外键
-----------------------------------------------
注:Author必须在Book以前定义。若是不想有这样的限制,那么在ForeignKey()中以
"Author"字符串对象做为参数传入。
_______________________________________________
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey('Author') # 注意,这里用的是类名称,而不是类
# 自己
class Author(models.Model):
name = models.CharField(max_length=100)
-----------------------------------------------
在外键的支持下,能够实现数据库中多表查询的功能。好比查到与该书做者的全部书:
________________________________________________
book_title = "C++程序设计"
this_book = Book.objects.get(title=book_title) # 找到title为"C++程序设计"
# 的book对象this_book
author = this_book.author # 由this_book得到做者对象author
books = author.book_set.all() # 根据author得到全部的书,获得books数组
^^^^^^^^
for book in books: # 打印每一本书
print(book.title)
------------------------------------------------
在Book中加入了ForeignKey('Author')以后,Django会在Author对象中添加一个属性
叫:book_set。
可是,若是用的是ForeignKey('Author', related_name="books"),也就是告诉django
在Author端对应的属性名叫"books",而再也不是django默认的"book_set"了。
models.ManyToManyField
~~~~~~~~~~~~~~~~~~~~~~
顾名思意,就是多对多域。当两个表存在多对多的关系时,这就颇有用。
好比:一名做者可能写了多本书,一本书也可能由多名做者共同编写。
_______________________________________________
class Author(models.Model):
name = models.CharField(max_length=100)
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ManyToManyField(Author)
-----------------------------------------------
其实,Django为咱们建了另外一个book_book_author的表。
以下为book_book_author的建立明细:
__________________________________________________________________________
sqlite> .schema book_book_author
CREATE TABLE "book_book_author" (
"id" integer NOT NULL PRIMARY KEY,
"book_id" varchar(50) NOT NULL,
"author_id" integer NOT NULL REFERENCES "book_author" ("id"),
UNIQUE ("book_id", "author_id")
);
CREATE INDEX "book_book_author_36c249d7" ON "book_book_author" ("book_id");
CREATE INDEX "book_book_author_e969df21" ON "book_book_author" ("author_id");
--------------------------------------------------------------------------
那么,这种多对多的关系在view中怎么使用呢?
models.OneToOneField一对一关系
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
模型继承关系
~~~~~~~~~~~~
在模型类中定义Meta内部类,并指定Meta.abstract = True时,表示该模型为抽象模型
,即只用来被子模型类派生而不生成实际的模型。
这时,Django在./manage.py syncdb时就不会为该模型建立表。好比:Person为人的模
型,里面定义了人的基本属性。Student与Teacher继承于它。在同步数据库时,咱们不
能为Person建立一张表吧。以下:
________________________________________________
class Person(models.Model):
name = models.CharField(max_length=50)
gender = models.PositiveSmallIntegerField()
birthday = models.DateField()
def __unicode__(self):
return self.name
class Meta:
abstract = True
class Teacher(Person):
pass
class Student(Person):
pass
------------------------------------------------
对了,记得给模型定义__unicode__方法。这用利于让admin知道模型对象该怎么显示。
Meta嵌套类
~~~~~~~~~~
在前面有两处提到了Meta类,一处是在blog排序时,另外一处就是上面的虚继承。
Meta的用法是嵌套在Model类里面,用于说明附加的信息。
数据查询
~~~~~~~~
每一个Model都有一个objects属性,而这个objects属性具备如下方法:
Model.objects.all() # 获取全部对象的QuerySet
Model.objects.filter() # 获取知足条件的对象的QuerySet
Model.objects.exclude() # 获取不知足条件的对象的QuerySet
Model.objects.get() # 获取单个符合条件的对象的QuerySet
QuerySet会将查询条件转换成SQL语句,并得到执行结果。
示例:
____________________________________________________________
# 找出John Doe
Person.objects.filter(last="Doe").filter(first="John")
# 找出逾期不还的书
today = datetime.now()
overdue_books = book_queryset.filter(due_date__lt = today)
^^^^
意恩是:due_date < today
# 注:除了__lt,还有:__gt
# 查询结果排序,并提取前5个
all_sorted_first = Person.objects.all().order_by('first')[:5]
# 使用select_related执行简单的join操做
Person.objects.all().select_related('address', depth=1)
-------------------------------------------------------------
用Q()让条件灵活组合
~~~~~~~~~~~~~~~~~~~
使用Q()来封装查询条件,与 & | ~ 配合,造成组合条件。
_______________________________________________________________________
Person.objects.filter(
Q(last="Doe") |
(Q(last="Smith") & Q(first="John") & ~Q(middle__startswith="W"))
)
first_names = ['John', 'Jane', 'Jeremy']
first_name_keywords = Q()
for name in first_names:
first_name_keywords = first_name_keywords | Q(first=name)
specific_does = Person.objects.filter(last="Doe").filter(first_name_keywords)
----------------------------------------------------------------------
用extra()提供其它的功能
~~~~~~~~~~~~~~~~~~~~~~~
## select提供简单数据
# SELECT age, (age > 18) as is_adult FROM myapp_person;
Person.objects.all().extra(select={'is_adult': "age > 18"})
## where提供查询条件
# SELECT * FROM myapp_person WHERE first||last ILIKE 'jeffrey%';
Person.objects.all().extra(where=["first||last ILIKE 'jeffrey%'"])
## table链接其它表
# SELECT * FROM myapp_book, myapp_person WHERE last = author_last
Book.objects.all().extra(table=['myapp_person'], where=['last = author_last'])
## params添参数
# !! 错误的方式 !!
first_name = 'Joe' # 若是first_name中有SQL特定字符就会出现漏洞
Person.objects.all().extra(where=["first = '%s'" % first_name])
# 正确方式
Person.objects.all().extra(where=["first = '%s'"], params=[first_name])
# ^^^^^^^^^^^^^^^^^^^^^
数据库导入导出
~~~~~~~~~~~~~~
# 将book应用的数据导出到book.json文件中去
./manage.py dumpdata --indent=4 book > book.json
自定义SQL查询
~~~~~~~~~~~~~
若是前面的QuerySet没法知足特殊的查询要求,那就让咱们本身来指定select语句吧。
以下:
_______________________________________________________________________
from django.db import connection
cursor = connection.cursor()
cursor.execute("SELECT first, last FROM myapp_person WHERE last='Doe'")
doe_rows = cursor.fetchall()
for row in doe_rows:
print("%s %s" % (row[0], row[1]))
-----------------------------------------------------------------------
数组