You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

models.py 3.6KB

5 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. import string
  2. from django.core.exceptions import ImproperlyConfigured, ValidationError
  3. from django.db import models
  4. from django.db.models.signals import pre_delete, pre_save
  5. from django.http.request import split_domain_port
  6. from django.utils.translation import gettext_lazy as _
  7. SITE_CACHE = {}
  8. def _simple_domain_name_validator(value):
  9. """
  10. Validate that the given value contains no whitespaces to prevent common
  11. typos.
  12. """
  13. checks = ((s in value) for s in string.whitespace)
  14. if any(checks):
  15. raise ValidationError(
  16. _("The domain name cannot contain any spaces or tabs."),
  17. code='invalid',
  18. )
  19. class SiteManager(models.Manager):
  20. use_in_migrations = True
  21. def _get_site_by_id(self, site_id):
  22. if site_id not in SITE_CACHE:
  23. site = self.get(pk=site_id)
  24. SITE_CACHE[site_id] = site
  25. return SITE_CACHE[site_id]
  26. def _get_site_by_request(self, request):
  27. host = request.get_host()
  28. try:
  29. # First attempt to look up the site by host with or without port.
  30. if host not in SITE_CACHE:
  31. SITE_CACHE[host] = self.get(domain__iexact=host)
  32. return SITE_CACHE[host]
  33. except Site.DoesNotExist:
  34. # Fallback to looking up site after stripping port from the host.
  35. domain, port = split_domain_port(host)
  36. if domain not in SITE_CACHE:
  37. SITE_CACHE[domain] = self.get(domain__iexact=domain)
  38. return SITE_CACHE[domain]
  39. def get_current(self, request=None):
  40. """
  41. Return the current Site based on the SITE_ID in the project's settings.
  42. If SITE_ID isn't defined, return the site with domain matching
  43. request.get_host(). The ``Site`` object is cached the first time it's
  44. retrieved from the database.
  45. """
  46. from django.conf import settings
  47. if getattr(settings, 'SITE_ID', ''):
  48. site_id = settings.SITE_ID
  49. return self._get_site_by_id(site_id)
  50. elif request:
  51. return self._get_site_by_request(request)
  52. raise ImproperlyConfigured(
  53. "You're using the Django \"sites framework\" without having "
  54. "set the SITE_ID setting. Create a site in your database and "
  55. "set the SITE_ID setting or pass a request to "
  56. "Site.objects.get_current() to fix this error."
  57. )
  58. def clear_cache(self):
  59. """Clear the ``Site`` object cache."""
  60. global SITE_CACHE
  61. SITE_CACHE = {}
  62. def get_by_natural_key(self, domain):
  63. return self.get(domain=domain)
  64. class Site(models.Model):
  65. domain = models.CharField(
  66. _('domain name'),
  67. max_length=100,
  68. validators=[_simple_domain_name_validator],
  69. unique=True,
  70. )
  71. name = models.CharField(_('display name'), max_length=50)
  72. objects = SiteManager()
  73. class Meta:
  74. db_table = 'django_site'
  75. verbose_name = _('site')
  76. verbose_name_plural = _('sites')
  77. ordering = ('domain',)
  78. def __str__(self):
  79. return self.domain
  80. def natural_key(self):
  81. return (self.domain,)
  82. def clear_site_cache(sender, **kwargs):
  83. """
  84. Clear the cache (if primed) each time a site is saved or deleted.
  85. """
  86. instance = kwargs['instance']
  87. using = kwargs['using']
  88. try:
  89. del SITE_CACHE[instance.pk]
  90. except KeyError:
  91. pass
  92. try:
  93. del SITE_CACHE[Site.objects.using(using).get(pk=instance.pk).domain]
  94. except (KeyError, Site.DoesNotExist):
  95. pass
  96. pre_save.connect(clear_site_cache, sender=Site)
  97. pre_delete.connect(clear_site_cache, sender=Site)