A BitField extension for Django Models

Overview

django-bitfield

https://api.travis-ci.org/disqus/django-bitfield.png?branch=master

Provides a BitField like class (using a BigIntegerField) for your Django models.

(If you're upgrading from a version before 1.2 the API has changed greatly and is backwards incompatible!)

Requirements

  • Django >= 1.10.8
  • PostgreSQL (see notes)

Notes:

  • SQLite does not support save operations using a Bit (per the example under Usage).
  • MySQL fails on most queries related to BitField's.

Installation

Install it with pip (or easy_install):

pip install django-bitfield

Usage

First you'll need to attach a BitField to your class. This acts as a BigIntegerField (BIGINT) in your database:

from bitfield import BitField

class MyModel(models.Model):
    flags = BitField(flags=(
        'awesome_flag',
        'flaggy_foo',
        'baz_bar',
    ))

Flags can also be defined with labels:

class MyModel(models.Model):
    flags = BitField(flags=(
        ('awesome_flag', 'Awesome Flag!'),
        ('flaggy_foo', 'Flaggy Foo'),
        ('baz_bar', 'Baz (bar)'),
    ))

Now you can use the field using very familiar Django operations:

# Create the model
o = MyModel.objects.create(flags=0)

# Add awesome_flag (does not work in SQLite)
MyModel.objects.filter(pk=o.pk).update(flags=F('flags').bitor(MyModel.flags.awesome_flag))

# Set flags manually to [awesome_flag, flaggy_foo]
MyModel.objects.filter(pk=o.pk).update(flags=MyModel.flags.awesome_flag | MyModel.flags.flaggy_foo)

# Remove awesome_flag (does not work in SQLite)
MyModel.objects.filter(pk=o.pk).update(flags=F('flags').bitand(~MyModel.flags.awesome_flag))

# Find by awesome_flag
MyModel.objects.filter(flags=MyModel.flags.awesome_flag)

# Exclude by awesome_flag
MyModel.objects.filter(flags=~MyModel.flags.awesome_flag)

# Test awesome_flag
if o.flags.awesome_flag:
    print "Happy times!"

# List all flags on the field
for f in o.flags:
    print f

# Get a flag label
print o.flags.get_label('awesome_flag')

Enjoy!

Admin

To use the widget in the admin, you'll need to import the classes and then update or create a ModelAdmin with these formfield_overrides lines in your admin.py:

from bitfield import BitField
from bitfield.forms import BitFieldCheckboxSelectMultiple

class MyModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
            BitField: {'widget': BitFieldCheckboxSelectMultiple},
    }

admin.site.register(MyModel, MyModelAdmin)

There is also a BitFieldListFilter list filter (Django 1.4 or newer). To use it set list_filter ModelAdmin option:

list_filter = (
        ('flags', BitFieldListFilter,)
        )

BitFieldListFilter is in bitfield.admin module:

from bitfield.admin import BitFieldListFilter

Changelog

2.1.0 - 2021-05-25:

  • Add support for Django 3.1, 3.2 (No changes needed).
  • Add support for Python 3.8, 3.9.
  • Fixed multiple bugs with use in the Django admin.
  • Removed dead compatibility code.

2.0.1 - 2020-01-25:

  • Add support for Django 3.0.

2.0.0 - 2020-01-24:

  • Drop support for Django versions below 1.10.
  • Use _meta.private_fields instead of deprecated _meta.virtual_fields in CompositeBitField.
  • Add testing with python 3.6, 3.7 and Django 2.x to travis configuration.
