创建完Model之后, Django 自动为你提供一套数据库抽象层的API,利用它可以完成创建,提取,更新,删除对象的操作。

以下面的Model为例:

class Blog(models.Model):
name = models.CharField(max_length=100)
tagline = models.TextField() # On Python 3: def __str__(self):
def __unicode__(self):
return self.name class Author(models.Model):
name = models.CharField(max_length=50)
email = models.EmailField() # On Python 3: def __str__(self):
def __unicode__(self):
return self.name class Entry(models.Model):
blog = models.ForeignKey(Blog)
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() # On Python 3: def __str__(self):
def __unicode__(self):
return self.headline

创建Creating objects

>>> b = Blog(name='Beatles Blog', tagline='All the latest Beatles news.')
>>> b.save()

Django 用一种很直观的表达方式将Python对象和数据表对应起来:一个model类对应一张数据表,一个model实例对应表中的某一行记录。

以创建对象为例:只要将关键字参数传递给model类,然后调用save()保存到数据库即可

这段代码就会在幕后执行一条INSERT SQL语句。除非你显式地调用save()方法,否则Django不会保存到数据库中。

你可以使用create()方法一次完成新建并保存对象的操作。

修改Saving changes to objects

>> b5.name = 'New name'
>> b5.save()

Saving ForeignKey and ManyToManyField fields

更新ForeignKey字段和保存普通字段没什么差别;只是在给字段分配对象时要注意对象类型一定要正确:

>>> entry = Entry.objects.get(pk=1)
>>> cheese_blog = Blog.objects.get(name="Cheddar Talk")
>>> entry.blog = cheese_blog
>>> entry.save()

更新ManyToManyField就有些不同;要在字段上使用add()方法来添加关系:

>>> joe = Author.objects.create(name="Joe")
>>> entry.authors.add(joe)

一次添加多个:

>>> 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)

检索对象 (Retrieving objects)

要检索数据库中的对象,就要为你的model 类构造一个查询集QuerySet。一个QuerySet就代表数据库中的一组数据。它可以有一个或很多个,也可以通过filter根据给定的参数对数据集做进一步筛选。在SQL术语中,QuerySet相当于SELECT语句,filter相当于WHERE或LIMIT这样的限定从句。

检索所有的对象

all_entries = Entry.objects.all()

使用过滤器filter检索特定的对象

filter(**kwargs)

返回满足筛选条件的新QuerySet

exclude(**kwargs)

返回不满足筛选条件的新QuerySet

Entry.objects.filter(pub_date__year=2006)

链式过滤:

>>> Entry.objects.filter(
... headline__startswith='What'
... ).exclude(
... pub_date__gte=datetime.date.today()
... ).filter(
... pub_date__gte=datetime(2005, 1, 30)
... )

查询一个单独的对象

>>> one_entry = Entry.objects.get(pk=1)

注意当使用get查询时若对象不存在会产生DoesNotExist异常。

QuerySet是惰性的

QuerySets是惰性的。创建 QuerySet 的动作不涉及任何数据库操作。你可以一直添加过滤器,在这个过程中,Django不会执行任何数据库查询,除非QuerySet被执行。

切片

可以用python的数组切片语法来限制你的QuerySet以得到一部分结果。它等价于SQL中的LIMIT和OFFSET。

例如,下面的这个例子返回前五个对象:

>>> Entry.objects.all()[:5]

Django 不支持对查询集做负数索引。

跨关系查询

Django 提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用双下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的 model 为止。

Blog.objects.filter(entry__authors__name='Lennon')

要注意的是如果跨关系对象有多个符合条件,被查询对象会返回多次:

Blog.objects.filter(entry__headline='note')

上面如果有个Blog链接多个headline为note的Entry对象,此Blog会返回多次。

跨一对多/多对多关系

对于包含在同一个filter()中的筛选条件,查询集要同时满足所有筛选条件。而对于连续的filter(),查询集的范围是依次限定的。但对于跨一对多/多对多关系查询来说,在第二种情况下,筛选条件针对的是主model所有的关联对象,而不是被前面的filter()过滤后的关联对象。

