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

Related tags

Djangodjango-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/[email protected]#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é
Extensions for using Rich with Django.

django-rich Extensions for using Rich with Django. Requirements Python 3.6 to 3.10 supported. Django 2.2 to 4.0 supported. Are your tests slow? Check

Adam Johnson 88 Dec 26, 2022
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 06, 2022
A Django/Python web app that functions as a digital diary

My Django Diary Full-stack web application that functions as a digital diary using Django, Python, SQLite, HTML & CSS. Things I learned during this pr

1 Sep 30, 2022
Money fields for Django forms and models.

django-money A little Django app that uses py-moneyed to add support for Money fields in your models and forms. Django versions supported: 1.11, 2.1,

1.4k Jan 06, 2023
Advanced school management system written in Django :)

Advanced school management system written in Django :) ⚙️ Config the project First you should make venv for this project. So in the main root of proje

AminAli Mazarian 72 Dec 05, 2022
MAC address Model Field & Form Field for Django apps

django-macaddress MAC Address model and form fields for Django We use netaddr to parse and validate the MAC address. The tests aren't complete yet. Pa

49 Sep 04, 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
Flashback is an awesome, retro IRC based app built using Django

Flashback Flashback is an awesome, retro IRC based app built using Django (and the Django Rest Framework) for the backend as well as React for the fro

Unloading Gnat 1 Dec 22, 2021
This is django-import-export module that exports data into many formats

django-import-export This is django-import-export module which exports data into many formats, you can implement this in your admin panel. - Dehydrat

Shivam Rohilla 3 Jun 03, 2021
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 09, 2022
A feature flipper for Django

README Django Waffle is (yet another) feature flipper for Django. You can define the conditions for which a flag should be active, and use it in a num

950 Dec 26, 2022
Source code for Django for Beginners 3.2

The official source code for https://djangoforbeginners.com/. Available as an ebook or in Paperback. If you have the 3.1 version, please refer to this

William Vincent 10 Jan 03, 2023
A clone of https://virgool.io written in django

Virgool clone A clone of virgool blog written in django Installation first rename the .env.sample to .env and fill it. with docker docker-compose up -

Danial Selmipoor 7 Dec 23, 2022
Add infinite scroll to any django app.

django-infinite-scroll Add infinite scroll to any django app. Features - Allows to add infinite scroll to any page.

Gustavo Teixeira 1 Dec 26, 2021
Django Starter is a simple Skeleton to start with a Django project.

Django Starter Template Description Django Starter is a simple Skeleton to start

Numan Ibn Mazid 1 Jan 10, 2022
A collection of models, views, middlewares, and forms to help secure a Django project.

Django-Security This package offers a number of models, views, middlewares and forms to facilitate security hardening of Django applications. Full doc

SD Elements 258 Jan 03, 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
Official clone of the Subversion repository.

Django is a high-level Python Web framework that encourages rapid development and clean, pragmatic design. All documentation is in the "docs" directo

Raymond Penners 3 May 06, 2022
Learn Python and the Django Framework by building a e-commerce website

The Django-Ecommerce is an open-source project initiative and tutorial series built with Python and the Django Framework.

Very Academy 275 Jan 08, 2023
Django REST Client API

Django REST Client API Client data provider API.

Ulysses Monteiro 1 Nov 08, 2021