Helps working with singletons - things like global settings that you want to edit from the admin site.

Related tags

Django django-solo
Overview

Django Solo

+---------------------------+
|                           |
|                           |
|             \             | Django Solo helps working with singletons:
|             /\            | database tables that only have one row.
|           >=)'>           | Singletons are useful for things like global
|             \/            | settings that you want to edit from the admin
|             /             | instead of having them in Django settings.py.
|                           | 
|                           | 
+---------------------------+

Features

Solo helps you enforce instantiating only one instance of a model in django.

  • You define the model that will hold your singleton object.
  • django-solo gives helper parent class for your model and the admin classes.
  • You get an admin interface that's aware you only have one object.
  • You can retrieve the object from templates.
  • By enabling caching, the database is not queried intensively.

Use Cases

Django Solo is also great for use with singleton objects that have a one to many relationship. Like the use case below where you have a 'Home Slider" that has many "Slides".

  • Global or default settings
  • An image slider that has many slides
  • A page section that has sub-sections
  • A team bio with many team members

There are many cases where it makes sense for the parent in a one to many relationship to be limited to a single instance.

Usage Example

# models.py

from django.db import models
from solo.models import SingletonModel

class SiteConfiguration(SingletonModel):
    site_name = models.CharField(max_length=255, default='Site Name')
    maintenance_mode = models.BooleanField(default=False)

    def __str__(self):
        return "Site Configuration"

    class Meta:
        verbose_name = "Site Configuration"
# admin.py

from django.contrib import admin
from solo.admin import SingletonModelAdmin
from config.models import SiteConfiguration

admin.site.register(SiteConfiguration, SingletonModelAdmin)

# There is only one item in the table, you can get it this way:
from .models import SiteConfiguration
config = SiteConfiguration.objects.get()

# get_solo will create the item if it does not already exist
config = SiteConfiguration.get_solo()

In your model, note how you did not have to provide a verbose_name_plural field - That's because Django Solo uses the verbose_name instead.

If you're changing an existing model (which already has some objects stored in the database) to a singleton model, you can explicitly provide the id of the row in the database for django-solo to use. This can be done by setting singleton_instance_id property on the model:

class SiteConfiguration(SingletonModel):
    singleton_instance_id = 24
    # (...)

Installation

This application requires Django >= 1.6.

  • Install the package using pip install django-solo
  • Add solo or solo.apps.SoloAppConfig to your INSTALLED_APPS setting.

This is how you run tests:

./manage.py test solo --settings=solo.tests.settings

Supported Languages

  • English
  • Spanish

Admin

The standard Django admin does not fit well when working with singleton, for instance, if you need some global site settings to be edited in the admin. Django Solo provides a modified admin for that.

django-solo admin

  • In the admin home page where all applications are listed, we have a config application that holds a singleton model for site configuration.
  • The configuration object can only be changed, there's no link for "add" (1).
  • The link to the configuration page (2) directly goes to the form page - no need for an intermediary object list page, since there's only one object.
  • The edit page has a modified breadcrumb (3) to avoid linking to the intermediary object list page.
  • From the edit page, we cannot delete the object (4) nor can we add a new one (5).

If you wish to disable the skipping of the object list page, and have the default breadcrumbs, you should set SOLO_ADMIN_SKIP_OBJECT_LIST_PAGE to False in your settings.

Availability from templates

The singleton object can be retrieved from template by giving the Django model dotted path:

{% get_solo 'app_label.ModelName' as my_config %}

Example:

{% load solo_tags %}
{% get_solo 'config.SiteConfiguration' as site_config %}
{{ site_config.site_name }}
{{ site_config.maintenance_mode }}

If you're extending a template, be sure to use the tag in the proper scope.

Right:

{% extends "index.html" %}
{% load solo_tags %}

{% block content %}
    {% get_solo 'config.SiteConfiguration' as site_config %}
    {{ site_config.site_name }}
{% endblock content %}

Wrong:

{% extends "index.html" %}
{% load solo_tags %}
{% get_solo 'config.SiteConfiguration' as site_config %}

{% block content %}
    {{ site_config.site_name }}
{% endblock content %}

Caching

By default caching is disabled: every time get_solo retrieves the singleton object, there will be a database query.

You can enable caching to only query the database when initially retrieving the object. The cache will also be updated when updates are made from the admin.

The cache timeout is controlled via the SOLO_CACHE_TIMEOUT settings. The cache backend to be used is controlled via the SOLO_CACHE settings.

Settings

Template tag name

You can retrieve your singleton object in templates using the get_solo template tag.