这听起来会让人迷糊,举个例子会讲得更清楚。要检索这样的 blog:它要关系一个大标题中含有 "Lennon" 并且在2008年出版的entry(这个entry同时满足这两个条件),可以这样写:

Blog.objects.filter(entry__headline__contains='Lennon',
entry__pub_date__year=2008)

要检索另外一种 blog:它关联一个大标题含有"Lennon"的 entry ,又关联一个在2008年出版的 entry (一个entry的大标题含有Lennon,同一个或另一个entry是在2008年出版的)。可以这样写:

Blog.objects.filter(entry__headline__contains='Lennon').filter(
entry__pub_date__year=2008)

上述原则同样适用于exclude():一个单独exclude()中的所有筛选条件都是作用于同一个实例 (如果这些条件都是针对同一个一对多/多对多的关系)。连续的filter()或exclude()却根据同样的筛选条件,作用于不同的关联对象。

Filters can reference fields on the model

class F

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供F()来做这样的比较。F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值。

例如:要查询回复数(comments)大于广播数(pingbacks)的博文(blog entries),可以构造一个 F() 对象在查询中引用评论数量:

>>> from django.db.models import F
>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks'))

Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。例如,要找到广播数等于评论数两倍的博文,可以这样修改查询语句:

>>> Entry.objects.filter(n_comments__gt=F('n_pingbacks') * 2)

要查找阅读数量小于评论数与广播数之和的博文,查询如下:

>>> Entry.objects.filter(rating__lt=F('n_comments') + F('n_pingbacks'))

你也可以在 F() 对象中使用双下划线做跨关系查询。F() 对象使用双下划线引入必要的关联对象。例如,要查询博客(blog)名称与作者(author)名称相同的博文(entry),查询就可以这样写:

>>> Entry.objects.filter(authors__name=F('blog__name'))

对于Date和datetime域,可以加减timedelta对象。

返回出版3天以后修改的博文:

>>> from datetime import timedelta
>>> Entry.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))

F对象现在也支持位运算(bitand(),bitor()):

>>> F('somefield').bitand(16)

主键查询的简捷方式 (The pk lookup shortcut)

为使用方便考虑,Django 用pk代表主键"primary key"。

以Blog为例, 主键是id字段,所以下面三个语句都是等价的:

>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
>>> Blog.objects.get(pk=14) # pk implies id__exact

在LIKE语句中转义百分号%和下划线_ (Escaping percent signs and underscores in LIKE statements)

字段筛选条件相当于LIKE SQL语句 (iexactcontainsicontainsstartswithistartswithendswith 和 iendswith) ,它会自动转义两个特殊符号,百分号(%)和下划线(_)。(在LIKE语句中,百分号%表示多字符匹配,而下划线_表示单字符匹配。)

这就意味着我们可以直接使用这两个字符,而不用考虑他们的SQL语义。例如,要查询大标题中含有一个百分号%的entry:

>>> Entry.objects.filter(headline__contains='%')

Django会处理转义,下划线_和百分号%的处理方式相同,Django都会自动转义。

缓存和查询

每个QuerySet都包含一个缓存,以减少对数据库的访问。要编写高效代码,就要理解缓存是如何工作的。

一个QuerySet时刚刚创建的时候,缓存是空的。 QuerySet 第一次运行时,会执行数据库查询,接下Django就在QuerySet的缓存中保存查询的结果,并根据请求返回这些结果(比如,后面再次调用这个 QuerySet 的时候)。再次运行 QuerySet 时就会重用这些缓存结果。

要牢住上面所说的缓存行为,否则在使用 QuerySet 时可能会给你造成不小的麻烦。例如,创建下面两个 QuerySet ,并对它们求值,然后释放:

>>> print([e.headline for e in Entry.objects.all()])
>>> print([e.pub_date for e in Entry.objects.all()])

这就意味着相同的数据库查询将执行两次,事实上读取了两次数据库。而且,这两次读出来的列表可能并不完全相同,因为存在这种可能:在两次读取之间,某个 Entry 被添加到数据库中,或是被删除了。

要避免这个问题,只要简单地保存QuerySet然后重用即可:

