diff --git a/django/contrib/sites/models.py b/django/contrib/sites/models.py
index 8590740..a7aa462 100644
--- a/django/contrib/sites/models.py
+++ b/django/contrib/sites/models.py
@@ -1,3 +1,4 @@
+from django.core.exceptions import ImproperlyConfigured
 from django.db import models
 from django.utils.translation import ugettext_lazy as _
 from django.utils.encoding import python_2_unicode_compatible
@@ -8,6 +9,21 @@ SITE_CACHE = {}
 
 class SiteManager(models.Manager):
 
+    def _get_site_by_id(self, sid):
+        if not sid in SITE_CACHE:
+            site = self.get(pk=sid)
+            SITE_CACHE[sid] = site
+        return SITE_CACHE[sid]
+
+    def _get_site_by_request(self, request):
+        host = request.get_host().lower()
+        if ':' in host:
+            host = host.split(':', 1)[0]
+        if not host in SITE_CACHE:
+            site = self.get(domain__iexact=host)
+            SITE_CACHE[host] = site
+        return SITE_CACHE[host]
+
     def get_current(self):
         """
         Returns the current ``Site`` based on the SITE_ID in the
@@ -18,14 +34,8 @@ class SiteManager(models.Manager):
         try:
             sid = settings.SITE_ID
         except AttributeError:
-            from django.core.exceptions import ImproperlyConfigured
             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 to fix this error.")
-        try:
-            current_site = SITE_CACHE[sid]
-        except KeyError:
-            current_site = self.get(pk=sid)
-            SITE_CACHE[sid] = current_site
-        return current_site
+        return self._get_site_by_id(sid)
 
     def clear_cache(self):
         """Clears the ``Site`` object cache."""
@@ -92,7 +102,11 @@ def get_current_site(request):
     ``Site`` object or a ``RequestSite`` object based on the request.
     """
     if Site._meta.installed:
-        current_site = Site.objects.get_current()
+        from django.conf import settings
+        if hasattr(settings, 'SITE_ID'):
+            current_site = Site.objects.get_current()
+        else:
+            current_site = Site.objects._get_site_by_request(request)
     else:
         current_site = RequestSite(request)
     return current_site
diff --git a/django/contrib/sites/tests.py b/django/contrib/sites/tests.py
index 1bb2495..28d8f26 100644
--- a/django/contrib/sites/tests.py
+++ b/django/contrib/sites/tests.py
@@ -5,6 +5,7 @@ from django.contrib.sites.models import Site, RequestSite, get_current_site
 from django.core.exceptions import ObjectDoesNotExist
 from django.http import HttpRequest
 from django.test import TestCase
+from django.test.utils import override_settings
 
 
 class SitesFrameworkTests(TestCase):
@@ -62,3 +63,14 @@ class SitesFrameworkTests(TestCase):
         site = get_current_site(request)
         self.assertTrue(isinstance(site, RequestSite))
         self.assertEqual(site.name, "example.com")
+
+    @override_settings(SITE_ID='')
+    def test_get_current_site_no_site_id(self):
+        request = HttpRequest()
+        request.META = {
+            "SERVER_NAME": "example.com",
+            "SERVER_PORT": "80",
+        }
+        del settings.SITE_ID
+        site = get_current_site(request)
+        self.assertEqual(site.name, "example.com")
diff --git a/docs/ref/contrib/sites.txt b/docs/ref/contrib/sites.txt
index 790e003..05fe9c0 100644
--- a/docs/ref/contrib/sites.txt
+++ b/docs/ref/contrib/sites.txt
@@ -20,9 +20,6 @@ The whole sites framework is based on a simple model:
 .. class:: Site
 
     A model for storing the ``domain`` and ``name`` attributes of a Web site.
-    The :setting:`SITE_ID` setting specifies the database ID of the
-    :class:`~django.contrib.sites.models.Site` object associated with that
-    particular settings file.
 
     .. attribute:: domain
 
@@ -32,6 +29,13 @@ The whole sites framework is based on a simple model:
 
         A human-readable "verbose" name for the Web site.
 
+The :setting:`SITE_ID` setting specifies the database ID of the
+:class:`~django.contrib.sites.models.Site` object associated with that
+particular settings file. It is possible to omit it, but then you cannot
+call the :meth:`~django.contrib.sites.models.Site.get_current` method any
+more. The :func:`get_current_site` function will then always try to get the
+current site by comparing the :attr:`~Site.domain` with the host name from the
+:meth:`~django.http.HttpRequest.get_host` method.
 
 How you use this is up to you, but Django uses it in a couple of ways
 automatically via simple conventions.
@@ -244,9 +248,10 @@ Caching the current ``Site`` object
 ===================================
 
 As the current site is stored in the database, each call to
-``Site.objects.get_current()`` could result in a database query. But Django is a
-little cleverer than that: on the first request, the current site is cached, and
-any subsequent call returns the cached data instead of hitting the database.
+``Site.objects.get_current()`` or to ``sites.get_current_site()`` could result
+in a database query. But Django is a little cleverer than that: on the first
+request, the current site is cached, and any subsequent call returns the cached
+data instead of hitting the database.
 
 If for any reason you want to force a database query, you can tell Django to
 clear the cache using ``Site.objects.clear_cache()``::
@@ -277,6 +282,11 @@ model(s). It's a model :doc:`manager </topics/db/managers>` that
 automatically filters its queries to include only objects associated
 with the current :class:`~django.contrib.sites.models.Site`.
 
+.. admonition:: Mandatory SITE_ID
+
+    The ``CurrentSiteManager`` is only usable when the :setting:`SITE_ID`
+    setting is defined in your settings.
+
 Use :class:`~django.contrib.sites.managers.CurrentSiteManager` by adding it to
 your model explicitly. For example::
 
