Django Sites Framework

admin

by
5th December 2016

Have you ever had to work with more than one site of the same organization at the same time? In this post, I’m going to expose a possible solution to associate sites in an easy way for optimization.

Here is an example. In Devsar, we develop “Find Your Trainer”, an online platform to book personal trainers in many states of the USA (another post in this blog explains this project in more detail). And at the moment, FYT organization is being associated with another fitness app, “Your Trainer”.

captura

This is the situation: both sites have trainer objects. Some trainers have to appear either on one site or the other, while some should be on both.

Django comes with a “sites” framework which helps you to manage this. It lets you associate objects and functionality to particular websites. You can have separated software with independent data, but maybe it’s useful to use that data together. The framework is based on a simple “Site” model which stores the domain and name of a website.

The way to do it is sharing data from the same database with an attribute in the model used as a differential. For example:

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

class Trainer(models.Model):
     first_name = models.CharField(max_length=32)
     # ...
     sites = models.ManyToManyField(Site)

Now with this solution, the content doesn’t have to be posted twice and could be edited for both sites from the same interface (django admin). This also allows re-utilization of the same view code for both sites, simply by checking in the request if the object belongs to the referrer website.

from django.contrib.sites.shortcuts import get_current_site

def trainer_detail(request, trainer_id):
    try:
        trainer = Trainer.objects.get(pk=trainer_id, sites__id=get_current_site(request).id)
    except Trainer.DoesNotExist:
        raise Http404("Trainer doesn’t exist on this site")
    # …

def trainers_list(request):
        trainers = Trainer.objects.filter(      sites__in=[get_current_site(request)])
    # ...

Otherwise, you could associate model strictly to one site:

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

class Trainer(models.Model):
    first_name = models.CharField(max_length=32)
    # ...
    site = models.ForeignKey(Site, on_delete=models.CASCADE)

And why would you use it? For example, one inefficient solution for this is to publish trainers twice, on one site, and on another in case you want it in both. But that is an annoying task and you get repeated data. Using sites you can avoid that.

So, you should take a few seconds to create site object with your domain info, set your SITE_ID in the settings file, and take advantage of this in places where you need it! With not many steps, you’re using sites and it helps you to manage the scenario of two different apps with data or functionality in common.