>>> queryset = Entry.objects.all()
>>> print([p.headline for p in queryset]) # 对查询集求值.
>>> print([p.pub_date for p in queryset]) # 使用缓存.

When querysets are not cached

查询集并不总是缓存结果,当查询集执行部分查询时,会先检查缓存,如果它没有被填充,部分查询返回的结果不会被缓存。这意味着,使用切片查询不会填充缓存。

例如,重复的切片查询每次都会访问数据库:

>>> queryset = Entry.objects.all()
>>> print queryset[5] # 访问数据库
>>> print queryset[5] # 再次访问数据库

但是,如果整个查询集已经被求值,切片查询会使用缓存:

>>> queryset = Entry.objects.all()
>>> [entry for entry in queryset] # 查询数据库
>>> print queryset[5] # 使用缓存
>>> print queryset[5] # 使用缓存

下面是一些会填充缓存的操作:

>>> [entry for entry in queryset]
>>> bool(queryset)
>>> entry in queryset
>>> list(queryset) 

用Q对象实现复杂查找 (Complex lookups with Q objects)

在filter() 等函式中关键字参数彼此之间都是 "AND" 关系。如果你要执行更复杂的查询(比如,实现筛选条件的OR关系),可以使用Q对象。

Q对象(django.db.models.Q)是用来封装一组查询关键字的对象。

例如,下面这个Q对象封装了一个单独的 LIKE 查询:

from django.db.models import Q
Q(question__startswith='What')

Q 对象可以用 & 和 | 运算符进行连接。当某个操作连接两个 Q 对象时,就会产生一个新的等价的 Q 对象。

例如,下面这段语句就产生了一个Q,这是用 "OR" 关系连接的两个"question__startswith" 查询:

Q(question__startswith='Who') | Q(question__startswith='What')

上面的例子等价于下面的 SQL WHERE 从句:

WHERE question LIKE 'Who%' OR question LIKE 'What%'

你可以用 & 和 | 连接任意多的Q对象,而且可以用括号分组。Q 对象也可以用 ~ 操作取反,而且普通查询和取反查询(NOT)可以连接在一起使用:

Q(question__startswith='Who') | ~Q(pub_date__year=2005)

每种查询函式(比如 filter(), exclude(), get()) 除了能接收关键字参数以外,也能以位置参数的形式接受一个或多个 Q 对象。如果你给查询函式传递了多个 Q 对象,那么它们彼此间都是 "AND" 关系。例如:

Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6))
)

... 大体可以翻译为下面的 SQL:

SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2005-05-02' OR pub_date = '2005-05-06')

查找函式可以混用 Q 对象和关键字参数。查询函式的所有参数(Q 关系和关键字参数) 都是 "AND" 关系。但是,如果参数中有 Q 对象,它必须排在所有的关键字参数之前。例如:

Poll.objects.get(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')

是一个有效的查询。但下面这个查询虽然看上去和前者等价:

# 无效查询
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))

但这个查询却是无效的。

对象比较 (Comparing objects)

要比较两个对象,就和Python 一样,使用双等号运算符:==。实际上比较的是两个model的主键值。

以上面的Entry为例,下面两个语句是等价的:

>>> some_entry == other_entry
>>> some_entry.id == other_entry.id

如果model的主键名称不是id,也没关系。Django会自动比较主键的值,而不管他们的名称是什么。例如,如果一个model的主键字段名称是name,那么下面两个语句是等价的:

>>> some_obj == other_obj
>>> some_obj.name == other_obj.name

对象删除(Deleting objects)

删除方法就是delete()。它运行时立即删除对象而不返回任何值。例如:

e.delete()

你也可以一次性删除多个对象。每个QuerySet 都有一个delete() 方法,它一次性删除 QuerySet 中所有的对象。

例如,下面的代码将删除 pub_date 是2005年的 Entry 对象:

Entry.objects.filter(pub_date__year=2005).delete()

