Skip to content

chibisov/django_boolean_mixins

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

21 Commits
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Django boolean mixins

Django app with some usefull mixins for models.BooleanField. Every mixin is independent.

Installation

  1. Install:

    git clone clone git://github.com/chibisov/django_boolean_mixins.git cd django_boolean_mixins/ sudo python setup.py install

    or with custom destination

    sudo python setup.py install --install-lib=/Library/Python/2.6/site-packages

  2. Add application to your settings.py:

    INSTALLED_APPS = ( ... 'django_boolean_mixins', ... )

ModelBooleanMixin

from django.db import models
from django.contrib.auth.models import User
from django_boolean_mixins.models import ModelBooleanMixin

class Article(ModelBooleanMixin, models.Model):
    # mixin should be first in model inheritance
    name = models.CharField(max_length=100)
    content = models.TextField()

    is_published = models.BooleanField(default=True)
    active = models.BooleanField()
    
    user_updated = models.ForeignKey(User, blank=True, null=True)

This mixin adds to your Manager's QuerySet new methods for any BooleanField:

  • filter_by_<field_name>
  • exclude_<field_name>

If <field_name> starts with "is_", then will be created same methods, without prefix "is_". For our example will be created methods:

  • filter_by_is_published()
  • filter_by_published()
  • filter_by_active()
  • exclude_is_published()
  • exclude_published()
  • exclude_active()

If model has both fields with names like "is_<field_name>" and "<field_name>", then magic method without "is_" prefix weel not be created:

class ArticleWithCollideFields(ModelBooleanMixin, models.Model):
    is_published = models.BooleanField(default=True)
    published = models.BooleanField(default=True)

    # filter_by_published() and filter_by_is_published() are different methods

You can easily extend mixin's QuerySet or Manager:

from django_boolean_mixins.models import (
                                   ModelBooleanMixin, 
                                   ModelBooleanMixinQuerySet,
                                   ModelBooleanMixinManager)

class ArticleQuerySet(ModelBooleanMixinQuerySet):
    def exclude_bad_words(self):
        self = (self.filter_by_published()
                    .exclude(text__icontains="badword_1")
                    .exclude(text__icontains="badword_2"))

        return self

class ArticleManager(ModelBooleanMixinManager):
    def get_query_set(self):
        return ArticleQuerySet(self.model)

    def __getattr__(self, name):
        return getattr(self.get_query_set(), name)

class Article(ModelBooleanMixin, models.Model):    
    title = models.CharField(max_length=200, verbose_name="заголовок")
    text = models.TextField(verbose_name="текст")
    is_published = models.BooleanField(default=True)
    is_login_required = models.BooleanField(default=False)

    objects = ArticleManager()
    ...

And now you can use these methods for example in views:

articles = Article.objects.filter_by_published().exclude_active().order_by("name")
...

Or in templates:

{% for article in articles.filter_by_is_published %}
    {{ article.content }}
{% endfor %}

<!-- OR filter_by_published -->
{% for article in articles.filter_by_published.filter_by_active %}
    {{ article.content }}
{% endfor %}

One of usefull example is creating your custom mixin:

class PublishedMixin(ModelBooleanMixin, models.Model):
    is_published = models.BooleanField(default=True)

    class Meta:
        abstract = True

class Category(PublishedMixin, models.Model):
    name = models.CharField(max_length=255)

class Article(PublishedMixin, models.Model):
    name = models.CharField(max_length=255)
    category = models.ForeignKey(Category)

You don't need to add by hand methods for every boolean field:

# iterate by published categories
for category in Category.objects.filter_by_published():
    # iterate by not published articles
    for article in category.article_set.exclude_published():
        print """This is not published article with name 
                 '{article.name}' of published category 
                 with name '{category.name}' """.format(category=category, 
                                                        article=article)

AdminBooleanMixin

from django.contrib import admin
from yourapp.models import Article
from django_boolean_mixins.admin import AdminBooleanMixin

class ArticleAdmin(AdminBooleanMixin, admin.ModelAdmin):
    list_display = ("name", "is_published", "active")

admin.site.register(Article, ArticleAdmin)

This mixin adds 2 actions for every BooleanField from list_display option.
First action - to set False, second - to set True.

actions example

By default adds actions with names like:

  • "Set selected <model_verbose_name_plural> <field_verbose_name> to True"
  • "Set selected <model_verbose_name_plural> <field_verbose_name> to False"

You can specify your own labels in admin.py:

class ArticleAdmin(AdminBooleanMixin, admin.ModelAdmin):
    ...
    boolean_short_descriptions = {
        "is_published": ("Publish selected articles", "Unpublish selected articles"),
        "active": ("Activate selected articles", "Deactivate selected articles")
    }
    ...

For more flexibility you can use model_verbose_name_plural and field_verbose_name, which will be formatted:

class ArticleAdmin(AdminBooleanMixin, admin.ModelAdmin):
    ...
    boolean_short_descriptions = {
        "is_published": ("Publish selected {model_verbose_name_plural}", 
                         "Unpublish selected {model_verbose_name_plural}"),
        "active": ("Activate selected {model_verbose_name_plural}", 
                   "Deactivate {field_verbose_name} for selected {model_verbose_name_plural}")
    }
    ...

If you want, that one of actions used default text, you can specify it to None:

class ArticleAdmin(AdminBooleanMixin, admin.ModelAdmin):
    ...
    boolean_short_descriptions = {
        "is_published": (None, "Unpublish selected {model_verbose_name_plural}"),
        ...
    }
    ...

Custom behavior

To trigger some custom behavior after action will end his job, you can specify after_any_boolean_action method in admin.py, which takes 2 arguments:

  • A QuerySet containing the set of objects selected by the user
  • An HttpRequest representing the current request

For example, update who changed the boolean state:

class ArticleAdmin(AdminBooleanMixin, admin.ModelAdmin):
    ...
    def after_any_boolean_action(self, queryset, request):
        queryset.update(user_updated=request.user)
    ...

About

Mixins for BooleanField model and admin parts.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages