Skip to main content
This is a pre-production deployment of Warehouse. Changes made here affect the production instance of PyPI (
Help us improve Python packaging - Donate today!

Mixins to cache, force and/or use non-atomic Model.objects.get_or_create() calls.

Project Description

Django GetOrCreatePlus is a set of queryset mixins to create custom querysets that can:

  • Cache results of get_or_create() or update_or_create()
  • Always use get_or_create() when get() calls are made
  • Allow non-atomic get_or_create() to avoid nested transaction points

Quick start


from django.db import models
from django.core.cache import caches
from getorcreateplus import CachedGetOrCreateMixin, AlwaysGetOrCreateMixin, NonAtomicGetOrCreateMixin

# sample for CachedGetOrCreateMixin (see below for changes to be made in
class CachedQuerySet(CachedGetOrCreateMixin, models.QuerySet):

class CachedManager(models.manager.BaseManager.from_queryset(CachedQuerySet)):
    use_for_related_fields = True

class CachedImmutableModel(models.Model):
    foo = models.CharField(max_length=8)
    bar = models.IntegerField(null=True)

    objects = CachedManager()

obj1, _ = CachedImmutableModel.objects.get_or_create(foo='FooBar') # fetches from db
obj2, _ = CachedImmutableModel.objects.get_or_create(foo='FooBar') # hits cache

class CachedMutableObject(models.Model):
    foo = models.CharField(max_length=8)
    bar = models.IntegerField(null=True)

    objects = CachedManager()

    def save(self, **kwargs):
        cache = caches[self._meta.model_name]
        return super(CachedMutableObject, self).save(**kwargs)

obj1, _ = CachedMutableModel.objects.get_or_create(foo='FooBar') # fetches from db = 1 # invalidate object cache
obj2, _ = CachedMutableModel.objects.get_or_create(foo='FooBar') # fetches from db
obj3, _ = CachedMutableModel.objects.get_or_create(foo='FooBar') # hits cache

# sample for NonAtomicGetOrCreateMixin
class NonAtomicQuerySet(NonAtomicGetOrCreateMixin, models.QuerySet):

class NonAtomicManager(models.manager.BaseManager.from_queryset(NonAtomicQuerySet)):
    use_for_related_fields = True

class ParentQuerySet(NonAtomicQuerySet):
    def create(self, **kwargs):
       children = kwargs.pop('children', [])
       parent = super(ParentQuerySet, self).create(**kwargs)
       for child in children:
       return parent

class ParentManager(models.manager.BaseManager.from_queryset(ParentQuerySet)):
    use_for_related_fields = True

class ParentModel(models.Model):
    foo = models.CharField(max_length=8)

    objects = ParentManager()

class ChildModel(models.Model):
    parent = models.ForeignKey(Parent, related_name='children')
    bar = models.CharField(max_length=8)

    objects = NonAtomicManager()

from django.db import transaction

with transaction.atomic():
    parent, _ = ParentModel.objects.get_or_create(foo='Foo', defaults={children: [{bar: 'Bar'}, {bar: 'Baz'}]})

# samples for combining mixins CachedGetOrCreateMixin, AlwaysGetOrCreateMixin, NonAtomicGetOrCreateMixin
class NonAtomicAlwaysQuerySet(NonAtomicGetOrCreateMixin, AlwaysGetOrCreateMixin, models.QuerySet):

class AlwaysCachedQuerySet(AlwaysGetOrCreateMixin, CachedGetOrCreateMixin, models.QuerySet):

class PlusQuerySet(CachedGetOrCreateMixin, AlwaysGetOrCreateMixin, NonAtomicGetOrCreateMixin, models.QuerySet):

CachedGetOrCreateMixin uses Django caches. The keys are cached to the default cache, and the objects are cached using alias model._meta.model_name.

NOTE: If you have models by the same name in different apps both using CachedGetOrCreateMixin, this will fail.

# assuming use of django-connection-url (shameless self-plug)

import connection_url

    'default': connection_url.config('locmem:///'),
    'cachedimmutablemodel': connection_url.config('REDIS_URL'),
    'cachedmutablemodel': connection_url.config('MEMCACHED_URL'),

Release History

This version
History Node


Download Files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Filename, Size & Hash SHA256 Hash Help File Type Python Version Upload Date
(5.9 kB) Copy SHA256 Hash SHA256
Wheel 2.7 Nov 22, 2016

Supported By

Elastic Elastic Search Pingdom Pingdom Monitoring Dyn Dyn DNS Sentry Sentry Error Logging CloudAMQP CloudAMQP RabbitMQ Heroku Heroku PaaS Kabu Creative Kabu Creative UX & Design Fastly Fastly CDN DigiCert DigiCert EV Certificate Google Google Cloud Servers DreamHost DreamHost Log Hosting