You can change the name get_solo using the GET_SOLO_TEMPLATE_TAG_NAME setting.

GET_SOLO_TEMPLATE_TAG_NAME = 'get_config'

Admin override flag

By default, the admin is overridden. But if you wish to keep the object list page (e.g. to customize actions), you can set the SOLO_ADMIN_SKIP_OBJECT_LIST_PAGE to False.

SOLO_ADMIN_SKIP_OBJECT_LIST_PAGE = True

Cache backend

Django provides a way to define multiple cache backends with the CACHES settings. If you want the singleton object to be cached separately, you could define the CACHES and the SOLO_CACHE settings like this:

CACHES = {
    'default': {
        'BACKEND': 'django.core.cache.backends.memcached.MemcachedCache',
        'LOCATION': '127.0.0.1:11211',
    },
    'local': {
        'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
    },
}

SOLO_CACHE = 'local'

Caching will be disabled if set to None.

Cache timeout

The cache timeout in seconds.

SOLO_CACHE_TIMEOUT = 60*5  # 5 mins

Cache prefix

The prefix to use for the cache key.

SOLO_CACHE_PREFIX = 'solo'

Getting the code

The code is hosted at https://github.com/lazybird/django-solo/

Check out the latest development version anonymously with:

$ git clone git://github.com/lazybird/django-solo.git

You can install the package in the "editable" mode like this:

pip uninstall django-solo  # just in case...
pip install -e git+https://github.com/lazybird/django-solo.git#egg=django-solo

You can also install a specific branch:

pip install -e git+https://github.com/lazybird/django-solo.git@my-branch#egg=django-solo

The package is now installed in your project and you can find the code.