要牢记这一点:无论在什么情况下,QuerySet 中的 delete() 方法都只使用一条 SQL 语句一次性删除所有对象,而并不是分别删除每个对象。如果你想使用在model中自定义的delete() 方法,就要自行调用每个对象的delete方法。(例如,遍历 QuerySet,在每个对象上调用 delete()方法),而不是使用QuerySe 中的 delete()方法。

在Django删除对象时,会模仿SQL约束ON DELETE CASCADE的行为,换句话说,删除一个对象时也会删除与它相关联的外键对象。例如:

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

要注意的是: delete() 方法是QuerySet上的方法,但并不适用于 Manager 本身。这是一种保护机制,是为了避免意外地调用Entry.objects.delete() 方法导致 所有的 记录被误删除。如果你确认要删除所有的对象,那么你必须显式地调用:

Entry.objects.all().delete()

复制Copying model instances

复制对象并没有内置的函数,最简单的情况,将pk设为None。

blog = Blog(name='My blog', tagline='Blogging is easy')
blog.save() # blog.pk == 1 blog.pk = None
blog.save() # blog.pk == 2

如果使用继承的话,情况会复杂一点:

class ThemeBlog(Blog):
theme = models.CharField(max_length=200) django_blog = ThemeBlog(name='Django', tagline='Django is easy', theme='python')
django_blog.save() # django_blog.pk == 3

需要将pk和id都设为None:

django_blog.pk = None
django_blog.id = None
django_blog.save() # django_blog.pk == 4

这样写是不会复制关系对象的,要复制关系对象,还需要一点代码:

entry = Entry.objects.all()[0] # some previous entry
old_authors = entry.authors.all()
entry.pk = None
entry.save()
entry.authors = old_authors # saves new many2many relations

一次更新多个对象 (Updating multiple objects at once)

有时你想对QuerySet中的所有对象,一次更新某个字段的值。这个要求可以用 update() 方法完成。例如:

# Update all the headlines with pub_date in 2007.
Entry.objects.filter(pub_date__year=2007).update(headline='Everything is the same')

这种方法仅适用于非关系字段和ForeignKey外键字段。更新非关系字段时,传入的值应该是一个常量。更新ForeignKey字段时,传入的值应该是你想关联的那个类的某个实例。例如:

>>> b = Blog.objects.get(pk=1)
# Change every Entry so that it belongs to this Blog.
>>> Entry.objects.all().update(blog=b)

update() 方法也是即时生效,返回与查询匹配的行数(可能不等于被更新的行数,因为有些行已经是新值,不需要被更新)。 在QuerySet进行更新时,唯一的限制就是一次只能更新一个数据表,就是当前 model 的主表。你可以尝试更新关联表和与此类似的操作,但是只有主表的条目被更新:

>>> b = Blog.objects.get(pk=1)
# Update all the headlines belonging to this Blog.
>>> Entry.objects.select_related().filter(blog=b).update(headline='Everything is the same')

要小心的是:update() 方法是直接翻译成一条SQL语句的。因此它是直接地一次完成所有更新。它不会调用你的 model 中的save() 方法,也不会发出pre_save 和post_save信号(这些信号在调用 save() 方法时产生)。如果你想保存QuerySet中的每个对象,并且调用每个对象各自的save() 方法,那么你不必另外多写一个函式。只要遍历这些对象,依次调用 save() 方法即可:

for item in my_queryset:
item.save()

在调用update时可以使用 F() 对象来把某个字段的值更新为另一个字段的值。这对于自增记数器是非常有用的。例如,给所有的博文 (entry) 的广播数 (pingback) 加一:

>>> Entry.objects.all().update(n_pingbacks=F('n_pingbacks') + 1)

但是,与 F() 对象在查询时所不同的是,在filter 和 exclude子句中,你不能在 F() 对象中引入关联关系(NO-Join),你只能引用当前 model 中要更新的字段。如果你在 F() 对象引入了Join 关系object,就会抛出 FieldError 异常:

# THIS WILL RAISE A FieldError
>>> Entry.objects.update(headline=F('blog__name'))

对象关联(Related objects)

当你定义在 model 定义关系时 (例如,ForeignKey, OneToOneField, 或 ManyToManyField),model 的实例自带一套很方便的API以获取关联的对象。

