免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2042 | 回复: 0
打印 上一主题 下一主题

常用的模型层API整理 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-08-04 10:05 |只看该作者 |倒序浏览

                                                1.基本数据访问
publisher_list = Publisher.objects.all()
后台相当于执行了一条SQL语句SELECT语句
2.插入和更新数据
p = Publisher(name='Apress',
...         address='2855 Telegraph Ave.',
...         city='Berkeley',
...         state_province='CA',
...         country='U.S.A.',
...         website='http://www.apress.com/')
利用构造函数得到一个对象。相当于传统MVC中给SET方法了!
p.save()
后台相当于执行了一个INSERT语句的!
p.id   
插入之后会返回其自增长的ID值。即类似于PHP中的一个函数的!
接着:
p.name = 'Apress Publishing'
p.save()
后台相当于执行了一个UPDATE语句的!
3.选择对象
Publisher.objects.all()
相当于SQL语句:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher;
4.数据过滤
Publisher.objects.filter(name="Apress Publishing")
相当于SQL语句:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
WHERE name = 'Apress Publishing';
条件性过滤处理
Publisher.objects.filter(country="U.S.A.", state_province="CA")
相当于:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
WHERE country = 'U.S.A.' AND state_province = 'CA';
两个条件查询的!
实现SQL中的模糊查询的方法
Publisher.objects.filter(name__contains="press")
相当于的SQL语句如下:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
WHERE name LIKE '%press%';
这些都是放到视图层处理。得到数据集或更新表。如果有涉及到多表联合查询的话就要考虑使用原生CURSOR
5。获取单个对象
Publisher.objects.get(name="Apress Publishing")
这样,就返回了单个对象,而不是列表(更准确的说,QuerySet)。所以,如果结果是多个对象,会导致抛出异常:
相当于用户登录系统这种唯一性的时候就可以考虑使用这种方法的!只有唯一的一个值了!
6.数据排序
Publisher.objects.order_by("name")
等价的SQL语句:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
ORDER BY name;
对于排序也可以放到模型层去处理。指定默认的排序方式即可!
在这种情况下,Django让你可以指定模型的缺省排序方式
**class Meta:**
        **ordering = ["name"]**
这样的话就会默认会有排序操作的!
同时做排序与过滤
Publisher.objects.filter(country="U.S.A.").order_by("-name")
慢慢来构造出来比较复杂的SQL查询语句了!
其:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
WHERE country = 'U.S.A'
ORDER BY name DESC;
7.限制返回的数据(返回limit)
Publisher.objects.all()[0]
相当的SQL语句:
SELECT
    id, name, address, city, state_province, country, website
FROM book_publisher
ORDER BY name
LIMIT 1;
限制返回的记录个数
8.要删除对象,只需简单的调用对象的 delete() 方法
p = Publisher.objects.get(name="Addison-Wesley")
得到单独的一条记录
p.delete()
通常更好的方法是给你的数据模型添加激活标志。你可以只在激活的对象中查找,对于不需要的对象,将激活字段值设为 False ,
而不是删除对象。这样,如果一旦你认为做错了的话,只需把标志重设回来就可以了。
为了确保数据的完整性!不能进行物理性删除的!
9.修改数据库表结构
修改表结构也就是按照正确的顺序修改各种Python代码和数据库本身(如果你需要修改表结构的话就要这样处理了。手工修改PYTHON代码与数据库本身)
9.1添加字段
   先在数据库中添加列,然后再改变模型中对应的字段。
