django-model-utils
一个普通例子:
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的更多相关文章
- 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, " ...
- 【AMAD】django-model-utils -- Django model使用的mixin和utils
动机 简介 个人评分 动机 为django model系统提供一些可重用的mixin和utils. 简介 django-model-utils1为Django Model提供了下嘛几种分类的utils ...
- 【转】Django Model field reference学习总结
Django Model field reference学习总结(一) 本文档包含所有字段选项(field options)的内部细节和Django已经提供的field types. Field 选项 ...
- django.db.utils.ProgrammingError: 1146 的解决办法
在models中设置完数据库相关的东西后执行命令 python manage.py makemigrations 此处无错误 再次执行 python manage.py migrate 发生报错 错误 ...
- Django Model field reference
===================== Model field reference ===================== .. module:: django.db.models.field ...
- Django Model Form
ModelForm ModelForm结合了Form和Model,将models的field类型映射成forms的field类型,复用了Model和Model验证, 写更少的代码,并且还实现了存储数据 ...
- 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代码 ...
- 在执行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 ...
- Django model总结(上)
Django model是django框架中处于比较核心的一个部位,准备分三个博客从不同的方面分别进行阐述,本文为<上篇>,主要对[a]Model的基本流程,比如它的创建,迁移等:默认行为 ...
- Django model字段类型清单
转载:<Django model字段类型清单> Django 通过 models 实现数据库的创建.修改.删除等操作,本文为模型中一般常用的类型的清单,便于查询和使用: AutoField ...
随机推荐
- LintCode-两个字符串是变位词
题目描述: 写出一个函数 anagram(s, t) 去判断两个字符串是否是颠倒字母顺序构成的 样例 给出 s="abcd",t="dcab",返回 true ...
- Python CSV文件处理/读写及With as 用法
可以不使用CSV模块 逐行处理: for line in open("samples/sample.csv"): title, year, director = line.spli ...
- perl5 第九章 关联数组/哈希表
第九章 关联数组/哈希表 by flamephoenix 一.数组变量的限制二.定义三.访问关联数组的元素四.增加元素五.创建关联数组六.从数组变量复制到关联数组七.元素的增删八.列出数组的索引和值九 ...
- 将一个数转化为二进制后,求其中1的个数 C++
#include <iostream>using namespace std;int func(int x){ int count=0; while(x) { x=x&(x-1); ...
- JavaSE学习总结第20天_IO流2
20.01 递归概述和注意事项 递归:方法定义中调用方法本身的现象 递归注意事项: 1.要有出口,否则就是死递归 2.次数不能太多,否则就内存溢出 3.构造方法不能递归使用 20.02 递归求 ...
- WEB ICON 的探讨
一般考虑到webicon 就是cssSprite和自定义font:本文基于下述而总结和进行分析,如有笔误有望指出,谢谢 在线教程:用字体在网页中画ICON图标 http://www.imooc.com ...
- 补全aaz288 可能有问题的过程 P_COMPL_AAZ288
补全aaz288 可能有问题的过程: /* add by weiyongle 20160623 失地农民补足aaz288,针对早期导出的数据(只适用于江安县) 经测试:江安县 江安县个体劳动者 这个单 ...
- nvl与 is not null的区别等
Oracle中: Select Aae140 From Ab07 Where Aab001 = Pi_Aab001 And Aae002 = Pi_Aae002 ) 1 nvl(aaz288,0)&g ...
- Binary Tree Preorder Traversal and Binary Tree Postorder Traversal
Binary Tree Preorder Traversal Given a binary tree, return the preorder traversal of its nodes' valu ...
- Recursive Depth first search graph(adj matrix)
1 深度优先遍历邻接矩阵 1 邻接矩阵初始化 2 访问数组初始化 3 深度优先遍历邻接矩阵图 算法如下: bool MGraph[128][128]; bool visit[128]; int vex ...