Giter Club home page Giter Club logo

django-better-choices's Introduction

Django Better Choices

PyPI PyPI - Python Version Build Status codecov License

Better choices library for Django web framework.

Requirements

This library was written for Python 3.7+ and will not work in any earlier versions.

Install

pip install django-better-choices

Usage

To start defining better choices, you need first to import the Choices class.

from django_better_choices import Choices

Class definition

The choices can be defined with overriding Choices class.

class PageStatus(Choices):
    CREATED = 'Created'
    PENDING = Choices.Value('Pending', help_text='This set status to pending')
    ON_HOLD = Choices.Value('On Hold', value='custom_on_hold')

    VALID = Choices.Subset('CREATED', 'ON_HOLD')
    INVISIBLE = Choices.Subset('PENDING', 'ON_HOLD')

    class InternalStatus(Choices):
        REVIEW = 'On Review'

    @classmethod
    def get_help_text(cls):
        return tuple(
            value.help_text
            for value in cls.values()
            if hasattr(value, 'help_text')
        )

Choices class key can be any public identifier (i.e. not starting with underscore _). Overridden choices classes cannot be initialised to obtain a new instance, calling the instance will return a tuple of choice entries.

Inline definition

Alternatively, the choices can be defined dynamically by creating a new Choices instance.

PageStatus = Choices('PageStatus', SUCCESS='Success', FAIL='Error')

The first name parameter of Choices constructor is optional and required only for better representation of the returned instance.

Value accessors

You can access choices values using dot notation and with getattr().

value_created = PageStatus.CREATED
value_review = PageStatus.InternalStatus.REVIEW
value_on_hold = getattr(PageStatus, 'ON_HOLD')

Values and value parameters

Choices.Value is a subclass of str and equals to its value. In addition to display parameter, other optional parameters can be specified in Choices.Value constructor (see class definition example).

print( PageStatus.CREATED )                # 'created'
print( PageStatus.ON_HOLD )                # 'custom_on_hold'
print( PageStatus.PENDING.display )        # 'Pending'
print( PageStatus.PENDING.help_text )      # 'This set status to pending'

PageStatus.ON_HOLD == 'custom_on_hold'     # True
PageStatus.CREATED == PageStatus.CREATED   # True

Choices.Value is an immutable string class, which instance cannot be modified after initialisation. Native non-magic str methods can be overridden in Choices.Value custom parameters. Choices.Value behaves like a normal string, e.g. {'val1': 'something'}[CHOICES.VAL1] == 'something'.

Search in choices

Search in choices is performed by value.

'created' in PageStatus                    # True
'custom_on_hold' in PageStatus             # True
'on_hold' in PageStatus                    # False
value = PageStatus['custom_on_hold']       # Choices.Value
value = PageStatus.get('on_hold', 123.45)  # 123.45
key = PageStatus.get_key('created')        # 'CREATED'

Search in subsets

Subsets are used to group several values together (see class definition example) and search by a specific value.

'custom_on_hold' in PageStatus.VALID       # True
PageStatus.CREATED in PageStatus.VALID     # True

Choices.Subset is a subclass of tuple, which is translated to inner choices class after definition. All internal or custom choices class methods or properties will be available in a subset class (see "Custom methods" section).

Extract subset

Subsets of choices can be dynamically extracted with extract() method.

PageStatus.extract('CREATED', 'ON_HOLD')   # ~= PageStatus.VALID
PageStatus.VALID.extract('ON_HOLD')        # Choices('PageStatus.VALID.Subset', ON_HOLD)

Choices iteration

Choices class implements __iter__ magic method, hence choices are iterable that yield choice entries (i.e. (value, display)). Methods items(), keys() and values() can be used to return tuples of keys and values combinations.

for value, display in PageStatus:  # can also be used as callable, i.e. PageStatus()
    print( value, display )

for key, value in PageStatus.items():
    print( key, value, value.display )

for key in PageStatus.keys():
    print( key )

for value in PageStatus.values():
    print( value, value.display, value.__choice_entry__ )

Additional displays() method is provided for choices and subsets to extract values display strings.

for display in PageStatus.displays():
    print( display )

for display in PageStatus.SUBSET.displays():
    print( display )

Iteration methods items(), keys(), values(), displays(), as well as class constructor can accept keyword arguments to filter collections based on custom parameters, e.g. PageStatus.values(help_text='Some', special=123).

Set operations

Choices class and subsets support standard set operations: union (|), intersection (&), difference (-), and symmetric difference (^).

PageStatus.VALID | PageStatus.INVISIBLE     # Choices(CREATED, ON_HOLD, PENDING)
PageStatus.VALID & PageStatus.INVISIBLE     # Choices(ON_HOLD)
PageStatus.VALID - PageStatus.INVISIBLE     # Choices(CREATED)
PageStatus.VALID ^ PageStatus.INVISIBLE     # Choices(CREATED, PENDING)

Custom methods

All custom choices class methods or properties (non-values) will be available in all subsets.

PageStatus.get_help_text()
PageStatus.VALID.get_help_text()
PageStatus.extract('PENDING', 'ON_HOLD').get_help_text()
PageStatus.VALID.extract('ON_HOLD').get_help_text()

Django model fields

Better choices are not different from the original Django choices in terms of usage in models.

class Page(models.Model):
    status = models.CharField(choices=PageStatus, default=PageStatus.CREATED)

Better choices are fully supported by Django migrations and debug toolbar.

Saving choices on models

Better choices are compatible with standard Django models manipulation.

page = Page.objects.get(pk=1)
page.status = PageStatus.PENDING
page.save()

Tests

Run python tests.py for testing.

License

Library is available under the MIT license. The included LICENSE file describes this in detail.

django-better-choices's People

Contributors

lokhman avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.