一个普通例子:

todos = Todo.objects.filter(owner=request.user).filter(is_done=False).filter(priority=1)

弊端:

首先,代码冗长,正式的项目中,将会更加复杂。

其次,泄露实现细节。比如代码中的is_done是BooleanField,如果改变了他的类型,代码就不能用了。

或者就是,意图不清晰,很难理解。

最后,使用中会有重复。

Django 有两个关系密切的与表级别操作相关的构图:managers 和 querysets

manager(django.db.models.manager.Manager的一个实例)被描述成 “通过查询数据库提供给Django的插件”。Manager是表级别功能的通往ORM大门。每一个model都有一个默认的manager,叫做objects。

Quesyset (django.db.models.query.QuerySet) 是“数据库中objects的集合”。本质上是一个SELECT查询,也可以使用过滤,排序等(filtered,ordered),来限制或者修改查询到的数据。用来 创建或操纵 django.db.models.sql.query.Query实例,然后通过数据库后端在真正的SQL中查询。

Manager接口就是个谎言。

QuerySet方法是可链接的。每一次调用QuerySet的方法(如:filter)都会返回一个复制的queryset等待下一次的调用。这也是Django ORM 流畅之美的一部分。

但是当Model.objects 是一个 Manager时,就出现问题了。我们需要调用objects作为开始,然后链接到结果的QuerySet上去。

那么Django又是如何解决呢?

接口的谎言由此暴露,所有的QuerySet 方法基于Manager。

更多:http://www.oschina.net/translate/higher-level-query-api-django-orm

models.py:

from model_utils.managers import PassThroughManager

class NewsQuerySet(models.query.QuerySet):
    def display(self):
        return self.filter(status=1).order_by('-create_time')

def exece(self, question_id):
        return self.exclude(pk=question_id).display()

class News(models.Model):
    STATUS = (
        (0, u'不展示'),
        (1, u'展示'),
    )
    title = models.CharField(max_length=20)
    author = models.CharField(max_length=20)
    img = models.ImageField(upload_to='upload/news/%Y/%m/%d', blank=True, null=True)
    content = models.TextField(blank=True, null=True)
    create_time = models.DateTimeField(auto_now_add=True)
    source = models.CharField(max_length=20)
    status = models.IntegerField(default=1, null=True, blank=True, choices=STATUS)

objects = PassThroughManager.for_queryset_class(NewsQuerySet)()

views.py:

原先:

q = News.objects.all().exclude(id=news_id).filter(status=1).order_by('-create_time')
现在:

q = News.objects.exece(news_id)

在视图和其他高级应用中使用源生的ORM查询代码不是很好的主意。而是用django-model-utils中的PassThroughManager将我们新加的自定义QuerySet API加进你的模型中,这能给你以下好处:

啰嗦代码少,并且更健壮。
    增加DRY,增强抽象级别。

  将所属的业务逻辑推送至对应的域模型层。


2015.1.6

StatusField

from model_utils.fields import StatusField
from model_utils import Choices class Article(models.Model):
STATUS = Choices('draft', 'published')
# ...
status = StatusField() from model_utils.fields import StatusField
from model_utils import Choices class Article(models.Model):
ANOTHER_CHOICES = Choices('draft', 'published')
# ...
another_field = StatusField(choices_name='ANOTHER_CHOICES')

MonitorField

from model_utils.fields import MonitorField, StatusField

class Article(models.Model):
STATUS = Choices('draft', 'published') status = StatusField()
status_changed = MonitorField(monitor='status') from model_utils.fields import MonitorField, StatusField class Article(models.Model):
STATUS = Choices('draft', 'published') status = StatusField()
published_at = MonitorField(monitor='status', when=['published'])

SplitField

from django.db import models
from model_utils.fields import SplitField class Article(models.Model):
title = models.CharField(max_length=100)
body = SplitField() content:
The full field contents.
excerpt:
The excerpt of content (read-only).
has_more:
True if the excerpt and content are different, False otherwise. >>> a = Article.objects.all()[0]
>>> a.body.content
u'some text\n\n<!-- split -->\n\nmore text'
>>> a.body.excerpt
u'some text\n'
>>> unicode(a.body)
u'some text\n\n<!-- split -->\n\nmore text' By default, SplitField looks for the marker <!-- split --> alone on a line and takes everything before that marker as the excerpt. This marker can be customized by setting the SPLIT_MARKER setting. If no marker is found in the content, the first two paragraphs (where paragraphs are blocks of text separated by a blank line) are taken to be the excerpt. This number can be customized by setting the SPLIT_DEFAULT_PARAGRAPHS setting.

 Choices

from model_utils import Choices

GENERIC_CHOICES = Choices((0, 'draft', _('draft')), (1, 'published', _('published')))

class Article(models.Model):
STATUS = GENERIC_CHOICES + [(2, 'featured', _('featured'))]
status = models.IntegerField(choices=STATUS, default=STATUS.draft)

 Field Tracker

