Best practice for Django sites to set up site configuration variables?

Viewed 4170

all! I am writing a Django blog site.

I am new to Django. Since Django has the philosophy of loose coupling, I believe it's best to follow their beliefs when using their framework.

So I am encountering a dilemma here:

I want to set up some variables for my blog, say, the blog title, slogan, and the maximum length of digest on the homepage of each blog I wrote, and how many blog digest should I display on the homepage per page.

I can do this by creating a new app in my Django project, and create models for my site's config variables, then read those variables from other app, but this practice obviously breaks the philosophy of loose coupling.

The only work around I can think of is setting up environment variables in my sites .wsgi file (I use Apache and mod_wsgi to serve Python scripts) But I don't think messing up with environment variable is 'clean' enough.

Can anyone suggest me a better solution?

3 Answers

In my opinion, the best way to do this is by adding a model related to Site model using inheritance

First add site id to your Django settings file

SITE_ID = 1

now create a model in an app

from django.db import models
from django.contrib.sites.models import Site

class Settings(Site):
    field_a = models.CharField(max_length=150, null=True)
    field_b = models.CharField(max_length=150, null=True)

    class Meta:
        verbose_name_plural = 'settings'
        db_table = 'core_settings' # core is name of my app

    def __str__(self) -> str:
        return 'Settings'

then edit apps.py file of that app

from django.apps import AppConfig
from django.db.models.signals import post_migrate

def build_settings(sender, **kwargs):
    from django.contrib.sites.models import Site
    from .models import Settings
    if Settings.objects.count() < 1:
        Settings.objects.create(site_ptr=Site.objects.first())


class CoreConfig(AppConfig):
    default_auto_field = 'django.db.models.BigAutoField'
    name = 'project.apps.core'

    def ready(self) -> None:
        post_migrate.connect(build_settings, sender=self)

now every time you run migrations a row will auto-generated in core_settings that have a one to one relationship with your Site model

and now you can access to your settings like this


Site.objects.get_current().settings.access_id

optional: if have only a single site unregister site model from admin site and disable creating and deleting settings model in admin panel

from django.contrib import admin
from . import models
from django.contrib.sites.models import Site


admin.site.unregister(Site)

@admin.register(models.Settings)
class SettingAdminModel(admin.ModelAdmin):
    def has_delete_permission(self, request,obj=None) -> bool:
        return False

    def has_add_permission(self, request) -> bool:
        return False
Related