就是修改数据库结构与模型中的内容的!
首先,在开发环境中执行下面的步骤(也就是说,不是在发布服务器上):
把这个字段添加到你的模型中.(第一步:定义到模型层中去新增一个字段出来)
运行 manage.py sqlall [yourapp] 会看到模型的新的 CREATE TABLE
语句。注意新的字段的列定义。(查看到具体的SQL语句)
启动您的数据库交互shell(也就是 psql 或 mysql , 或者您也可以使用 manage.py dbshell )。 执行一个 ALTER TABLE
语句,添加您的新列。
4. (可选)用 manage.py shell
启动Python交互式shell,并通过引入模型并选择表验证新的字段已被正确添加(比如, MyModel.objects.all()[:5] )。
删除、修改字段都是一样的操作。先修改模型层的代码然后再
(目前系统中不考虑使用多对多或一对多的情况的)
10.删除模型
将此模型从你的 models.py
文件里删除,并且重启Web服务器。
然后数据库那边直接不要
数据库API实现ORM必备!
1.自增主键
b2 = Blog(name='Cheddar Talk', tagline='Thoughts on cheese.')
b2.save()
b2.id           #php有类似的功能
2.获取对象
blogs = Blog.objects.filter(author__name__contains="Joe")
QuerySet
代表了你的数据库中的对象的一个集合。它根据所给参数可以构造若干个 过滤器 来缩小这个集合的规模。用SQL术语来讲,一个 QuerySet 就相当于一个 SELECT 语句,过滤器相当于诸如 WHERE 或者 LIMIT 的限定语
3.缓存与查询集
为了减少数据库访问次数,每个 QuerySet 包含一个缓存,要写出高效的代码,理解这一点很重要。
在刚被创建的 QuerySet 中,缓存是空的。当 QuerySet 第一次被赋值,就是执行数据库查询的时候,Django会把查询结果保存到这个 QuerySet 的缓存中,并返回请求结果(例如,
QuerySet
迭代结束的时候,就会返回下一条记录)。再次使用 QuerySet 的值的话会重复使用缓存中的内容。
非常地跟memecherad相似哦!
实现的方法如下:
queryset = Poll.objects.all() #得到一个queryset数据集能够存在缓存
print [p.headline for p in queryset] # Evaluate the query set.
4.过滤器
加一些过滤条件。用 filter() 和
exclude() 方法可以实现这样的功能
5.级联过滤器
对我们的结果集进一步过滤处理!
细化过的 QuerySet 本身就是一个
QuerySet ,所以可以进一步细化。
>>> qs = Entry.objects.filter(headline__startswith='What')
会得到一个结果集出来!
>>> qs = qs..exclude(pub_date__gte=datetime.datetime.now())
在此基础上进一步过滤处理!
6.限量查询集
可以用Python的数据切片的语法来限定 QuerySet 的结果数量,这和SQL中的 LIMIT 和 OFFSET 语句是一样的。
比如,这句返回前五个条目( LIMIT 5 ):
>>> Entry.objects.all()[:5]
filter(**lookup)
返回一个新的 QuerySet ,包含匹配参数lookup的对象。
exclude(**kwargs)
返回一个新的 QuerySet ,包含不匹配参数kwargs的对象。
order_by(*fields)
默认情况下,会返回一个按照models的metadata中的``ordering``选项排序的``QuerySet``(请查看附录B)。你可以调用``order_by()``方法按照一个特定的规则进行排序以覆盖默认的行为:
要使用随机的顺序,使用 "?"
,比如:
>>> Entry.objects.order_by('?')  随机排序处理操作!
7.select_related()
e = Entry.objects.get(id=5)
b = e.blog  这样的话还会再去请求一次数据库服务器的!
如果这样写的:e = Entry.objects.select_related().get(id=5)
然后:
b = e.blog 就不会再去请求服务器了!
1.
get(**lookup)get() raises a DoesNotExist exception if
an object wasnt found for the given parameters (如果没有记录存在就会有异常出现)
from django.core.exceptions import ObjectDoesNotExist
>>> try:
...     e = Entry.objects.get(id=3)
...     b = Blog.objects.get(id=1)
... except ObjectDoesNotExist:
...     print "Either the entry or blog doesn't exist."
create(**kwargs)
这个快捷的方法可以一次性完成创建并保证对象。它让你完成了下面两个步骤:
>>> p = Person(first_name="Bruce", last_name="Springsteen")
>>> p.save()
into a single line:
>>> p = Person.objects.create(first_name="Bruce", last_name="Springsteen")
传统的方法是通过
1.构造出来对象
2.调用save方法处理。现在不用直接使用create即可!
try:
    obj = Person.objects.get(first_name='John', last_name='Lennon')
