(Comments)
Django provides the sites framework which allows us to associate the data (objects/models) and functionality with a particular website. This is particularly useful if you are managing multiple websites with a single code base (as in a content-management system) or multiple websites that share a common database.
To enable the sites framework,
django.contrib.sites
to your INSTALLED_APPS
settingSITE_ID
setting (this will be used by get_current_site()
function if defined)This framework mainly works based on the django.contrib.sites.models.Site
model. The model has domain
(stores fully qualified domain name) and name
(stores a verbose/human-readable name) fields. The most obvious way of using the sites is to use the Site
model as a foreign key in a model to associate the data with a website. For example, say, a post in a blog is associated with a website, then the model will be represented as:
from django.contrib.sites.models import Site class BlogPost(models.Model): title = models.CharField(max_length=120) content = models.TextField() # .... some other fields site = models.ForeignKey(Site)
The list of BlogPost
s of a site can be listed with:
post_list = BlogPost.objects.filter(site__domain='www.mydomain.com')
Of course, hard-coding the domain is not the proper way. The view has to get the list based on the site the visitor is viewing. The clean way of getting the current site as a Site
object is to use the get_current_site
method as follows:
from django.contrib.sites.shortcuts import get_current_site def posts_view(request): current_site = get_current_site(request) post_list = BlogPost.objects.filter(site=current_site) # We have the needed posts
Django is smart. It also provides a get_current()
method to the Site
's object manager. So the statement current_site = get_current_site(request)
can be replaced with current_site = Site.objects.get_current()
, and this method sets the cache for current site, so the subsequent calls to Site.objects.get_current()
will be served from cache.
If your data is tightly bound with sites and have the SITE_ID
setting defined (different code base or settings per website), Django provides another enhancement - the CurrentSIteManager
. This manger can be used along with the default model manager (django.db.models.Manger
) as follows:
from django.contrib.sites.managers import CurrentSiteManager class BlogPost(models.Model): title = models.CharField(max_length=120) content = models.TextField() # .... some other fields site = models.ForeignKey(Site) # objects = models.Manger() is implicit on_site = CurrentSiteManager() # Your alternative manager
This helps us with filtering the objects based on the site. The query BlogPost.objects.filter(site=settings.SITE_ID)
can be written as BlogPost.on_site.all()
. The CurrentSiteManager
will look for a foreign key field named site or a many to many field named sites to filter the data. If the field name is different from those, it can be specified in the initialization of the manager as:
from django.contrib.sites.managers import CurrentSiteManager class BlogPost(models.Model): title = models.CharField(max_length=120) content = models.TextField() # .... some other fields published_in = models.ForeignKey(Site) # This is the field of interest # objects = models.Manger() is implicit on_site = CurrentSiteManager('published_in')
One other feature to note is the django.contrib.sites.middleware.CurrentSiteMiddleware
middleware that sets the site attribute on the request object. Just add the django.contrib.sites.middleware.CurrentSiteMiddleware
to the MIDDLEWARE (or MIDDLEWARE_CLASSES in old versions). The current site object will be available as request.site
in Django's views.
We develop web applications to our customers using python/django/angular.
Contact us at hello@cowhite.com
Comments