以最上面的 models 为例,一个 Entry 对象e能通过blog属性获得相关联的Blog对象:e.blog。

Django也提供反向获取关联对象的API,就是由从被关联的对象得到其定义关系的主对象。例如,一个Blog类的实例b对象通过entry_set属性得到所有相关联的Entry对象列表:

b.entry_set.all()

一对多关系(One-to-many relationships)

正向(Forward)

如果一个model有一个ForeignKey字段,我们只要通过使用关联model的名称就可以得到相关联的外键对象。

>>> e = Entry.objects.get(id=2)
>>> e.blog # Returns the related Blog object.

你可以设置和获得外键属性。正如你所期望的,改变外键的行为并不引发数据库操作,直到你调用 save()方法时,才会保存到数据库。例如:

>>> e = Entry.objects.get(id=2)
>>> e.blog = some_blog
>>> e.save()

如果外键字段 ForeignKey 有一个 null=True 的设置(它允许外键接受空值 NULL),你可以赋给它空值 None 。例如:

>>> e = Entry.objects.get(id=2)
>>> e.blog = None
>>> e.save() # "UPDATE blog_entry SET blog_id = NULL ..

在一对多关系中,第一次正向获取关联对象时,关联对象会被缓存。其后根据外键访问时这个实例,就会从缓存中获得它。例如:

>>> e = Entry.objects.get(id=2)
>>> print(e.blog) # 访问数据库
>>> print(e.blog) # 使用缓存

要注意的是,QuerySet 的select_related() 方法提前将所有的一对多关系放入缓存中。例如:

>>> e = Entry.objects.select_related().get(id=2)
>>> print(e.blog) # 使用缓存
>>> print(e.blog) # 使用缓存

逆向关联(Following relationships "backward")

如果model有一个ForeignKey外键字段,那么外联model的实例可以通过访问Manager来得到所有相关联的源model的实例。默认情况下,这个Manager被命名为 FOO_set, 这里面的 FOO 就是源 model 的小写名称。这个Manager返回QuerySets,它是可过滤和可操作的,在上面 "对象获取(Retrieving objects)" 有提及。

>>> b = Blog.objects.get(id=1)
>>> b.entry_set.all() # Returns all Entry objects related to Blog. # b.entry_set is a Manager that returns QuerySets.
>>> b.entry_set.filter(headline__contains='Lennon')
>>> b.entry_set.count()

你可以通过在ForeignKey() 的定义中设置related_name的值来覆写FOO_set 的名称。例如,如果 Entry model 中做一下更改: blog = ForeignKey(Blog, related_name='entries'),那么接下来就会如我们看到这般:

>>> b = Blog.objects.get(id=1)
>>> b.entries.all() # Returns all Entry objects related to Blog.
# b.entries is a Manager that returns QuerySets.
>>> b.entries.filter(headline__contains='Lennon')
>>> b.entries.count()

ForeignKey Manager 还有如下一些方法。下面仅仅对它们做一个简短介绍:

add(obj1, obj2, ...)

将某个特定的 model 对象添加到被关联对象集合中。

create(**kwargs)

创建并保存一个新对象,然后将这个对象加被关联对象的集合中,然后返回这个新对象。

remove(obj1, obj2, ...)

将某个特定的对象从被关联对象集合中去除。

clear()

清空被关联对象集合。

想一次指定关联集合的成员,那么只要给关联集合分配一个可迭代的对象即可。它可以包含对象的实例,也可以只包含主键的值。例如:

b = Blog.objects.get(id=1)
b.entry_set = [e1, e2]

在这个例子中,e1 和 e2 可以是完整的 Entry 实例,也可以是整型的主键值。

如果 clear() 方法是可用的,在迭代器(上例中就是一个列表)中的对象加入到 entry_set 之前,已存在于关联集合中的所有对象将被清空。如果 clear() 方法 不可用,原有的关联集合中的对象就不受影响,继续存在。

这一节提到的每一个 "reverse" 操作都是实时操作数据库的,每一个添加,创建,删除操作都会及时保存将结果保存到数据库中。

多对多关系(Many-to-many relationships)

