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é
This a Django TODO app project and practiced how to deploy and publish the project to Heroku

ToDo App Demo | Project Table of Contents Overview Built With Features How to use Acknowledgements Contact Overview Built With HTML CSS JS Django How

Cetin OGUT 1 Nov 19, 2021
Automated image processing for Django. Currently v4.0

ImageKit is a Django app for processing images. Need a thumbnail? A black-and-white version of a user-uploaded image? ImageKit will make them for you.

Matthew Dapena-Tretter 2.1k Jan 04, 2023
An opinionated Django CMS setup bundled as an Aldryn Addon

Aldryn CMS |PyPI Version| An opinionated django CMS setup bundled as an Aldryn Addon. This package will auto configure django CMS including some extra

Vladimir Bezrukov 1 Nov 12, 2021
A Django app for working with BTCPayServer

btcpay-django A Django app for working with BTCPayServer Installation pip install btcpay-django Developers Release To cut a release, run bumpversion,

Crawford 3 Nov 20, 2022
Reusable workflow library for Django

django-viewflow Viewflow is a lightweight reusable workflow library that helps to organize people collaboration business logic in django applications.

Viewflow 2.3k Jan 08, 2023
I managed to attach the Django Framework to my Telegram Bot and set a webhook

I managed to attach the Django Framework to my Telegram Bot and set a webhook. I've been developing it from 10th of November 2021 and I want to have a basic working prototype.

Valentyn Vovchak 2 Sep 08, 2022
Developer-friendly asynchrony for Django

Django Channels Channels augments Django to bring WebSocket, long-poll HTTP, task offloading and other async support to your code, using familiar Djan

Django 5.5k Jan 06, 2023
A Django based shop system

django-SHOP Django-SHOP aims to be a the easy, fun and fast e-commerce counterpart to django-CMS. Here you can find the full documentation for django-

Awesto 2.9k Dec 30, 2022
Radically simplified static file serving for Python web apps

WhiteNoise Radically simplified static file serving for Python web apps With a couple of lines of config WhiteNoise allows your web app to serve its o

Dave Evans 2.1k Dec 15, 2022
A Django application that provides country choices for use with forms, flag icons static files, and a country field for models.

Django Countries A Django application that provides country choices for use with forms, flag icons static files, and a country field for models. Insta

Chris Beaven 1.2k Jan 07, 2023
Django backend of Helium's planner application

Helium Platform Project Prerequisites Python (= 3.6) Pip (= 9.0) MySQL (= 5.7) Redis (= 3.2) Getting Started The Platform is developed using Pytho

Helium Edu 17 Dec 14, 2022
Book search Django web project that uses requests python library and openlibrary API.

Book Search API Developer: Vladimir Vojtenko Book search Django web project that uses requests python library and openlibrary API. #requests #openlibr

1 Dec 08, 2021
Django datatables and widgets, both AJAX and traditional. Display-only ModelForms.

Django datatables and widgets, both AJAX and traditional. Display-only ModelForms. ModelForms / inline formsets with AJAX submit and validation. Works with Django templates.

Dmitriy Sintsov 132 Dec 14, 2022
🗂️ 🔍 Geospatial Data Management and Search API - Django Apps

Geospatial Data API in Django Resonant GeoData (RGD) is a series of Django applications well suited for cataloging and searching annotated geospatial

Resonant GeoData 53 Nov 01, 2022
A simple Blog Using Django Framework and Used IBM Cloud Services for Text Analysis and Text to Speech

ElhamBlog Cloud Computing Course first assignment. A simple Blog Using Django Framework and Used IBM Cloud Services for Text Analysis and Text to Spee

Elham Razi 5 Dec 06, 2022
Wrapping Raml around Django rest-api's

Ramlwrap is a toolkit for Django which allows a combination of rapid server prototyping as well as enforcement of API definition from the RAML api. R

Jmons 8 Dec 27, 2021
A test microblog project created using Django 4.0

django-microblog This is a test microblog project created using Django 4.0. But don't worry this is a fully working project. There is no super-amazing

Ali Kasimoglu 8 Jan 14, 2022
Awesome Django Blog App

Awesome-Django-Blog-App Made with love django as the backend and Bootstrap as the frontend ! i hope that can help !! Project Title Django provides mul

ANAS NABIL 2 Feb 08, 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
Drf-stripe-subscription - An out-of-box Django REST framework solution for payment and subscription management using Stripe

Drf-stripe-subscription - An out-of-box Django REST framework solution for payment and subscription management using Stripe

Oscar Y Chen 68 Jan 07, 2023