from django.db import models
from model_utils import FieldTracker class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField() tracker = FieldTracker() >>> a = Post.objects.create(title='First Post')
>>> a.title = 'Welcome'
>>> a.tracker.previous('title') >>> a = Post.objects.create(title='First Post')
>>> a.title = 'Welcome'
>>> a.tracker.has_changed('title')
True
>>> a.tracker.has_changed('body')
False >>> a = Post.objects.create(title='First Post')
>>> a.title = 'Welcome'
>>> a.body = 'First post!'
>>> a.tracker.changed()
{'title': 'First Post', 'body': ''}
from django.db import models
from model_utils import FieldTracker class Post(models.Model):
title = models.CharField(max_length=100)
body = models.TextField() title_tracker = FieldTracker(fields=['title']) >>> a = Post.objects.create(title='First Post')
>>> a.body = 'First post!'
>>> a.title_tracker.changed()
{'title': None}

https://django-model-utils.readthedocs.org/en/latest/models.html

django-model-utils的更多相关文章

  1. django.db.utils.ProgrammingError: (1146, "Table 'db_gold.user_ip_info' doesn't exist") RuntimeError: Model class scanhosts.models.HostLoginInfo doesn't declare an explicit app_label and isn't in an a

    Error Msg 创建了一个apps的目录将所有app放入apps文件中, 将apps路径加入sys.path中:sys.insert(0, os.path.join(BASE_DIR, " ...

  2. 【AMAD】django-model-utils -- Django model使用的mixin和utils

    动机 简介 个人评分 动机 为django model系统提供一些可重用的mixin和utils. 简介 django-model-utils1为Django Model提供了下嘛几种分类的utils ...

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

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

  4. django.db.utils.ProgrammingError: 1146 的解决办法

    在models中设置完数据库相关的东西后执行命令 python manage.py makemigrations 此处无错误 再次执行 python manage.py migrate 发生报错 错误 ...

  5. Django Model field reference

    ===================== Model field reference ===================== .. module:: django.db.models.field ...

  6. Django Model Form

    ModelForm ModelForm结合了Form和Model,将models的field类型映射成forms的field类型,复用了Model和Model验证, 写更少的代码,并且还实现了存储数据 ...

  7. django.db.utils.OperationalError: (1071, 'Specified key was too long; max key length is 767 bytes')

    环境介绍 Django (2.1)  Python 3.5.5 mysqlclient (1.4.2.post1) Mysql 5.6.28 RHEL 7.3 在migrate时候报错 model代码 ...

  8. 在执行migrate的时候出现问题(错误见末尾): django.db.utils.OperationalError: (1045, "Access denied for user ‘ODBC‘@‘localho st‘ (using password: YES)")

    Python框架之Django的数据库 在执行migrate的时候出现问题(错误见末尾) django.db.utils.OperationalError: (1045, "Access d ...

  9. Django model总结(上)

    Django model是django框架中处于比较核心的一个部位,准备分三个博客从不同的方面分别进行阐述,本文为<上篇>,主要对[a]Model的基本流程,比如它的创建,迁移等:默认行为 ...

  10. Django model字段类型清单

    转载:<Django model字段类型清单> Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField ...

随机推荐

  1. multi-threaded copy command - robocopy

    we can copy files by the powerful robocopy tool, and it allow copy using muliti-threaded as well. As ...

  2. hadoop配置及无法移动文件到hdfs故障解析

    首先博主用的64位ubuntu,hadoop官方只提供32位版本,这样的话启动本地库无法兼容,需要自己编译为64位版本,或下载别人编译好的64位版本. 下载好需要在etc/hadoop目录下改动以下几 ...

  3. cocos2dx ResolutionPolicy

    FrameSize 参数,在游戏运行时,我们可以通过 CCEGLView::sharedOpenGLView()->getFrameSize();如果在手机上运行,那么不同分辨率将会得到不同的值 ...

  4. Java Socket 入门2 Java与C# Socket 通信

    参考http://www.cnblogs.com/cdtarena/p/3184313.html 这里以C#作为服务端  其实不论C#是服务端还是客户端都不是主要问题 毕竟不论客户端还是服务端 都包括 ...

  5. android studio recent projects

    android studio正常的删除项目的方法是可以点击右键,选择project structure,进入到界面时,选择你要删除的工程,点击减号,接着就可以右键工程有一个delete. 另外一种方法 ...

  6. Windows Azure 即将更名

     今天我们宣布自2014 年4 月3 日起,WindowsAzure 将更名为Microsoft Azure.这一更名反映了Microsoft 的战略,并显示了Microsoft 专注于将Azur ...

  7. Microsoft Accelerator for Windows Azure Alum Azuqua 今天启动

     云最大的一个优势就是,它使开发人员比以往任何时候都更迅速.更灵活.在 Windows Azure 中开发应用程序时,工程师无需考虑架设服务器.规划容量或进行日常维护.相反,他们可以专注于提出假设 ...

  8. HDU 2202 最大三角形

    题解:先算出凸包,然后枚举凸包上的点计算即可 #include <cstdio> #include <cmath> #include <cstdlib> #incl ...

  9. BZOJ 1739: [Usaco2005 mar]Space Elevator 太空电梯

    题目 1739: [Usaco2005 mar]Space Elevator 太空电梯 Time Limit: 5 Sec  Memory Limit: 64 MB Description The c ...

  10. 搞不清FastCgi与PHP-fpm之间是个什么样的关系 - SegmentFault

    搞不清FastCgi与PHP-fpm之间是个什么样的关系 - SegmentFault 搞不清FastCgi与PHP-fpm之间是个什么样的关系 3赞 踩 收藏 我在网上查fastcgi与php-fp ...