django2

Django 1.7 – 更新后重新阅读文档的拾遗

Preface

最近终于从 Django1.6 版本正式升级 到 Django1.7 版本,其中有很多重大的改变,再加上以前在学习 Django 的时候,半桶水,很多没有详细理解的环节,在这里做一个索引,记录下来。

1.1. Model – F() 表达式

F() 可以在查询、更新模型的时候引用该模型对象原有的值。

引用几个简例说明问题就好了:

第一种(直接字段赋值):
from django import models

page = MyPage.objects.get(pk=1)
page.visit_count = models.F('visit_count') + 1
page.save()

这个例子可以,让 update 的时候才加一,也就是:如果直接让 page.visit_count += 1 的话,在 save 之前如果有其他线程修改了值,累加值的基础还是原来的,这样的实现就不是稳定的。其他自行脑补就好了;

注意这个情况下,事实上是将一个 F() 对象赋值到字段中,而不是一个固定值,而 F() 对象支持用 sql 支持的各类运算符进行运算,例如加减乘除等,运算的结果也是另一种形式 的 F() 对象,这样处理起来就相当的灵活高效。

第二种(批量更新):
from django import models

pages = MyPage.objects.all()
page.update(visit_count=models.F('visit_count') + 1)

如果用 update 方法其实跟上述的做法一样,但是 update 方法是面向 queryset 的,换而言之可以对多个对象同时生效。

第三种(查询条件):
from django import models

pages = MyPage.objects.filter(visit_count__gt=models.F(visit_threshold))

这种情况就很有必要,如果没有的话,这样的查询还真挺难实现。

1.2. Model – 自定义查询器(Custom Lookups [1.7+])

在 Django 的 orm 里面,我们可以通过一系列的查询条件进行转化,这一个规则在这里可以看到(同样是 1.7 新特性):https://docs.djangoproject.com/en/1.7/ref/models/lookups/#module-django.db.models.lookups

举个例子:

Book.objects.filter(author__best_friends__first_name__lower__first3chars__reversed__icontains='bob');

这个分为三部分:

  1. Fields part: author__best_friends__first_name
  2. Transforms part: __lower__first3chars__reversed
  3. Lookup: __icontains (默认为 __exact)

这个意思就是说,这个 Lookup 部分的函数,现在可以自己来扩展,至于怎么扩展,暂时呵呵置之,用到再算。

1.3. Model – 模型的验证

以前用的时候很容易不小心对模型操作的时候会触发错误,例如什么 Foreign Keys 不能为空啊,日期格式不对啊这类种种。为了处理这类的问题,Django 提供一个模型验证的机制,提供一个接口 Model.full_clean) 供我们对模型进行验证。

当然,验证的级别有几种,有些是数据结构层面的,有些是业务层面的,Django 将其分层三层,对应于 full_clean 的三个步骤:

def full_clean(self):
    self.clean_fields()
    self.clean()
    self.validate_unique()

其中 full_clean 可以执行三个验证方法,我们也可以单独调用其中的某个验证方法进行验证。

第一个 clean_fields,是 django 默认实现的验证,会根据设置的字段值有没有超出类定义的范围等等。 第二个 clean,需要由用户自己实现,用来实现某些业务逻辑的验证。 第三个 validate_unique,会检查一些 unique 的字段时候与现有记录的重复。

不得不提的是,这个 full_clean 不会再 Model.save() 的时候被自动触发,因此,实现一个好的 clean 方法,然后记得在 save 之前进行一次 full_clean() 是一个很好的习惯。

1.4. Model – Model.get_absolute_url

在模型定义的时候可以实现一个方法 Model.get_absolute_url()

这可以为模型指定一个 url(一般来说用 View 层的 reverse 方法提取),指定这个模型对象的管理页面 url。这在写模板的时候会相当的方便,可以用 {{ object.get_absolute_url }} 的方法来获取 url,这样具有更好的内聚性和语义性,是一个很值得实现的模型方法。

举个例子:

def get_absolute_url(self):
    from django.core.urlresolvers import reverse
    return reverse('people.views.details', args=[str(self.id)])

2.1. View – url include

关于 url,实际上是一个 django.conf.urls.patterns 产生的类 tuple 对象。

这个的 patterns 对象可以指定公共的前缀,或者在某一条 url 里面 include 另一个 patterns。

至于这个 include 以前只知道 include 另一个 url 模块,这个被 include 的目标模块必须具有同样的格式(在里面定义一个名为 urlpatterns)的对象。

include 也可以获取另一个 patterns 的对象,这就没必要将被 include 的 url 规则放在一个新的 .py 文件中,并且将它命名为 urlpatterns,而可以更加灵活,甚至直接在内部立即构造一个 urlpatterns 嵌在里面:

例如:

from django.conf.urls import include, patterns, url

urlpatterns = patterns('',
    url(r'^(?P<page_slug>\w+)-(?P<page_id>\w+)/', include(patterns('wiki.views',
        url(r'^history/$', 'history'),
        url(r'^edit/$', 'edit'),
        url(r'^discuss/$', 'discuss'),
        url(r'^permissions/$', 'permissions'),
    ))),
)

【转载请附】愿以此功德,回向 >>

原文链接:https://www.huangwenchao.com.cn/2014/10/django-1-7-tips.html【Django 1.7 – 更新后重新阅读文档的拾遗】

发表评论

电子邮件地址不会被公开。 必填项已用*标注