Login

change SITE_ID on fly

Author:
[email protected]
Posted:
September 30, 2008
Language:
Python
Version:
1.0
Score:
2 (after 4 ratings)

Django SITE_ID is a global setting, so the site framework requires you to run multiple instances of Django; at least one for each site. But i want have one instance for multiple sites. This snippet solve this task by change SITE_ID on fly. /sorry my bad english/

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
# 1) site_id_hook.py
from threading import local

SITE_THREAD_INFO = local()

class SiteIDHook:

    def __int__(self):        
        return SITE_THREAD_INFO.SITE_ID

    def __hash__(self):        
        return SITE_THREAD_INFO.SITE_ID

# 2) settings.py
.....
from site_id_hook import SiteIDHook, SITE_THREAD_INFO
SITE_ID = SiteIDHook()
....

# 3) site_middleware.py (simple middleware)

class SiteOnFlyDetectionMiddleware:    
    def process_request(self, request):
        sid = None
        host = request.META.get('HTTP_HOST')
        # ...
        #   any logic for `sid`
        #...
        settings.SITE_THREAD_INFO.SITE_ID = sid
           


Ok, now settings.SITE_ID will change in middleware on fly.

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 11 months, 2 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months, 3 weeks ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 6 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 7 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

plungerman (on November 2, 2008):

interesting concept. i have tried out the solution that you outlined above but it does not seem to work with the CurrentSiteManager, which is part of the Sites framework. i am seeing the error:

'thread._local' object has no attribute 'SITE_ID'

when i attempt to retrieve an object that uses the CurrentSiteManager:

obj = MyModel.on_site.get(slug=slug)

where on_site is the manager designation in the model:

on_site = CurrentSiteManager()

slug is a field that is not unique in the system but is restricted by the unique_together constraint, with slug and site as the two values.

have you run into this problem?

#

joe (on November 6, 2008):

I am not using CurrentSiteManager() at the moment, but I also encountered the error:

'thread._local' object has no attribute 'SITE_ID'

Placing this snippet's middleware (site_middleware.py above) first in settings.MIDDLEWARE_CLASSES seems to have fixed the problem.

I think the error was due to django.middleware.common.CommonMiddleware trying to access SITE_ID before it was set by this snippet's middleware.

#

plungerman (on November 6, 2008):

thanks for the quick response. that seems to have fixed the problem. unfortunately, i now experience intermittent problems while using date based generic views. i send the queryset to the generic view from urls.py :

(r'^(?P<year>\d{4})/(?P<month>\d{2})/(?P<day>\d{1,2})/(?P<slug>[-\w]+)/$', object_detail, dict(queryset=MyModel.on_site.filter(active=True),date_field='pub_date', slug_field='slug', month_format='%m', allow_future=False)),

for example, and the object_detail view will not find the desired object in the queryset because the queryset contains a result that is from another site. normally, the object_detail view will return a 404 if it does not find what it is looking for, but i removed that try/except part of that view for testing to see the actual error and i can see the queryset is for a different site than the one on which i am currently navigating.

i suspect that creating a custom wrapper view around the object_detail view that passes the queryset from that view instead of from the urls.py file, will solve the problem, but i am not certain. i have been looking at the threaded_multihost project but my first tests revealed that this solution is better suited to my needs, so i will report back if i find a solution.

#

[email protected] (on November 18, 2008):

0) it's work

1) i use this:

MIDDLEWARE_CLASSES = ( 'django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.middleware.doc.XViewMiddleware', <br /> 'myproject.app.middleware.SiteDetectionMiddleware', )

2) i use this logic for detect SITE_ID:

class SiteDetectionMiddleware:

def process_request(self, request):       
    settings.SITE_THREAD_INFO.SITE_ID = 1 # MUST BE

    host = request.META.get('HTTP_HOST')
    if host:
        try:
            site = Site.objects.get(domain=host)
            settings.SITE_THREAD_INFO.SITE_ID = site.id
        except Site.DoesNotExist:
            pass

#

[email protected] (on November 18, 2008):

of course it's does not work for unit-testing, but it's does work for ftesting.

#

Please login first before commenting.