Comments
  • Support Django 1.10

    Support Django 1.10

    In Django 1.8, SubfieldBase has been deprecated and will be removed in Django 1.10. I'm using Django 1.9 and getting "RemovedInDjango110Warning".

    opened by tzachyrm 16
  • Various improvements to tests and compatibility

    Various improvements to tests and compatibility

    • Switch to pytest
    • Add flake8
    • Enhance TravisCI configuration
      • Switch to container builds
      • Add pypy to grid
      • Add explicit mysql/postgres/sqlite to grid
      • Add development Django to grid
    • Raise Django requirement to 1.4+

    Review on Reviewable

    opened by dcramer 12
  • 'BitQueryLookupWrapper' object is not iterable on Django 1.7

    'BitQueryLookupWrapper' object is not iterable on Django 1.7

    I ported some code that previously worked in Django 1.6, which now seems to fail in Django 1.7. I have the following code:

    class FlagsManager(models.Manager):
        def get_queryset(self):
            return super(FlagsManager, self).get_queryset().filter(
                flags=~self.model.flags.INACTIVE)
    

    In Django 1.7 I get a "'BitQueryLookupWrapper' object is not iterable". Seems like Django is trying to do a

    params.extend(rhs_params) where rhs_params is: bitfield.query.BitQueryLookupWrapper object

    Traceback:
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
      111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/Users/bryanmarty/mybitfieldapp/mybitfieldapp/apps/registration/views.py" in register
      17.         if form.is_valid():
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/forms/forms.py" in is_valid
      162.         return self.is_bound and not bool(self.errors)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/forms/forms.py" in errors
      154.             self.full_clean()
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/forms/forms.py" in full_clean
      353.         self._clean_fields()
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/forms/forms.py" in _clean_fields
      371.                     value = getattr(self, 'clean_%s' % name)()
    File "/Users/bryanmarty/mybitfieldapp/mybitfieldapp/apps/registration/forms.py" in clean_username
      51.             User._default_manager.get(username=username)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/manager.py" in manager_method
      92.                 return getattr(self.get_queryset(), name)(*args, **kwargs)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/query.py" in get
      351.         num = len(clone)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/query.py" in __len__
      122.         self._fetch_all()
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/query.py" in _fetch_all
      966.             self._result_cache = list(self.iterator())
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/query.py" in iterator
      265.         for row in compiler.results_iter():
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in results_iter
      700.         for rows in self.execute_sql(MULTI):
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in execute_sql
      775.             sql, params = self.as_sql()
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in as_sql
      109.         where, w_params = self.compile(self.query.where)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in compile
      80.             return node.as_sql(self, self.connection)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/where.py" in as_sql
      106.                     sql, params = qn.compile(child)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/sql/compiler.py" in compile
      80.             return node.as_sql(self, self.connection)
    File "/Users/bryanmarty/.env/mybitfieldapp/lib/python2.7/site-packages/django/db/models/lookups.py" in as_sql
      151.         params.extend(rhs_params)
    
    Exception Type: TypeError at /register/
    Exception Value: 'BitQueryLookupWrapper' object is not iterable
    
    opened by bxm156 11
  • Fix deprecation: Change force_text to force_str

    Fix deprecation: Change force_text to force_str

    This is not a breaking change for Python 3. force_str has existed at least as far back as Django 1.8.

    If Python 2 support is needed, then this could break it. IMO it shouldn't be supported but if preferred I can wrap this in a try catch.

    opened by bufke 8
  • Release of django-bitfield compliant with django2.2

    Release of django-bitfield compliant with django2.2

    Hi There!

    Since django2.2 will become soon the new LTS version, I'm wondering if you can provide a new release of django-bitfield compliant with this version. I've seen in commit history since the 3rd september the compliance is guarantee for django >=1.10 (893b5ae232de88c8368a41b40865459a9e1d11e5), can you please release a new version with those commits ?

    I've seen on pypi the last available release has been done the 13th July 2019.

    Many thxs!

    opened by moumoutte 7
  • "can't adapt type 'CombinedExpression'" in admin filter

    Getting an error with Django 1.11.21 and the latest PyPI release of this library (1.9.3) -

    django.db.utils.ProgrammingError: can't adapt type 'CombinedExpression'

    When I try to filter by a flag in admin.

    opened by Datamance 7
  • 'CombinedExpression' object is not iterable when using an admin filter on Django 1.8

    'CombinedExpression' object is not iterable when using an admin filter on Django 1.8

    Hi,

    I'm having a problem when using BitFieldListFilter on Django 1.8

    Selecting any item in the filter raises the following error:

    Traceback:
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/core/handlers/base.py" in get_response
      132.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/contrib/admin/options.py" in wrapper
      616.                 return self.admin_site.admin_view(view)(*args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
      110.                     response = view_func(request, *args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/views/decorators/cache.py" in _wrapped_view_func
      57.         response = view_func(request, *args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/contrib/admin/sites.py" in inner
      233.             return view(request, *args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapper
      34.             return bound_func(*args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/utils/decorators.py" in _wrapped_view
      110.                     response = view_func(request, *args, **kwargs)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/utils/decorators.py" in bound_func
      30.                 return func.__get__(self, type(self))(*args2, **kwargs2)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/contrib/admin/options.py" in changelist_view
      1548.                 self.list_max_show_all, self.list_editable, self)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/contrib/admin/views/main.py" in __init__
      82.         self.get_results(request)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/contrib/admin/views/main.py" in get_results
      177.         result_count = paginator.count
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/core/paginator.py" in _get_count
      77.                 self._count = len(self.object_list)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/query.py" in __len__
      144.         self._fetch_all()
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/query.py" in _fetch_all
      965.             self._result_cache = list(self.iterator())
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/query.py" in iterator
      238.         results = compiler.execute_sql()
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in execute_sql
      829.             sql, params = self.as_sql()
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in as_sql
      387.             where, w_params = self.compile(self.query.where)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in compile
      357.             sql, params = node.as_sql(self, self.connection)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/sql/where.py" in as_sql
      104.                     sql, params = compiler.compile(child)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/sql/compiler.py" in compile
      357.             sql, params = node.as_sql(self, self.connection)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/django/db/models/lookups.py" in as_sql
      210.         lhs_sql, params = self.process_lhs(compiler, connection)
    File "/Users/antonin/Documents/Projects/venv/lib/python3.4/site-packages/bitfield/query.py" in process_lhs
      38.             params.extend(self.get_db_prep_lookup(self.rhs, connection)[1])
    
    Exception Type: TypeError at /admin/core/item/
    Exception Value: 'CombinedExpression' object is not iterable
    

    It looks like this should be fixed for Django 1.8

    opened by ALenfant 7
  • Any plans for a new release?

    Any plans for a new release?

    Hi, do you have any plans for a new release of this package on pypi ? There's been a few useful commits in the last year that we'd be happy to have in an official release instead of having to fetch code from a git branch :)

    Thank you!

    opened by guillaumealgis 5
  • New release on PyPI

    New release on PyPI

    The current release is over 2 years old and obviously not in sync with the master branch. From what I can gather, the master branch should work with Django 2.x whereas the current PyPI release does not (fully).

    The widgets lack the renderer parameter it seems

    opened by wolph 5
  • Fix Deprecation warning for ugettext_lazy

    Fix Deprecation warning for ugettext_lazy

    Fixes this deprecation warning: /usr/local/lib/python3.9/site-packages/bitfield/admin.py:43: RemovedInDjango40Warning: django.utils.translation.ugettext_lazy() is deprecated in favor of django.utils.translation.gettext_lazy().

    opened by pcarn 4
  • models: remove unnecessary BitField.pre_save

    models: remove unnecessary BitField.pre_save

    The code already equaled the default implementation.

    Probably ended up from some tinkering that eventually resulted in reverting back to the default behavior.

    opened by ortholeviator 4
  • A Django form containing BitField always have this field as changed

    A Django form containing BitField always have this field as changed

    As the title says the form is always marked and changed.

    in the changed_data property of the Form, initial_value is an int while the data_value is a list

    this is causing Field.has_changed to return True because of the ValidationError thrown by the to_python method

    opened by b1izzard 0
  • How to retrieve a BitField flag value in a queryset filter using values.

    How to retrieve a BitField flag value in a queryset filter using values.

    If I do the below filter, using ".values" to retrieve profile related values from multiple tables, the bitfield 'interests' is converted into a normal number. profiles = Profile.objects.filter(to_profile__from_profile=request.user.id).values('id', 'nickname', 'age', 'location', 'country__name', 'description', 'to_profile__like', 'to_profile__favourite', 'interests', 'photo1', 'photo2', 'photo3') Once the BitField 'interests' is converted into a normal number, if you try and use it you get the error: 'int' object has no attribute 'flags'. It would be very useful if you could pass a number into the BitField and use the flags option. Without this option BitField cannot be used with .values or .value_lists which are very useful filter options. I admit this is similar to the issue "https://github.com/disqus/django-bitfield/issues/98", but that didn't include ".values" and also didn't suggest a solution of passing the number into BitField.

    opened by andrewcirel 0
  • tests: Use direct values instead of raw SQL

    tests: Use direct values instead of raw SQL

    Supersedes #11.

    In order to prevent (-1) from being masked by BitField.get_prep_value and converted to 15 (0xf), the test code uses a direct SQL statement. Its implementation has a few peculiarities that may be undesirable:

    • It uses an Django internal API, the Field.column attribute. Granted, this package already uses a lot of internal APIs, and Field.column is highly unlikely to change. However, in general using less internal APIs is better for future compatibility.

    • Using low-level API misses a lot of code paths that could have been tested.

    • Neither db_table nor db_column is escaped. In case we later incorporate tests involving pathological SQL object identifiers, we have to further use quote_name, which is not exactly public API either.

    Instead, we use models.Value() with an explicit output_field, which still avoids BitField.get_prep_value and inserts the value directly.

    Further, directly assign to __dict__ so that the BitFieldCreator descriptor's __set__ method is bypassed and the value is assigned unchanged.

    opened by iamahuman 0
  • How to present flags in django admin list view ( flags which are active )

    How to present flags in django admin list view ( flags which are active )

    I have a model with BitField like this:

    class MyModel(models.Model):
            notifications = BitField(flags=('facebook', 'phone', 'gmail'))
    

    Say facebook, gmail are active, then in list view(django-admin) want those flag label comma separated.

    opened by maharshi-trendlyne 1
Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project

Django URL Shortener Django URL Shortener is a Django app to to include URL Shortening feature in your Django Project Install this package to your Dja

Rishav Sinha 4 Nov 18, 2021
Django project starter on steroids: quickly create a Django app AND generate source code for data models + REST/GraphQL APIs (the generated code is auto-linted and has 100% test coverage).

Create Django App ?? We're a Django project starter on steroids! One-line command to create a Django app with all the dependencies auto-installed AND

imagine.ai 68 Oct 19, 2022
Meta package to combine turbo-django and stimulus-django

Hotwire + Django This repository aims to help you integrate Hotwire with Django ?? Inspiration might be taken from @hotwired/hotwire-rails. We are sti

Hotwire for Django 31 Aug 9, 2022
Django-environ allows you to utilize 12factor inspired environment variables to configure your Django application.

Django-environ django-environ allows you to use Twelve-factor methodology to configure your Django application with environment variables. import envi

Daniele Faraglia 2.7k Jan 7, 2023
Rosetta is a Django application that eases the translation process of your Django projects

Rosetta Rosetta is a Django application that facilitates the translation process of your Django projects. Because it doesn't export any models, Rosett

Marco Bonetti 909 Dec 26, 2022
Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly.

Cookiecutter Django Powered by Cookiecutter, Cookiecutter Django is a framework for jumpstarting production-ready Django projects quickly. Documentati

Daniel Feldroy 10k Dec 31, 2022
django-quill-editor makes Quill.js easy to use on Django Forms and admin sites

django-quill-editor django-quill-editor makes Quill.js easy to use on Django Forms and admin sites No configuration required for static files! The ent

lhy 139 Dec 5, 2022
A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, celery and redis.

Django Channels Websocket Chatbot A Django chatbot that is capable of doing math and searching Chinese poet online. Developed with django, channels, c

Yunbo Shi 8 Oct 28, 2022
A handy tool for generating Django-based backend projects without coding. On the other hand, it is a code generator of the Django framework.

Django Sage Painless The django-sage-painless is a valuable package based on Django Web Framework & Django Rest Framework for high-level and rapid web

sageteam 51 Sep 15, 2022
A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a unique id.

Django-URL-Shortener A beginner django project and also my first Django project which involves shortening of a longer URL into a short one using a uni

Rohini Rao 3 Aug 8, 2021
Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot. A fully Django starter project.

Dockerizing Django with Postgres, Gunicorn, Nginx and Certbot ?? Features A Django stater project with fully basic requirements for a production-ready

null 8 Jun 27, 2022
pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-django allows you to test your Django project/applications with the pytest testing tool.

pytest-dev 1.1k Dec 14, 2022
APIs for a Chat app. Written with Django Rest framework and Django channels.

ChatAPI APIs for a Chat app. Written with Django Rest framework and Django channels. The documentation for the http end points can be found here This

Victor Aderibigbe 18 Sep 9, 2022
django-dashing is a customisable, modular dashboard application framework for Django to visualize interesting data about your project. Inspired in the dashboard framework Dashing

django-dashing django-dashing is a customisable, modular dashboard application framework for Django to visualize interesting data about your project.

talPor Solutions 703 Dec 22, 2022
Django-MySQL extends Django's built-in MySQL and MariaDB support their specific features not available on other databases.

Django-MySQL The dolphin-pony - proof that cute + cute = double cute. Django-MySQL extends Django's built-in MySQL and MariaDB support their specific

Adam Johnson 504 Jan 4, 2023
Django-Audiofield is a simple app that allows Audio files upload, management and conversion to different audio format (mp3, wav & ogg), which also makes it easy to play audio files into your Django application.

Django-Audiofield Description: Django Audio Management Tools Maintainer: Areski Contributors: list of contributors Django-Audiofield is a simple app t

Areski Belaid 167 Nov 10, 2022
django Filer is a file management application for django that makes handling of files and images a breeze.

django Filer is a file management application for django that makes handling of files and images a breeze.

django CMS Association 1.6k Jan 6, 2023
Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

Twitter Bootstrap for Django Form - A simple Django template tag to work with Bootstrap

tzangms 557 Oct 19, 2022
Blog focused on skills enhancement and knowledge sharing. Tech Stack's: Vue.js, Django and Django-Ninja

Blog focused on skills enhancement and knowledge sharing. Tech Stack's: Vue.js, Django and Django-Ninja

Wanderson Fontes 2 Sep 21, 2022