except Person.DoesNotExist:
    obj = Person(first_name='John', last_name='Lennon', birthday=date(1940, 10, 9))
    obj.save()
为了不保存重复的记录可以这样处理哦!
这种方法如可以使用如下的方法代替出来!
obj, created = Person.objects.get_or_create(
    first_name = 'John',
    last_name  = 'Lennon',
    defaults   = {'birthday': date(1940, 10, 9)}
)
2.count()
返回记录集的个数。即QuerySet的个数!
Entry.objects.count()
Entry.objects.filter(headline__contains='Lennon').count()
可以返回当前数据集的记录条数!
相当于: SELECT COUNT(*)
3.latest(field_name=None)
Entry.objects.latest('pub_date')
能够查询出来最新的记录!
4.exact>>> Blog.objects.get(id__exact=14) # Explicit form
>>> Blog.objects.get(id=14) # __exact is implied
这两个语句实现的功能是一样的!
contains (区分大小写关系)
执行严格区分大小写的内容包含检测:
Entry.objects.get(headline__contains='Lennon')
这将会匹配标题为``’Today Lennon honored’`` 的,而不匹配
``
‘today lennon
honored’
``

icontains (不区分大小写)
执行一个忽略大小写的内容包含检测:
>>> Entry.objects.get(headline__icontains='Lennon')
与``contains``不同, icontains 会 匹配 'today lennon honored' 。
gt, gte, lt, and lte
这些即大于,大于或等于,小于,小于或等于:
>>> Entry.objects.filter(id__gt=4)
>>> Entry.objects.filter(id__lt=15)
>>> Entry.objects.filter(id__gte=0)
过滤的时候使用的逻辑连接词
in
筛选出包含在给定列表中的数据:
Entry.objects.filter(id__in=[1, 3, 4])
这会返回所有ID为1,3,或4的条目。
startswith
区分大小写的开头匹配:
>>> Entry.objects.filter(headline__startswith='Will')
这将返回标题Will he run?和Willbur named judge,但是不会返回Who is Will?
和will found in crypt.
istartswith
Performs a case-insensitive starts-with:
>>> Entry.objects.filter(headline__istartswith='will')
range
Performs an inclusive range check:
>>> start_date = datetime.date(2005, 1, 1)
>>> end_date = datetime.date(2005, 3, 31)
>>> Entry.objects.filter(pub_date__range=(start_date, end_date))
查询日期的时候能够介于两个时间值之间处理的!
isnull
使用``True``或``False``,则分别相当于SQL语句中的``IS NULL``和``IS NOT
NULL``:
>>> Entry.objects.filter(pub_date__isnull=True)
回归原始的SQL操作
如果你需要写一个SQL查询,但是用Django的数据库映射来实现的话太复杂了,那么你可以考虑使用原始的SQL语句。
解决这个问题的比较好的方法是,给模块写一个自定义的方法或者管理器方法来执行查询。尽管在Django中,数据库查询在模块中没有任何存在的
必要性 ,但是这种解决方案使你的数据访问在逻辑上保持一致,而且从组织代码的角度讲也更灵活。操作指南见附录B。
最后,请记住Django的数据库层仅仅是访问数据库的一个接口,你可以通过其他的工具、编程语言或者数据库框架来访问数据库,它并不是特定于Django使用的。
可以考虑使用ORM也可以使用原生SQL语句!

               
               
               
               

本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/84280/showart_2017070.html
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP