CarlLee
CarlLee

Reputation: 4182

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

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?

Upvotes: 10

Views: 5010

Answers (3)

Mahdi mehrabi
Mahdi mehrabi

Reputation: 1744

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

Upvotes: 0

Jj.
Jj.

Reputation: 3160

First thing you can do is set up those variables in your project's settings module, many apps do that:

# settings
BLOG_TITLE = 'My title'

Then, a good practice is to provide settings defaults, so your app should have a settings file

# blog/settings.py
from django.conf import settings
BLOG_TITLE = getattr(settings, 'BLOG_TITLE', 'MY default title')

# Then wherever, views or context processor
from blog import settings # See how we're not importing project's settings

title = settings.BLOG_TITLE

Another alternative is to create a "Blog" model that contains all those variables, this may invite you to make your app to have a blog tied per Django sites

from django.contrib.sites.models import Site
class Blog(models.Model):
  site = models.OneToOneField(Site) # Tied up to a Django site
  title = models.CharField(max_length=256)

Now you can change those values from your Admin interface and use them in your views or context processor

site = Site.objects.get_current() # Installed Django Sites app and middleware
blog = site.blog
print blog.title

Upvotes: 10

Silver Light
Silver Light

Reputation: 45922

You can create settings or constants file in your app folder and use it. This way all your constants will be bound to your application:

apps/
  blog/
    __init__.py
    models.py
    urls.py
    constants.py # <-- here it is!

File can look like this:

BLOG_TITLE = 'My super blog'
# ...

And you can use tour constants like this:

import blog.constants
# ...
return render_to_response('index.html', {title: blog.constants.BLOG_TITLE})

And in template:

<title>{{ title }}</title>  

Upvotes: 4

Related Questions