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é
An example of Django project with basic user functionality and account activation.

Simple Django Login and Registration An example of Django project with basic user functionality. Screenshots Log In Create an account Authorized page

Hussein Sarea 3 Oct 19, 2022
A Django web application to receive, virus check and validate transfers of digital archival records, and allow archivists to appraise and accession those records.

Aurora Aurora is a Django web application that can receive, virus check and validate transfers of digital archival records, and allows archivists to a

Rockefeller Archive Center 20 Aug 30, 2022
A simple trivia quizzz web app made using django

Trivia Quizzz A simple trivia quizzz web app made using django Demo http://triviaquizzz.herokuapp.com/ & https://triviaquiz.redcrypt.xyz Features Goog

Rachit Khurana 2 Feb 10, 2022
This repository contains django library management system project.

Library Management System Django ** INSTALLATION** First of all install python on your system. Then run pip install -r requirements.txt to required se

whoisdinanath 1 Dec 26, 2022
xsendfile etc wrapper

Django Sendfile This is a wrapper around web-server specific methods for sending files to web clients. This is useful when Django needs to check permi

John Montgomery 476 Dec 01, 2022
Projeto Crud Django and Mongo

Projeto-Crud_Django_and_Mongo Configuração para rodar o projeto Download Project

Samuel Fernandes Oliveira 2 Jan 24, 2022
Automatically reload your browser in development.

django-browser-reload Automatically reload your browser in development. Requirements Python 3.6 to 3.10 supported. Django 2.2 to 4.0 supported. Are yo

Adam Johnson 254 Jan 04, 2023
Django Simple Spam Blocker is blocking spam by regular expression.

Django Simple Spam Blocker is blocking spam by regular expression.

Masahiko Okada 23 Nov 29, 2022
Django Persistent Filters is a Python package which provide a django middleware that take care to persist the querystring in the browser cookies.

Django Persistent Filters Django Persistent Filters is a Python package which provide a django middleware that take care to persist the querystring in

Lorenzo Prodon 2 Aug 05, 2022
Django REST Client API

Django REST Client API Client data provider API.

Ulysses Monteiro 1 Nov 08, 2021
Automatic caching and invalidation for Django models through the ORM.

Cache Machine Cache Machine provides automatic caching and invalidation for Django models through the ORM. For full docs, see https://cache-machine.re

846 Nov 26, 2022
Easily share data across your company via SQL queries. From Grove Collab.

SQL Explorer SQL Explorer aims to make the flow of data between people fast, simple, and confusion-free. It is a Django-based application that you can

Grove Collaborative 2.1k Dec 30, 2022
A simple plugin to attach a debugger in Django on runserver command.

django-debugger A simple plugin to attach a debugger in Django during runserver Installation pip install django-debugger Usage Prepend django_debugger

Sajal Shrestha 11 Nov 15, 2021
django-idom allows Django to integrate with IDOM

django-idom allows Django to integrate with IDOM, a package inspired by ReactJS for creating responsive web interfaces in pure Python.

113 Jan 04, 2023
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

2.6k Dec 26, 2022
✋ Auto logout a user after specific time in Django

django-auto-logout Auto logout a user after specific time in Django. Works with Python 🐍 ≥ 3.7, Django 🌐 ≥ 3.0. ✔️ Installation pip install django-a

Georgy Bazhukov 21 Dec 26, 2022
Strawberry-django-plus - Enhanced Strawberry GraphQL integration with Django

strawberry-django-plus Enhanced Strawberry integration with Django. Built on top

BLB Ventures 138 Dec 28, 2022
Django Federated Login provides an authentication bridge between Django projects and OpenID-enabled identity providers.

Django Federated Login Django Federated Login provides an authentication bridge between Django projects and OpenID-enabled identity providers. The bri

Bouke Haarsma 18 Dec 29, 2020
Backend with Django .

BackendCode - Cookies Documentation: https://docs.djangoproject.com/fr/3.2/intro/ By @tcotidiane33 & @yaya Models Premium class Pack(models.Model): n

just to do it 1 Jan 28, 2022
Add a help desk or knowledge base to your Django project with only a few lines of boilerplate code.

This project is no longer maintained. If you are interested in taking over the project, email Zapier 487 Dec 06, 2022