summaryrefslogtreecommitdiff
path: root/parts/django/docs/ref/contrib/sites.txt
diff options
context:
space:
mode:
authorNishanth Amuluru2011-01-08 11:20:57 +0530
committerNishanth Amuluru2011-01-08 11:20:57 +0530
commit65411d01d448ff0cd4abd14eee14cf60b5f8fc20 (patch)
treeb4c404363c4c63a61d6e2f8bd26c5b057c1fb09d /parts/django/docs/ref/contrib/sites.txt
parent2e35094d43b4cc6974172e1febf76abb50f086ec (diff)
downloadpytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.gz
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.tar.bz2
pytask-65411d01d448ff0cd4abd14eee14cf60b5f8fc20.zip
Added buildout stuff and made changes accordingly
--HG-- rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/djangorecipe-0.20-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/infrae.subversion-1.4.5-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/mercurial-1.7.3-py2.6-linux-x86_64.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/py-1.4.0-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.buildout-1.5.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/dependency_links.txt rename : profile/management/__init__.py => eggs/zc.recipe.egg-1.3.2-py2.6.egg/EGG-INFO/not-zip-safe rename : profile/management/__init__.py => parts/django/Django.egg-info/dependency_links.txt rename : taskapp/models.py => parts/django/django/conf/app_template/models.py rename : taskapp/tests.py => parts/django/django/conf/app_template/tests.py rename : taskapp/views.py => parts/django/django/conf/app_template/views.py rename : taskapp/views.py => parts/django/django/contrib/gis/tests/geo3d/views.py rename : profile/management/__init__.py => parts/django/tests/modeltests/delete/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/files/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/invalid_models/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/m2m_signals/__init__.py rename : profile/management/__init__.py => parts/django/tests/modeltests/model_package/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/management/commands/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/bash_completion/models.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/delete_regress/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/file_storage/__init__.py rename : profile/management/__init__.py => parts/django/tests/regressiontests/max_lengths/__init__.py rename : profile/forms.py => pytask/profile/forms.py rename : profile/management/__init__.py => pytask/profile/management/__init__.py rename : profile/management/commands/seed_db.py => pytask/profile/management/commands/seed_db.py rename : profile/models.py => pytask/profile/models.py rename : profile/templatetags/user_tags.py => pytask/profile/templatetags/user_tags.py rename : taskapp/tests.py => pytask/profile/tests.py rename : profile/urls.py => pytask/profile/urls.py rename : profile/utils.py => pytask/profile/utils.py rename : profile/views.py => pytask/profile/views.py rename : static/css/base.css => pytask/static/css/base.css rename : taskapp/tests.py => pytask/taskapp/tests.py rename : taskapp/views.py => pytask/taskapp/views.py rename : templates/base.html => pytask/templates/base.html rename : templates/profile/browse_notifications.html => pytask/templates/profile/browse_notifications.html rename : templates/profile/edit.html => pytask/templates/profile/edit.html rename : templates/profile/view.html => pytask/templates/profile/view.html rename : templates/profile/view_notification.html => pytask/templates/profile/view_notification.html rename : templates/registration/activate.html => pytask/templates/registration/activate.html rename : templates/registration/activation_email.txt => pytask/templates/registration/activation_email.txt rename : templates/registration/activation_email_subject.txt => pytask/templates/registration/activation_email_subject.txt rename : templates/registration/logged_out.html => pytask/templates/registration/logged_out.html rename : templates/registration/login.html => pytask/templates/registration/login.html rename : templates/registration/logout.html => pytask/templates/registration/logout.html rename : templates/registration/password_change_done.html => pytask/templates/registration/password_change_done.html rename : templates/registration/password_change_form.html => pytask/templates/registration/password_change_form.html rename : templates/registration/password_reset_complete.html => pytask/templates/registration/password_reset_complete.html rename : templates/registration/password_reset_confirm.html => pytask/templates/registration/password_reset_confirm.html rename : templates/registration/password_reset_done.html => pytask/templates/registration/password_reset_done.html rename : templates/registration/password_reset_email.html => pytask/templates/registration/password_reset_email.html rename : templates/registration/password_reset_form.html => pytask/templates/registration/password_reset_form.html rename : templates/registration/registration_complete.html => pytask/templates/registration/registration_complete.html rename : templates/registration/registration_form.html => pytask/templates/registration/registration_form.html rename : utils.py => pytask/utils.py
Diffstat (limited to 'parts/django/docs/ref/contrib/sites.txt')
-rw-r--r--parts/django/docs/ref/contrib/sites.txt415
1 files changed, 415 insertions, 0 deletions
diff --git a/parts/django/docs/ref/contrib/sites.txt b/parts/django/docs/ref/contrib/sites.txt
new file mode 100644
index 0000000..6d795d0
--- /dev/null
+++ b/parts/django/docs/ref/contrib/sites.txt
@@ -0,0 +1,415 @@
+=====================
+The "sites" framework
+=====================
+
+.. module:: django.contrib.sites
+ :synopsis: Lets you operate multiple Web sites from the same database and
+ Django project
+
+Django comes with an optional "sites" framework. It's a hook for associating
+objects and functionality to particular Web sites, and it's a holding place for
+the domain names and "verbose" names of your Django-powered sites.
+
+Use it if your single Django installation powers more than one site and you
+need to differentiate between those sites in some way.
+
+The whole sites framework is based on a simple model:
+
+.. class:: django.contrib.sites.models.Site
+
+This model has :attr:`~django.contrib.sites.models.Site.domain` and
+:attr:`~django.contrib.sites.models.Site.name` fields. The :setting:`SITE_ID`
+setting specifies the database ID of the
+:class:`~django.contrib.sites.models.Site` object associated with that
+particular settings file.
+
+How you use this is up to you, but Django uses it in a couple of ways
+automatically via simple conventions.
+
+Example usage
+=============
+
+Why would you use sites? It's best explained through examples.
+
+Associating content with multiple sites
+---------------------------------------
+
+The Django-powered sites LJWorld.com_ and Lawrence.com_ are operated by the
+same news organization -- the Lawrence Journal-World newspaper in Lawrence,
+Kansas. LJWorld.com focuses on news, while Lawrence.com focuses on local
+entertainment. But sometimes editors want to publish an article on *both*
+sites.
+
+The brain-dead way of solving the problem would be to require site producers to
+publish the same story twice: once for LJWorld.com and again for Lawrence.com.
+But that's inefficient for site producers, and it's redundant to store
+multiple copies of the same story in the database.
+
+The better solution is simple: Both sites use the same article database, and an
+article is associated with one or more sites. In Django model terminology,
+that's represented by a :class:`~django.db.models.ManyToManyField` in the
+``Article`` model::
+
+ from django.db import models
+ from django.contrib.sites.models import Site
+
+ class Article(models.Model):
+ headline = models.CharField(max_length=200)
+ # ...
+ sites = models.ManyToManyField(Site)
+
+This accomplishes several things quite nicely:
+
+ * It lets the site producers edit all content -- on both sites -- in a
+ single interface (the Django admin).
+
+ * It means the same story doesn't have to be published twice in the
+ database; it only has a single record in the database.
+
+ * It lets the site developers use the same Django view code for both sites.
+ The view code that displays a given story just checks to make sure the
+ requested story is on the current site. It looks something like this::
+
+ from django.conf import settings
+
+ def article_detail(request, article_id):
+ try:
+ a = Article.objects.get(id=article_id, sites__id__exact=settings.SITE_ID)
+ except Article.DoesNotExist:
+ raise Http404
+ # ...
+
+.. _ljworld.com: http://www.ljworld.com/
+.. _lawrence.com: http://www.lawrence.com/
+
+Associating content with a single site
+--------------------------------------
+
+Similarly, you can associate a model to the :class:`~django.contrib.sites.models.Site`
+model in a many-to-one relationship, using
+:class:`~django.db.models.fields.related.ForeignKey`.
+
+For example, if an article is only allowed on a single site, you'd use a model
+like this::
+
+ from django.db import models
+ from django.contrib.sites.models import Site
+
+ class Article(models.Model):
+ headline = models.CharField(max_length=200)
+ # ...
+ site = models.ForeignKey(Site)
+
+This has the same benefits as described in the last section.
+
+Hooking into the current site from views
+----------------------------------------
+
+You can use the sites framework in your Django views to do
+particular things based on the site in which the view is being called.
+For example::
+
+ from django.conf import settings
+
+ def my_view(request):
+ if settings.SITE_ID == 3:
+ # Do something.
+ else:
+ # Do something else.
+
+Of course, it's ugly to hard-code the site IDs like that. This sort of
+hard-coding is best for hackish fixes that you need done quickly. A slightly
+cleaner way of accomplishing the same thing is to check the current site's
+domain::
+
+ from django.conf import settings
+ from django.contrib.sites.models import Site
+
+ def my_view(request):
+ current_site = Site.objects.get(id=settings.SITE_ID)
+ if current_site.domain == 'foo.com':
+ # Do something
+ else:
+ # Do something else.
+
+The idiom of retrieving the :class:`~django.contrib.sites.models.Site` object
+for the value of :setting:`settings.SITE_ID <SITE_ID>` is quite common, so
+the :class:`~django.contrib.sites.models.Site` model's manager has a
+``get_current()`` method. This example is equivalent to the previous one::
+
+ from django.contrib.sites.models import Site
+
+ def my_view(request):
+ current_site = Site.objects.get_current()
+ if current_site.domain == 'foo.com':
+ # Do something
+ else:
+ # Do something else.
+
+.. versionchanged:: 1.3
+
+For code which relies on getting the current domain but cannot be certain
+that the sites framework will be installed for any given project, there is a
+utility function :func:`~django.contrib.sites.models.get_current_site` that
+takes a request object as an argument and returns either a Site instance (if
+the sites framework is installed) or a RequestSite instance (if it is not).
+This allows loose coupling with the sites framework and provides a usable
+fallback for cases where it is not installed.
+
+Getting the current domain for display
+--------------------------------------
+
+LJWorld.com and Lawrence.com both have e-mail alert functionality, which lets
+readers sign up to get notifications when news happens. It's pretty basic: A
+reader signs up on a Web form, and he immediately gets an e-mail saying,
+"Thanks for your subscription."
+
+It'd be inefficient and redundant to implement this signup-processing code
+twice, so the sites use the same code behind the scenes. But the "thank you for
+signing up" notice needs to be different for each site. By using
+:class:`~django.contrib.sites.models.Site`
+objects, we can abstract the "thank you" notice to use the values of the
+current site's :attr:`~django.contrib.sites.models.Site.name` and
+:attr:`~django.contrib.sites.models.Site.domain`.
+
+Here's an example of what the form-handling view looks like::
+
+ from django.contrib.sites.models import Site
+ from django.core.mail import send_mail
+
+ def register_for_newsletter(request):
+ # Check form values, etc., and subscribe the user.
+ # ...
+
+ current_site = Site.objects.get_current()
+ send_mail('Thanks for subscribing to %s alerts' % current_site.name,
+ 'Thanks for your subscription. We appreciate it.\n\n-The %s team.' % current_site.name,
+ 'editor@%s' % current_site.domain,
+ [user.email])
+
+ # ...
+
+On Lawrence.com, this e-mail has the subject line "Thanks for subscribing to
+lawrence.com alerts." On LJWorld.com, the e-mail has the subject "Thanks for
+subscribing to LJWorld.com alerts." Same goes for the e-mail's message body.
+
+Note that an even more flexible (but more heavyweight) way of doing this would
+be to use Django's template system. Assuming Lawrence.com and LJWorld.com have
+different template directories (:setting:`TEMPLATE_DIRS`), you could simply farm out
+to the template system like so::
+
+ from django.core.mail import send_mail
+ from django.template import loader, Context
+
+ def register_for_newsletter(request):
+ # Check form values, etc., and subscribe the user.
+ # ...
+
+ subject = loader.get_template('alerts/subject.txt').render(Context({}))
+ message = loader.get_template('alerts/message.txt').render(Context({}))
+ send_mail(subject, message, 'editor@ljworld.com', [user.email])
+
+ # ...
+
+In this case, you'd have to create :file:`subject.txt` and :file:`message.txt` template
+files for both the LJWorld.com and Lawrence.com template directories. That
+gives you more flexibility, but it's also more complex.
+
+It's a good idea to exploit the :class:`~django.contrib.sites.models.Site`
+objects as much as possible, to remove unneeded complexity and redundancy.
+
+Getting the current domain for full URLs
+----------------------------------------
+
+Django's ``get_absolute_url()`` convention is nice for getting your objects'
+URL without the domain name, but in some cases you might want to display the
+full URL -- with ``http://`` and the domain and everything -- for an object.
+To do this, you can use the sites framework. A simple example::
+
+ >>> from django.contrib.sites.models import Site
+ >>> obj = MyModel.objects.get(id=3)
+ >>> obj.get_absolute_url()
+ '/mymodel/objects/3/'
+ >>> Site.objects.get_current().domain
+ 'example.com'
+ >>> 'http://%s%s' % (Site.objects.get_current().domain, obj.get_absolute_url())
+ 'http://example.com/mymodel/objects/3/'
+
+Caching the current ``Site`` object
+===================================
+
+.. versionadded:: 1.0
+
+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.
+
+If for any reason you want to force a database query, you can tell Django to
+clear the cache using ``Site.objects.clear_cache()``::
+
+ # First call; current site fetched from database.
+ current_site = Site.objects.get_current()
+ # ...
+
+ # Second call; current site fetched from cache.
+ current_site = Site.objects.get_current()
+ # ...
+
+ # Force a database query for the third call.
+ Site.objects.clear_cache()
+ current_site = Site.objects.get_current()
+
+The ``CurrentSiteManager``
+==========================
+
+.. class:: django.contrib.sites.managers.CurrentSiteManager
+
+If :class:`~django.contrib.sites.models.Site` plays a key role in your
+application, consider using the helpful
+:class:`~django.contrib.sites.managers.CurrentSiteManager` in your
+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`.
+
+Use :class:`~django.contrib.sites.managers.CurrentSiteManager` by adding it to
+your model explicitly. For example::
+
+ from django.db import models
+ from django.contrib.sites.models import Site
+ from django.contrib.sites.managers import CurrentSiteManager
+
+ class Photo(models.Model):
+ photo = models.FileField(upload_to='/home/photos')
+ photographer_name = models.CharField(max_length=100)
+ pub_date = models.DateField()
+ site = models.ForeignKey(Site)
+ objects = models.Manager()
+ on_site = CurrentSiteManager()
+
+With this model, ``Photo.objects.all()`` will return all ``Photo`` objects in
+the database, but ``Photo.on_site.all()`` will return only the ``Photo`` objects
+associated with the current site, according to the :setting:`SITE_ID` setting.
+
+Put another way, these two statements are equivalent::
+
+ Photo.objects.filter(site=settings.SITE_ID)
+ Photo.on_site.all()
+
+How did :class:`~django.contrib.sites.managers.CurrentSiteManager`
+know which field of ``Photo`` was the
+:class:`~django.contrib.sites.models.Site`? By default,
+:class:`~django.contrib.sites.managers.CurrentSiteManager` looks for a
+either a :class:`~django.db.models.fields.related.ForeignKey` called
+``site`` or a
+:class:`~django.db.models.fields.related.ManyToManyField` called
+``sites`` to filter on. If you use a field named something other than
+``site`` or ``sites`` to identify which
+:class:`~django.contrib.sites.models.Site` objects your object is
+related to, then you need to explicitly pass the custom field name as
+a parameter to
+:class:`~django.contrib.sites.managers.CurrentSiteManager` on your
+model. The following model, which has a field called ``publish_on``,
+demonstrates this::
+
+ from django.db import models
+ from django.contrib.sites.models import Site
+ from django.contrib.sites.managers import CurrentSiteManager
+
+ class Photo(models.Model):
+ photo = models.FileField(upload_to='/home/photos')
+ photographer_name = models.CharField(max_length=100)
+ pub_date = models.DateField()
+ publish_on = models.ForeignKey(Site)
+ objects = models.Manager()
+ on_site = CurrentSiteManager('publish_on')
+
+If you attempt to use :class:`~django.contrib.sites.managers.CurrentSiteManager`
+and pass a field name that doesn't exist, Django will raise a :exc:`ValueError`.
+
+Finally, note that you'll probably want to keep a normal
+(non-site-specific) ``Manager`` on your model, even if you use
+:class:`~django.contrib.sites.managers.CurrentSiteManager`. As
+explained in the :doc:`manager documentation </topics/db/managers>`, if
+you define a manager manually, then Django won't create the automatic
+``objects = models.Manager()`` manager for you. Also note that certain
+parts of Django -- namely, the Django admin site and generic views --
+use whichever manager is defined *first* in the model, so if you want
+your admin site to have access to all objects (not just site-specific
+ones), put ``objects = models.Manager()`` in your model, before you
+define :class:`~django.contrib.sites.managers.CurrentSiteManager`.
+
+How Django uses the sites framework
+===================================
+
+Although it's not required that you use the sites framework, it's strongly
+encouraged, because Django takes advantage of it in a few places. Even if your
+Django installation is powering only a single site, you should take the two
+seconds to create the site object with your ``domain`` and ``name``, and point
+to its ID in your :setting:`SITE_ID` setting.
+
+Here's how Django uses the sites framework:
+
+* In the :mod:`redirects framework <django.contrib.redirects>`, each
+ redirect object is associated with a particular site. When Django searches
+ for a redirect, it takes into account the current :setting:`SITE_ID`.
+
+* In the comments framework, each comment is associated with a particular
+ site. When a comment is posted, its
+ :class:`~django.contrib.sites.models.Site` is set to the current
+ :setting:`SITE_ID`, and when comments are listed via the appropriate
+ template tag, only the comments for the current site are displayed.
+
+* In the :mod:`flatpages framework <django.contrib.flatpages>`, each
+ flatpage is associated with a particular site. When a flatpage is created,
+ you specify its :class:`~django.contrib.sites.models.Site`, and the
+ :class:`~django.contrib.flatpages.middleware.FlatpageFallbackMiddleware`
+ checks the current :setting:`SITE_ID` in retrieving flatpages to display.
+
+* In the :mod:`syndication framework <django.contrib.syndication>`, the
+ templates for ``title`` and ``description`` automatically have access to a
+ variable ``{{ site }}``, which is the
+ :class:`~django.contrib.sites.models.Site` object representing the current
+ site. Also, the hook for providing item URLs will use the ``domain`` from
+ the current :class:`~django.contrib.sites.models.Site` object if you don't
+ specify a fully-qualified domain.
+
+* In the :mod:`authentication framework <django.contrib.auth>`, the
+ :func:`django.contrib.auth.views.login` view passes the current
+ :class:`~django.contrib.sites.models.Site` name to the template as
+ ``{{ site_name }}``.
+
+* The shortcut view (:func:`django.views.defaults.shortcut`) uses the domain
+ of the current :class:`~django.contrib.sites.models.Site` object when
+ calculating an object's URL.
+
+* In the admin framework, the "view on site" link uses the current
+ :class:`~django.contrib.sites.models.Site` to work out the domain for the
+ site that it will redirect to.
+
+
+``RequestSite`` objects
+=======================
+
+.. _requestsite-objects:
+
+.. versionadded:: 1.0
+
+Some :doc:`django.contrib </ref/contrib/index>` applications take advantage of
+the sites framework but are architected in a way that doesn't *require* the
+sites framework to be installed in your database. (Some people don't want to, or
+just aren't *able* to install the extra database table that the sites framework
+requires.) For those cases, the framework provides a
+:class:`~django.contrib.sites.models.RequestSite` class, which can be used as a
+fallback when the database-backed sites framework is not available.
+
+A :class:`~django.contrib.sites.models.RequestSite` object has a similar
+interface to a normal :class:`~django.contrib.sites.models.Site` object, except
+its :meth:`~django.contrib.sites.models.RequestSite.__init__()` method takes an
+:class:`~django.http.HttpRequest` object. It's able to deduce the
+:attr:`~django.contrib.sites.models.RequestSite.domain` and
+:attr:`~django.contrib.sites.models.RequestSite.name` by looking at the
+request's domain. It has :meth:`~django.contrib.sites.models.RequestSite.save()`
+and :meth:`~django.contrib.sites.models.RequestSite.delete()` methods to match
+the interface of :class:`~django.contrib.sites.models.Site`, but the methods
+raise :exc:`NotImplementedError`.