Comments
  • Django 1.9 will remove get_cache support

    Django 1.9 will remove get_cache support

    https://docs.djangoproject.com/en/1.7/topics/cache/#django.core.cache.get_cache

    In order to support future django releases we need to remove usage of that feature and convert to using https://docs.djangoproject.com/en/1.7/topics/cache/#django.core.cache.caches

    opened by Harper04 10
  • Support django-rest-framework by providing ViewSets

    Support django-rest-framework by providing ViewSets

    A ReadOnlyModelViewSet and ModelViewSet like would be great. (more info at http://www.django-rest-framework.org/api-guide/viewsets/)

    This is as far I could get:

    from rest_framework import mixins, viewsets
    
    
    class ReadOnlySingletonViewSet(
            mixins.RetrieveModelMixin, viewsets.GenericViewSet):
    
        def get_object(self):
            obj = self.model.get_solo()
            self.check_object_permissions(self.request, obj)
            return obj
    

    It is ok but I have to provide a pk argument to the URL as following:

    /api/<resource-prefix>/<pk>/

    can be any value. Would be great if we could get rid of this parameter.

    feature request 
    opened by semente 10
  • Django 4.0 Support

    Django 4.0 Support

    Closes #76

    Closes #108

    #104 instates the policy for supporting supported Django versions and thus this PR is compatible with that new policy.

    • Officially support Django 2.2, 3.2, and 4.0, the versions of Django currently supported
    • Do not require Django to be installed simply to build the source distribution for django-solo. This enables testing to work when only tox is installed (e.g. CI)
    bug 
    opened by johnthagen 8
  • django.template.exceptions.TemplateDoesNotExist: admin/solo/change_form.html

    django.template.exceptions.TemplateDoesNotExist: admin/solo/change_form.html

    Hi!

    When I go to my singleton model's admin change page, I get the exception django.template.exceptions.TemplateDoesNotExist: admin/solo/change_form.html. I'm working with Django 3.1.1.

    The problem is that the egg file of the package is a zip file and not a directory (the extraction did not happen). But Django's default template loader can find templates in directories only: https://github.com/django/django/blob/0b8871ab6744285943784795ede053839ee009ef/django/template/utils.py#L94

    To force the unzip, you need to set the zip-safe option to False: https://setuptools.readthedocs.io/en/latest/formats.html#zip-safe-and-not-zip-safe. You can do so in the setup.py file:

    # ...
    setup(
        # ...
        zip_safe=False,
    )
    

    Thanks!

    bug 
    opened by Vayel 7
  • In Django 2.0 / Python 3.6 getting the error AttributeError: 'Library' object has no attribute 'assignment_tag'

    In Django 2.0 / Python 3.6 getting the error AttributeError: 'Library' object has no attribute 'assignment_tag'

    python manage.py test solo --settings=solo.tests.settings

    ...... site-packages/solo/templatetags/solo_tags.py", line 16, in @register.assignment_tag(name=solo_settings.GET_SOLO_TEMPLATE_TAG_NAME) AttributeError: 'Library' object has no attribute 'assignment_tag'

    opened by mohamed-osama-aboelkheir 7
  • Publish 2.0.0 to PyPI (Django 4.0)

    Publish 2.0.0 to PyPI (Django 4.0)

    @lazybird Could you please release a new sdist and wheel to PyPI for the 2.0.0 release? This is required to allow Django 4.0 users to use django-solo.

    To create a wheel along with source distribution:

    (venv) $ python -m pip install --upgrade pip setuptools wheel
    (venv) $ python setup.py sdist bdist_wheel
    
    # See dist/*.whl
    

    To upload sdist and wheel:

    (venv) $ pip install twine
    (venv) $ twine upload dist/*
    
    opened by johnthagen 5
  • verbose_name_plural for SingletonModelAdmin

    verbose_name_plural for SingletonModelAdmin

    Can you add in so that if the model is a SingletonModelAdmin, the name that is displayed in the admin is the verbose_name instead of the verbose_name_plural ?

    opened by radzhome 5
  • Django 4.x deprecation errors (ugettext + force_text)

    Django 4.x deprecation errors (ugettext + force_text)

    Upgrading to Django 3.x and using Django-Solo 1.1.3 raise these deprecations:

    solo/admin.py:53: RemovedInDjango40Warning: django.utils.translation.ugettext() 
    is deprecated in favor of django.utils.translation.gettext().
        msg = _('%(obj)s was changed successfully.') % {'obj': force_unicode(obj)}
    
    solo/admin.py:53: RemovedInDjango40Warning: force_text()
     is deprecated in favor of force_str().
        msg = _('%(obj)s was changed successfully.') % {'obj': force_unicode(obj)}
    

    It will take a while before Django 4.x is here, so no need to rush yet. I'll have a look if I'm able to create a PR myself.

    bug 
    opened by dennissiemensma 4
  • Crash on migrations

    Crash on migrations

    I have an issue with running manage.py migrate - it tries to run ModelName.get_solo() method and fails with database error.

    App structure: --- models.py --- helpers/ ----- bot.py

    In bot.py I'm doing:

    from appname.models import ModelName
    config = ModelName.get_solo()
    

    How to prevent execution of ModelName.get_solo() while manage.py migrate ?

    opened by deusesx 4
  • django-reversion integration

    django-reversion integration

    Usecase

    I want to have a singleton object with versions.

    Integration

    At first the were several issues with integrating it all together.

    reversion/admin.py:

    def change_view(self, request, object_id, form_url='', extra_context=None):
            with self.create_revision(request):
                # ugly hack to make it work:
                return admin.ModelAdmin.change_view(self, request, object_id, form_url, extra_context)
    

    solo/admin.py:

        def change_view(self, request, object_id, extra_context=None, form_url='/'):
            if object_id == '1':
                self.model.objects.get_or_create(pk=1)
            return super(SingletonModelAdmin, self).change_view(
                request,
                object_id,
                form_url=form_url,  # this parameter was required
                extra_context=extra_context,
            )
    

    and my own admin.py:

    from solo.admin import SingletonModelAdmin
    from reversion.admin import VersionAdmin
    
    class MyModelAdmin(VersionAdmin, SingletonModelAdmin):
        pass  # it does not work with `MyModelAdmin(SingletonModelAdmin, VersionAdmin)`
    
    admin.site.register(Document, MyModelAdmin)
    

    TODO

    1. I have not tried to run any tests
    2. Ugly hack with admin.ModelAdmin.change_view(self, ...) should be changed
    3. Any other things to keep in mind?

    Demo

    2016-06-26 14 41 04

    2016-06-26 14 40 56

    2016-06-26 14 40 49
    opened by sobolevn 4
  • TemplateDoesNotExist  admin/solo/change_form.html

    TemplateDoesNotExist admin/solo/change_form.html

    I'm working on django 1.7.5 with django-suit, the error occurs access my singleton model.

    I corrected this error by commenting the line # 13 admin.py: change_form_template = "admin / solo / change_form.html"

    TemplateDoesNotExist at /admin/config/siimciconfig/

    admin/solo/change_form.html

    Request Method: GET Request URL: http://localhost:8000/admin/config/siimciconfig/ Django Version: 1.7.5 Exception Type: TemplateDoesNotExist Exception Value:

    admin/solo/change_form.html

    Exception Location: /home/leon/.virtualenvs/django1.7/local/lib/python2.7/site-packages/django/template/loader.py in find_template, line 136 Python Executable: /home/leon/.virtualenvs/django1.7/bin/python Python Version: 2.7.8 Python Path:

    ['/media/ubuntu13/home/leon/django1.7/siaiepi', '/home/leon/.virtualenvs/django1.7/local/lib/python2.7/site-packages/django_solo-1.1.0-py2.7.egg', '/home/leon/.virtualenvs/django1.7/lib/python2.7/site-packages/django_solo-1.1.0-py2.7.egg', '/home/leon/.virtualenvs/django1.7/lib/python2.7', '/home/leon/.virtualenvs/django1.7/lib/python2.7/plat-x86_64-linux-gnu', '/home/leon/.virtualenvs/django1.7/lib/python2.7/lib-tk', '/home/leon/.virtualenvs/django1.7/lib/python2.7/lib-old', '/home/leon/.virtualenvs/django1.7/lib/python2.7/lib-dynload', '/usr/lib/python2.7', '/usr/lib/python2.7/plat-x86_64-linux-gnu', '/usr/lib/python2.7/lib-tk', '/home/leon/.virtualenvs/django1.7/local/lib/python2.7/site-packages', '/home/leon/.virtualenvs/django1.7/lib/python2.7/site-packages']

    Server time: Lun, 2 Mar 2015 18:46:49 -0500

    opened by loco0321 4
  • Django migrations don't work if you use the model in code without making migrations first

    Django migrations don't work if you use the model in code without making migrations first

    if I take my existing model

    class SiteConfiguration(SingletonModel):
         site_name = models.CharField(max_length=255, default='Administration')
    

    then add to it a additional field

    class SiteConfiguration(SingletonModel):
         site_name = models.CharField(max_length=255, default='Administration')
         message = models.TextField(default="this is a standard message")
    

    then inside of django views.py

    ...
    site_config = SiteConfiguration.get_solo()
    def view(request):
          site_config.message
         return HttpResponse("some response")
    ...
    

    then try to run a migration i get a error django.db.utils.OperationalError: no such column: siteconfiguration.message

    this is a very big problem for me because I often write my code first to see how it looks first before making the migrations. Also this does work in a standard model so it should work in a SingletonModel

    opened by dragoncommits 0
  • whenever I update the model I get

    whenever I update the model I get "No such column" error

    I cant seem to update the model without getting an error when trying to makemigrations / migrate that states the field I am trying to add does not exist in the table.

    For example: models:

        maintenance_mode = models.BooleanField(default=False)
        name = models.CharField(max_length=255, default='Open Mosque Project')
        about = models.TextField(max_length=2000, blank=True) ## new field i've added ##
    

    view:

    from config.models import CentreProfile
    centre = CentreProfile.objects.get()
    ##### Variables loaded from centre profile here #####
    centre_name = centre.name 
    

    Error when I try to make migrations

    django.db.utils.OperationalError: no such column: config_centreprofile.about

    opened by bitFez 1
  • Update cache after instance save

    Update cache after instance save

    Maybe I'm missing something obvious, but is there a way to clear the cache after saving the instance directly, instead of via the form?

    We have one singleton that's updated automatically via a worker task, so doesn't go through the form. If I run this:

    sgtn = MySingleton.get_solo()
    sgtn.name = 'New Value'
    sgtn.save()
    

    and then I query the result using MySingleton.get_solo().name I get the previous value.

    I tried overriding the save method like this:

    def save(self, *args, **kwargs):
            self.clear_cache()
            super().save(*args, **kwargs)  
    

    But that didn't work either. Is there a way of configuring this? Seems like quite a reasonable use case if not.

    question 
    opened by matt-dalton 0
  • App verbose_name not used in breadcrumbs

    App verbose_name not used in breadcrumbs

    Django uses verbose_name of apps when constructing breadcrumbs. Solo doesn't :(

    django/contrib/admin/templates/admin/change_form.html:

    {{ opts.app_config.verbose_name }}
    

    solo/templates/admin/solo/change_form.html:

    {{ opts.app_label|capfirst|escape }}
    

    Should probably update the code.

    It is quite possible that some extra care has to be taken to maintain support for older versions of Django. I didn't check...

    feature request 
    opened by frnhr 1
Releases(2.0.0)
  • 2.0.0(Dec 10, 2021)

    What's Changed

    • Use assertEqual instead of assertEquals for Python 3.11 compatibility. by @tirkarthi in https://github.com/lazybird/django-solo/pull/103
    • Change package URL to use HTTPS by @johnthagen in https://github.com/lazybird/django-solo/pull/105
    • Setup automated testing using GitHub Actions by @johnthagen in https://github.com/lazybird/django-solo/pull/106
    • Django 4.0 Support by @johnthagen in https://github.com/lazybird/django-solo/pull/107
    • Release 2.0.0 by @johnthagen in https://github.com/lazybird/django-solo/pull/112

    New Contributors

    • @tirkarthi made their first contribution in https://github.com/lazybird/django-solo/pull/103

    Full Changelog: https://github.com/lazybird/django-solo/compare/1.2.0...2.0.0

    Source code(tar.gz)
    Source code(zip)
  • 1.2.0(Sep 29, 2021)

Owner
Sylvain Toé
Sylvain Toé
The Django Leaflet Admin List package provides an admin list view featured by the map and bounding box filter for the geo-based data of the GeoDjango.

The Django Leaflet Admin List package provides an admin list view featured by the map and bounding box filter for the geo-based data of the GeoDjango. It requires a django-leaflet package.

Vsevolod Novikov 33 Nov 11, 2022
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 8, 2023
Store model history and view/revert changes from admin site.

django-simple-history django-simple-history stores Django model state on every create/update/delete. This app supports the following combinations of D

Jazzband 1.8k Jan 6, 2023
Django-static-site - A simple content site framework that harnesses the power of Django without the hassle

coltrane A simple content site framework that harnesses the power of Django with

Adam Hill 57 Dec 6, 2022
Dynamic Django settings.

Constance - Dynamic Django settings A Django app for storing dynamic settings in pluggable backends (Redis and Django model backend built in) with an

Jazzband 1.5k Jan 7, 2023
A helper for organizing Django project settings by relying on well established programming patterns.

django-configurations django-configurations eases Django project configuration by relying on the composability of Python classes. It extends the notio

Jazzband 953 Dec 29, 2022
DRF_commands is a Django package that helps you to create django rest framework endpoints faster using manage.py.

DRF_commands is a Django package that helps you to create django rest framework endpoints faster using manage.py.

Mokrani Yacine 2 Sep 28, 2022
DCM is a set of tools that helps you to keep your data in your Django Models consistent.

Django Consistency Model DCM is a set of tools that helps you to keep your data in your Django Models consistent. Motivation You have a lot of legacy

Occipital 59 Dec 21, 2022
Django application and library for importing and exporting data with admin integration.

django-import-export django-import-export is a Django application and library for importing and exporting data with included admin integration. Featur

null 2.6k Dec 26, 2022
Django admin CKEditor integration.

Django CKEditor NOTICE: django-ckeditor 5 has backward incompatible code moves against 4.5.1. File upload support has been moved to ckeditor_uploader.

null 2.2k Jan 2, 2023
Django admin CKEditor integration.

Django CKEditor NOTICE: django-ckeditor 5 has backward incompatible code moves against 4.5.1. File upload support has been moved to ckeditor_uploader.

null 2.2k 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
Add Chart.js visualizations to your Django admin using a mixin class

django-admincharts Add Chart.js visualizations to your Django admin using a mixin class. Example from django.contrib import admin from .models import

Dropseed 22 Nov 22, 2022
📝 Sticky Notes in Django admin

django-admin-sticky-notes Share notes between superusers. Installation Install via pip: pip install django_admin_sticky_notes Put django_admin_sticky_

Dariusz Choruży 7 Oct 6, 2021
mirage ~ ♪ extended django admin or manage.py command.

mirage ~ ♪ extended django admin or manage.py command. ⬇️ Installation Installing Mirage with Pipenv is recommended. pipenv install -d mirage-django-l

Shota Shimazu 6 Feb 14, 2022
Super simple bar charts for django admin list views visualizing the number of objects based on date_hierarchy using Chart.js.

Super simple bar charts for django admin list views visualizing the number of objects based on date_hierarchy using Chart.js.

foorilla LLC 4 May 18, 2022
Intellicards-backend - A Django project bootstrapped with django-admin startproject mysite

Intellicards-backend - A Django project bootstrapped with django-admin startproject mysite

Fabrizio Torrico 2 Jan 13, 2022
This is a repository for collecting global custom management extensions for the Django Framework.

Django Extensions Django Extensions is a collection of custom extensions for the Django Framework. Getting Started The easiest way to figure out what

Django Extensions 6k Dec 26, 2022
Generate generic activity streams from the actions on your site. Users can follow any actors' activities for personalized streams.

Django Activity Stream What is Django Activity Stream? Django Activity Stream is a way of creating activities generated by the actions on your site. I

Justin Quick 2.1k Dec 29, 2022