在多对多关系的任何一方都可以使用 API 访问相关联的另一方。多对多的 API 用起来和上面提到的 "逆向" 一对多关系关系非常相象。

唯一的差虽就在于属性的命名: ManyToManyField 所在的 model (为了方便,我称之为源model A) 使用字段本身的名称来访问关联对象;而被关联的另一方则使用 A 的小写名称加上 '_set' 后缀(这与逆向的一对多关系非常相象)。

下面这个例子会让人更容易理解:

e = Entry.objects.get(id=3)
e.authors.all() # Returns all Author objects for this Entry.
e.authors.count()
e.authors.filter(name__contains='John') a = Author.objects.get(id=5)
a.entry_set.all() # Returns all Entry objects for this Author.

与 ForeignKey 一样, ManyToManyField 也可以指定 related_name。在上面的例子中,如果 Entry 中的 ManyToManyField 指定 related_name='entries',那么接下来每个 Author 实例的 entry_set 属性都被 entries 所代替。

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

相对于多对一关系而言,一对一关系是非常简单的。如果你在 model 中定义了一个 OneToOneField 关系,那么你就可以用这个字段的名称做为属性来访问其所关联的对象。

class EntryDetail(models.Model):
entry = models.OneToOneField(Entry)
details = models.TextField() ed = EntryDetail.objects.get(id=2)
ed.entry # Returns the related Entry object.

与 "reverse" 查询不同的是,一对一关系的关联对象也可以访问Manager对象,但是这个Manager表现一个单独的对象,而不是一个列表:

e = Entry.objects.get(id=2)
e.entrydetail # returns the related EntryDetail object

如果一个空对象被赋予关联关系,Django就会抛出一个DoesNotExist 异常。

和你定义正向关联所用的方式一样,类的实例也可以赋予逆向关联关系:

e.entrydetail = ed

关系中的反向连接是如何做到的?

