zoukankan      html  css  js  c++  java
  • 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
    
    <!-- split -->
    
    more text'
    >>> a.body.excerpt
    u'some text
    '
    >>> unicode(a.body)
    u'some text
    
    <!-- split -->
    
    more 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

  • 相关阅读:
    PKU 3984 迷宫问题
    九度 1341 艾薇儿的演唱会
    九度 1335
    SDUT 1198 鞍点计算
    POJ 1363 Rails
    SDUT 1570 C旅行
    HDU 1042 N!
    SDUT 1568 俄罗斯方块
    HDU 1257 最少拦截系统
    POJ 3750 小孩报数问题
  • 原文地址:https://www.cnblogs.com/tuifeideyouran/p/3938515.html
Copyright © 2011-2022 走看看