Question

I run a site that operates the same on many URLs except for the name and the display of objects tied to a given site. Because of this I have extended the Site model to include various other bits of information about a site and created a middleware to put the standard Site object information into the request object. Previously the only info I needed in the request object was the site's name, which I could get from the Site models Django provides. I now need bits of information that reside in my extended Site model (which previously was only used by my other various app models).

This goes from adding one query to each page (request.site = Site.objects.get_current()) to adding two, as I need to get the current site, then get the associated extended Site object from my model.

Is there a way to get this information without using two queries? Or even without using one?

models.py:

from django.contrib.sites.models import Site

class SiteMethods(Site):
    """
    Extended site model
    """
    colloquial_name = models.CharField(max_length=32,)
    ...

middleware.py:

class RequestContextMiddleware(object):
    """
    Puts the Site into each request object
    """
    def process_request(self, request):
        # This runs two queries on every page, instead of just one
        request.site = SiteMethods.objects.get(id=Site.objects.get_current().id)
        return None

In my settings.py file, I have all shared configuration data. My server instances (gunicorn) are configured to load [site]_settings.py, which holds all site-specific settings (to include Django's SITE_ID), and at the bottom:

try:
    from settings import *
except ImportError:
    pass

I am looking for options (if they exist) that do not include referencing the hard-coded SITE_ID in [site]_settings.py.

Update:

As suggested below, subclassed objects should still have access to their parent objects and all the parent object's functionality. For the Site object, strangely, this seems to not be the case.

>>> Site.objects.get_current()
<Site: website.com>
>>> SiteMethods.objects.get_current()
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'Manager' object has no attribute 'get_current'
>>> SiteMethods.objects.select_related('site').get_current() # as suggested below
Traceback (most recent call last):
  File "<console>", line 1, in <module>
AttributeError: 'QuerySet' object has no attribute 'get_current'
>>> dir(SiteMethods)
['DoesNotExist', 'MultipleObjectsReturned', '__class__', '__delattr__', '__dict__',
'__doc__', '__eq__', '__format__', '__getattribute__', '__hash__', '__init__', 
'__metaclass__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', 
'__repr__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', '__unicode__', 
'__weakref__', '_base_manager', '_default_manager', '_deferred', '_get_FIELD_display', 
'_get_next_or_previous_by_FIELD', '_get_next_or_previous_in_order', '_get_pk_val', 
'_get_unique_checks', '_meta', '_perform_date_checks', '_perform_unique_checks', 
'_set_pk_val', 'clean', 'clean_fields', 'date_error_message', 'delete', 'full_clean', 
'objects', 'pk', 'prepare_database_save', 'save', 'save_base', 'serializable_value', 
'site_ptr', 'sitemethods', 'unique_error_message', 'validate_unique',]
Was it helpful?

Solution

Since you subclassed Site you should be able to just do SiteMethods.objects.get_current(), which will net you an instance of SiteMethods. Since Django's implementation of MTI (Multiple Table Inheritance) uses a OneToOneField to the parent class, you should also be able to use select_related for site. So, try the following:

SiteMethods.objects.select_related('site').get_current()
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top