Django 'Sites' Model - what is and why is 'SITE_ID = 1'?
Asked Answered
M

6

62

I am trying to work with Sites Model of Django.

I dont quite understand why SITE_ID should be SITE_ID = 1.

in the docs:

The ID, as an integer, of the current site in the django_site database table. This is used so that application data can hook into specific sites and a single database can manage content for multiple sites.

why 1? what is the current site? this is not clearly explained in the docs.

lets say, I have www.coolsite.com and some other subdomains like www.wow.coolsite.com and www.awesome.coolsite.com

I want to render different content depending on domain name.

my question is, or better, are:

  1. Do I have to add all those domains into Sites Table in DB?
  2. if so, how should I set SITE_ID in settings? Do I have to set all ids like SITE_ID = 1, SITE_ID = 2.. etc?
  3. what does current site has to do with SITE_ID = 1?

I am a bit confused here.

I thought, each Site (e.g. www.wow.coolsite.com) should be a separate django project so that they can have their own settings.py? and in each of those settings.py's, I will set the id of that page from Sites table? but then there are many django projects which also doesnot make sense to me.

Maxima answered 24/8, 2014 at 4:58 Comment(0)
N
48

Django was created from a set of scripts developed at a newspaper to publish content on multiple domains; using one single content base.

This is where the "sites" module comes in. Its purpose is to mark content to be displayed for different domains.

In previous versions of django, the startproject script automatically added the django.contrib.sites application to INSTALLED_APPS, and when you did syncdb, a default site with the URL example.com was added to your database, and since this was the first site, its ID was 1 and that's where the setting comes from.

Keep in mind that starting from 1.6, this framework is not enabled by default. So if you need it, you must enable it

The SITE_ID setting sets the default site for your project. So, if you don't specify a site, this is the one it will use.

So to configure your application for different domains:

  1. Enable the sites framework
  2. Change the default site from example.com to whatever your default domain is. You can do this from the django shell, or from the admin.
  3. Add your other sites for which you want to publish content to the sites application. Again, you can do this from the django shell just like any other application or from the admin.
  4. Add a foreign key to the Site model in your object site = models.ForeignKey(Site)
  5. Add the site manager on_site = CurrentSiteManager()

Now, when you want to filter content for the default site, or a particular site:

foo = MyObj.on_site.all() # Filters site to whatever is `SITE_ID`
foo = MyObj.objects.all() # Get all objects, irrespective of what site
                          # they belong to

The documentation has a full set of examples.

Neb answered 24/8, 2014 at 5:21 Comment(5)
thanks, but i am not still sure about SITE_ID. what if i have 3 sites? do i have to add all those 3 site ids into one single main settings.py? this doesnot make any sense to me right now :(Maxima
i think, each site should be a separate django project so that they can have their own settings.py? and in that settings.py, i will set the id of that page from Sites table? but then there are many django projects which also doesnot make sense to me :(Maxima
You don't create multiple projects, you just add all the domains to the sites database; then based on what the current domain is, you filter the content you want to show. Its a very simple, basic implementation.Neb
django knows the current site depending on SITE_ID in settings.py, right? How can I have multiple SITE_ID's in a single settings.py and how can foo = MyObj.on_site.all() know what the current site is? sorry for many questions.Maxima
You have one SITE_ID in a settings file. Each site has its own server. On each server you set a different DJANGO_SETTINGS_MODULE, picking up a different settings, hence a different SITE_ID.Martyrdom
B
24

Things would be much easier to understand if Django's default SiteAdmin included the id field in the list_display fields.

To do this, you can redefine SiteAdmin (anywhere in your app, but I'd recommend your admin.py or maybe your urls.py) like this:

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

admin.site.unregister(Site)
class SiteAdmin(admin.ModelAdmin):
    fields = ('id', 'name', 'domain')
    readonly_fields = ('id',)
    list_display = ('id', 'name', 'domain')
    list_display_links = ('name',)
    search_fields = ('name', 'domain')
admin.site.register(Site, SiteAdmin)

After including this code snippet, the ID for each "Site" will be shown in the first column of the admin list and inside the form as a read only field. These 'id' fields are what you need to use as SITE_ID:

modified admin page showing Site records' id

The concept is that each different site runs in a different application server instance, launched using a different yourdomain_settings.py that then includes a base_settings.py with the rest of the common configuration.

Each of these yourdomain_settings.py will define its own SITE_ID and all other different settings.py parameters that they need to look and be different from each other (static resources, templates, etc.) then you'll define a DJANGO_SETTINGS_MODULE environment variable pointing to that specific yourdomain_settings.py file when launching the application server instance for that domain.

A further note: get_current_site(request) does need request to be available for it to work. If your code doesn't have one, you can use Site.objects.get_current() that however will need a SITE_ID properly defined in the running application server's settings.

Basketwork answered 6/1, 2018 at 5:45 Comment(1)
That's the answer I was looking for. Django's documentation is not clear enough to make me sure it's intended to be used like that. Sometimes it's worth going to the last answer ;)Inert
A
6

This is a late answer but for anyone else having SITE_ID issues and Site problems. Inside the database, django has a django_site table with(id, domain, name). This is where django stores the SITE_IDs. Mine was actually 5 in the database but i had it set to SITE_ID=1 in the settings.

Knowing that, i can now go back to the database and clear it to get back to zero or use the actual id in the database.

Antho answered 22/11, 2015 at 16:46 Comment(0)
M
5

This is covered in the documentation for the Sites framework:

In order to serve different sites in production, you’d create a separate settings file with each SITE_ID (perhaps importing from a common settings file to avoid duplicating shared settings) and then specify the appropriate DJANGO_SETTINGS_MODULE for each site.

But if you didn't want to do it that way, you can not set SITE_ID at all and just look up the current site based on the domain name in your views using get_current_site:

from django.contrib.sites.shortcuts import get_current_site

def my_view(request):
    current_site = get_current_site(request)
    if current_site.domain == 'foo.com':
        # Do something
        pass
    else:
        # Do something else.
        pass
Mistook answered 28/4, 2016 at 20:36 Comment(0)
W
1

This link explains it:

You’ll want to create separate settings files for each domain you’re adding; each one will need its own MEDIA_URL and other settings. You’ll also want to do two things to make sure everything works out properly for administering the different sites:

Create a new Site object in your admin for each domain, and put the id of that Site into its settings file as SITE_ID so Django knows which site in the database corresponds to this settings file.

In the settings file for your original site (the one with id 1), add the other sites’ settings files to the ADMIN_FOR setting, to let Django know that this one instance of the admin application will handle all of the sites.

Also, if you wanna figure out how to modify models and set the views You may take a look at this link: https://django.cowhite.com/blog/managing-multiple-websites-with-a-common-database-in-django-the-sites-framework/

Wilford answered 25/1, 2019 at 23:13 Comment(1)
A link to a solution is welcome, but please ensure your answer is useful without it: add context around the link so your fellow users will have some idea what it is and why it’s there, then quote the most relevant part of the page you're linking to in case the target page is unavailable. Answers that are little more than a link may be deleted.Mucronate
S
0

"Sites" was initially intended for multiple servers sharing a DB, but was extended with feature #15089 around version 1.4 to support basic multitenancy.

Nowadays you can simply not define SITE_ID if you always use methods that take a request.

Seibold answered 14/9, 2023 at 15:30 Comment(1)
Your answer could be improved with additional supporting information. Please edit to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers in the help center.Purapurblind

© 2022 - 2024 — McMap. All rights reserved.