其他对象关系的映射(ORM)需要你在关联双方都定义关系。而 Django 的开发者则认为这违背了 DRY 原则 (Don't Repeat Yourself),所以Django只需要你在一方定义关系即可。

但仅由一个model类并不能知道其他model 类是如何与它关联的,除非是其他model也被载入,那么这是如何办到的?

答案就在于 INSTALLED_APPS 设置中。任何一个 model 在第一次调用时,Django 就会遍历所有的 INSTALLED_APPS 的所有models,并且在内存中创建中必要的反向连接。本质上来说,INSTALLED_APPS 的作用之一就是确认 Django 完整的model范围。

在关联对象上的查询(Queries over related objects)

包含关联对象的查询与包含普通字段值的查询都遵循相同的规则。为某个查询指定某个值的时候,你可以使用一个类实例,也可以使用对象的主键值。

例如,如果你有一个 Blog 对象 b ,它的 id=5, 下面三个查询是一样的:

Entry.objects.filter(blog=b) # Query using object instance
Entry.objects.filter(blog=b.id) # Query using id from instance
Entry.objects.filter(blog=5) # Query using id directly

直接使用SQL(Falling back to raw SQL)

如果你发现某个 SQL 查询用 Django 的数据库映射来处理会非常复杂的话,你可以使用直接写 SQL 来完成。

建议的方式是在你的model自定义方法或是自定义model的manager方法来运行查询。虽然Django不要求数据操作必须在model层中执行。但是把你的商业逻辑代码放在一个地方,从代码组织的角度来看,也是十分明智的。

最后,要注意的是,Django的数据操作层仅仅是访问数据库的一个接口。你可以用其他的工具,编程语言,数据库框架来访问数据库。对你的数据库而言,没什么是非用 Django 不可的。

Django Model数据访问Making queries的更多相关文章

  1. django model数据 时间格式

    from datetime import datetime dt = datetime.now() print '时间:(%Y-%m-%d %H:%M:%S %f): ' , dt.strftime( ...

  2. Django Model 数据表

    Django Model 定义语法 版本:1.7主要来源:https://docs.djangoproject.com/en/1.7/topics/db/models/ 简单用法 from djang ...

  3. 16. Django基础数据访问

    如果我们想使用Django对数据库进行访问,我们可以使用django自带的shell. 进入blog目录,打开cmd命令窗口,输入python manage.py shell,如下图所示: 插入数据 ...

  4. Django学习之四:Django Model模块

    目录 Django Model 模型 MODEL需要在脑子里记住的基础概念 区分清楚,必须不能混淆的 class Meta 内嵌元数据定义类 简单model创建实例 数据源配置 接着通过models在 ...

  5. 【转】Django Model field reference学习总结

    Django Model field reference学习总结(一) 本文档包含所有字段选项(field options)的内部细节和Django已经提供的field types. Field 选项 ...

  6. django 用imagefiled访问图片

    使用FileField和ImageField时,我们有几个步骤: 在settings.py中设置MEDIA_ROOT和MEDIA_URL MEDIA_ROOT:一个绝对路径,Django根据它知道文件 ...

  7. Django model对象接口

    Django model查询 # 直接获取表对应字段的值,列表嵌元组形式返回 Entry.objects.values_list('id', 'headline') #<QuerySet [(1 ...

  8. Django Model 基础

    程序涉及到数据库相关操作时,一般都会这样: 创建数据库,设计表结构和字段 使用 pymysql 来连接数据库,并编写数据访问层代码 业务逻辑层去调用数据访问层执行数据库操作 import pymysq ...

  9. Django Model 定义语法

    简单用法 from django.db import models class Person(models.Model): first_name = models.CharField(max_leng ...

随机推荐

  1. 设计模式------STRATEGY(策略模式)

    http://blog.csdn.net/wuzhekai1985/article/details/6665197.仅供参考. 策略模式:实现替换功能,如cache替换算法:当发生Cache缺失时,C ...

  2. web开发常用图片格式

    web开发常用图片格式有:gif   jpg/jpeg    png gif:图片压缩率高,可以显示动画,但是只能显示256色,可能造成颜色丢失. jpg:图片压缩率高(有损压缩),可以用小文件来显示 ...

  3. sql server 查询字符串指定字符出现的次数

    这里提取指定符串"A"在字段中的出现次数SQL为: select len(keyword)-len(replace(keyword, 'A', ' ')) from 表 原理:用r ...

  4. IOS-7步学会用代理

    代理:又叫委托 自己不能去办的事委托给别人去办 之前学过的 UIAlertView UITextField都是使用了代理 反向传值代理 代理Block 写代理的步骤 需要帮忙的人(请求帮代饭的人) 1 ...

  5. [翻译][MVC 5 + EF 6] 7:加载相关数据

    原文:Reading Related Data with the Entity Framework in an ASP.NET MVC Application 1.延迟(Lazy)加载.预先(Eage ...

  6. MVC——分页控件

    不管是什么类型的网站,分页都是必不可少的功能实现.在这里记录一下我自己接触过的分页控件: 一. MvcPager控件(记得项目里添加MvcPager.dll的引用) 这里面比较常用的就 ——@Html ...

  7. 七牛云覆盖上传 php

    使用七牛云过程中遇到了需要上传覆盖的情况,最终解决,分享给大家. 七牛云sdk上传示例中是这样写的 <?php require_once 'path_to_sdk/vendor/autoload ...

  8. HaProxy+keepalived实现负载均衡

    HAProxy提供高可用性.负载均衡以及基于TCP和HTTP应用的代理,支持虚拟主机,它是免费.快速并且可靠的一种解决方案.HAProxy特别适用于那些负载特大的web站点,这些站点通常又需要会话保持 ...

  9. php QQ登录

    基本原理: 就是获取唯一的openid,此值只要与自己数据库表中的值对应,就说明是此用户, 没有,则说明是新用户,其实就是找对应关系,因为openid与QQ号是唯一对应关系 放置按钮: 如在首页 in ...

  10. Winform TreeView控件技巧

    在开发的时候经常使用treeview控件来显示组织结构啊,目录结构啊,通常会结合属性checkedboxs,来做选中,取消的操作下面是一个选中,取消的小例子,选中节点的时候,如果节点存在子节点,可以选 ...