validate that the given value contains no whitespaces to prevent common typos first attempt to look up the site by host with or without port fallback to looking up site after stripping port from the host return the current site based on the siteid in the project s settings if siteid isn t defined return the site with domain matching request gethost the site object is cached the first time it s retrieved from the database clear the site object cache global sitecache sitecache def getbynaturalkeyself domain return self getdomaindomain class sitemodels model domain models charfield domain name maxlength100 validatorssimpledomainnamevalidator uniquetrue name models charfielddisplay name maxlength50 objects sitemanager class meta dbtable djangosite verbosename site verbosenameplural sites ordering domain def strself return self domain def naturalkeyself return self domain def clearsitecachesender kwargs instance kwargsinstance using kwargsusing try del sitecacheinstance pk except keyerror pass try del sitecachesite objects usingusing getpkinstance pk domain except keyerror site doesnotexist pass presave connectclearsitecache sendersite predelete connectclearsitecache sendersite validate that the given value contains no whitespaces to prevent common typos first attempt to look up the site by host with or without port fallback to looking up site after stripping port from the host return the current site based on the site_id in the project s settings if site_id isn t defined return the site with domain matching request get_host the site object is cached the first time it s retrieved from the database clear the site object cache clear the cache if primed each time a site is saved or deleted
import string

from django.core.exceptions import ImproperlyConfigured, ValidationError
from django.db import models
from django.db.models.signals import pre_delete, pre_save
from django.http.request import split_domain_port
from django.utils.translation import gettext_lazy as _

SITE_CACHE = {}


def _simple_domain_name_validator(value):
    
    checks = ((s in value) for s in string.whitespace)
    if any(checks):
        raise ValidationError(
            _("The domain name cannot contain any spaces or tabs."),
            code="invalid",
        )


class SiteManager(models.Manager):
    use_in_migrations = True

    def _get_site_by_id(self, site_id):
        if site_id not in SITE_CACHE:
            site = self.get(pk=site_id)
            SITE_CACHE[site_id] = site
        return SITE_CACHE[site_id]

    def _get_site_by_request(self, request):
        host = request.get_host()
        try:
            
            if host not in SITE_CACHE:
                SITE_CACHE[host] = self.get(domain__iexact=host)
            return SITE_CACHE[host]
        except Site.DoesNotExist:
            
            domain, port = split_domain_port(host)
            if domain not in SITE_CACHE:
                SITE_CACHE[domain] = self.get(domain__iexact=domain)
            return SITE_CACHE[domain]

    def get_current(self, request=None):
        
        from django.conf import settings

        if getattr(settings, "SITE_ID", ""):
            site_id = settings.SITE_ID
            return self._get_site_by_id(site_id)
        elif request:
            return self._get_site_by_request(request)

        raise ImproperlyConfigured(
            'You\'re using the Django "sites framework" without having '
            "set the SITE_ID setting. Create a site in your database and "
            "set the SITE_ID setting or pass a request to "
            "Site.objects.get_current() to fix this error."
        )

    def clear_cache(self):
        
        global SITE_CACHE
        SITE_CACHE = {}

    def get_by_natural_key(self, domain):
        return self.get(domain=domain)


class Site(models.Model):
    domain = models.CharField(
        _("domain name"),
        max_length=100,
        validators=[_simple_domain_name_validator],
        unique=True,
    )
    name = models.CharField(_("display name"), max_length=50)

    objects = SiteManager()

    class Meta:
        db_table = "django_site"
        verbose_name = _("site")
        verbose_name_plural = _("sites")
        ordering = ["domain"]

    def __str__(self):
        return self.domain

    def natural_key(self):
        return (self.domain,)


def clear_site_cache(sender, **kwargs):
    
    instance = kwargs["instance"]
    using = kwargs["using"]
    try:
        del SITE_CACHE[instance.pk]
    except KeyError:
        pass
    try:
        del SITE_CACHE[Site.objects.using(using).get(pk=instance.pk).domain]
    except (KeyError, Site.DoesNotExist):
        pass


pre_save.connect(clear_site_cache, sender=Site)
pre_delete.connect(clear_site_cache, sender=Site)