Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Ticket #18620: Prefer current Site when checking M2M in "shortcut"/"view_on_site" redirect #203

Closed
wants to merge 7 commits into from

6 participants

Mike Tigas Tim Graham Stefan Kjartansson Adrian Holovaty Alex Gaynor Claude Paroz
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Jul 10, 2012
  1. Stefan Kjartansson
Commits on Jul 11, 2012
  1. Adrian Holovaty

    Merge pull request #199 from mitnk/master

    adrianholovaty authored
    Fixed a typo in the timezones document.
  2. Adrian Holovaty

    Merge pull request #197 from StefanKjartansson/master

    adrianholovaty authored
    Fixed typo in docs
Commits on Jul 12, 2012
  1. Alex Gaynor

    Remove some code that has been dead since newforms-admin was merged, …

    alex authored Alex Gaynor committed
    …many moons ago.
  2. Claude Paroz
  3. Mike Tigas
  4. Mike Tigas
This page is out of date. Refresh to see the latest.
42 django/contrib/contenttypes/tests.py
View
@@ -8,6 +8,7 @@
from django.contrib.sites.models import Site
from django.http import HttpRequest, Http404
from django.test import TestCase
+from django.utils import unittest
from django.utils.encoding import smart_str
@@ -45,6 +46,13 @@ class FooWithBrokenAbsoluteUrl(FooWithoutUrl):
def get_absolute_url(self):
return "/users/%s/" % self.unknown_field
+if Site._meta.installed:
+ class FooWithSiteM2MAndUrl(FooWithUrl):
+ """
+ Fake model containing a `Site` many-to-many relationship.
+ """
+ sites = models.ManyToManyField(Site)
+
class ContentTypesTests(TestCase):
def setUp(self):
@@ -260,6 +268,40 @@ def test_shortcut_view_with_broken_get_absolute_url(self):
self.assertRaises(AttributeError, shortcut, request, user_ct.id, obj.id)
+ @unittest.skipIf(not Site._meta.installed,
+ "this tests against relationship behavior with the Sites framework")
+ def test_shortcut_view_m2m(self):
+ """
+ Check that the shortcut view (used for the admin "view on site"
+ functionality) returns a complete URL regardless of whether the sites
+ framework is installed
+ """
+ # Tests ticket #18620; prefer current_site rather than allowing
+ # M2M to select first domain via ABC order.
+ current_site = Site.objects.get_current() # example.com
+ other_site = Site(domain="a.example.com", name="a.example.com")
+ other_site.save()
+
+ # Build an object that belongs to both sites.
+ obj = FooWithSiteM2MAndUrl(name="john")
+ obj.save() # need saved object to set M2M relationship
+ obj.sites = [other_site, current_site]
+
+ # Check that shortcut view returns absolute URI for `current_site`
+ # and not `other_site`.
+ request = HttpRequest()
+ request.META = {
+ "SERVER_NAME": "Example.com",
+ "SERVER_PORT": "80",
+ }
+ user_ct = ContentType.objects.get_for_model(FooWithSiteM2MAndUrl)
+ response = shortcut(request, user_ct.id, obj.id)
+ self.assertEqual("http://%s/users/john/" % current_site.domain,
+ response._headers.get("location")[1])
+
+ obj.delete()
+ other_site.delete()
+
def test_missing_model(self):
"""
Ensures that displaying content types in admin (or anywhere) doesn't
33 django/contrib/contenttypes/views.py
View
@@ -38,6 +38,15 @@ def shortcut(request, content_type_id, object_id):
# Otherwise, we need to introspect the object's relationships for a
# relation to the Site object
object_domain = None
+ current_domain = None
+
+ # Get current site (if possible): this decides the preferred domain
+ # if this object has an M2M site field and provides a fallback if this
+ # object does not have a site FK or M2M field.
+ try:
+ current_domain = get_current_site(request).domain
+ except Site.DoesNotExist:
+ pass
if Site._meta.installed:
opts = obj._meta
@@ -45,10 +54,21 @@ def shortcut(request, content_type_id, object_id):
# First, look for an many-to-many relationship to Site.
for field in opts.many_to_many:
if field.rel.to is Site:
+ site_qs = getattr(obj, field.name).all()
+ try:
+ # If one of the sites this object belongs to is the current
+ # site, use it.
+ object_domain = site_qs.get(domain=current_domain).domain
+ except Site.DoesNotExist:
+ pass
+ if object_domain is not None:
+ break
try:
- # Caveat: In the case of multiple related Sites, this just
- # selects the *first* one, which is arbitrary.
- object_domain = getattr(obj, field.name).all()[0].domain
+ # Current site was not in the M2M relationship for this
+ # object. Caveat: This just selects the *first* one, which
+ # is arbitrary. (Generally based on Site model ordering,
+ # which is alphabetical by domain.)
+ object_domain = site_qs[0].domain
except IndexError:
pass
if object_domain is not None:
@@ -65,12 +85,9 @@ def shortcut(request, content_type_id, object_id):
if object_domain is not None:
break
- # Fall back to the current site (if possible).
+ # Fall back to the current site (if possible) or None (which is fine).
if object_domain is None:
- try:
- object_domain = get_current_site(request).domain
- except Site.DoesNotExist:
- pass
+ object_domain = current_domain
# If all that malarkey found an object domain, use it. Otherwise, fall back
# to whatever get_absolute_url() returned.
2  django/db/models/__init__.py
View
@@ -15,8 +15,6 @@
from django.db.models import signals
from django.utils.decorators import wraps
-# Admin stages.
-ADD, CHANGE, BOTH = 1, 2, 3
def permalink(func):
"""
50 docs/ref/contrib/gis/install.txt
View
@@ -1034,61 +1034,11 @@ Optional packages to consider:
do not plan on doing any database transformation of geometries to the
Google projection (900913).
-.. _heron:
-
-8.04 and lower
-~~~~~~~~~~~~~~
-
-The 8.04 (and lower) versions of Ubuntu use GEOS v2.2.3 in their binary packages,
-which is incompatible with GeoDjango. Thus, do *not* use the binary packages
-for GEOS or PostGIS and build some prerequisites from source, per the instructions
-in this document; however, it is okay to use the PostgreSQL binary packages.
-
-For more details, please see the Debian instructions for :ref:`etch` below.
-
.. _debian:
Debian
------
-.. _etch:
-
-4.0 (Etch)
-^^^^^^^^^^
-
-The situation here is the same as that of Ubuntu :ref:`heron` -- in other words,
-some packages must be built from source to work properly with GeoDjango.
-
-Binary packages
-~~~~~~~~~~~~~~~
-The following command will install acceptable binary packages, as well as
-the development tools necessary to build the rest of the requirements:
-
-.. code-block:: bash
-
- $ sudo apt-get install binutils bzip2 gcc g++ flex make postgresql-8.1 \
- postgresql-server-dev-8.1 python-ctypes python-psycopg2 python-setuptools
-
-Required package information:
-
-* ``binutils``: for ctypes to find libraries
-* ``bzip2``: for decompressing the source packages
-* ``gcc``, ``g++``, ``make``: GNU developer tools used to compile the libraries
-* ``flex``: required to build PostGIS
-* ``postgresql-8.1``
-* ``postgresql-server-dev-8.1``: for ``pg_config``
-* ``python-psycopg2``
-
-Optional packages:
-
-* ``libgeoip``: for :ref:`GeoIP <ref-geoip>` support
-
-Source packages
-~~~~~~~~~~~~~~~
-You will still have to install :ref:`geosbuild`, :ref:`proj4`,
-:ref:`postgis`, and :ref:`gdalbuild` from source. Please follow the
-directions carefully.
-
.. _lenny:
5.0 (Lenny)
2  docs/topics/python3.txt
View
@@ -181,7 +181,7 @@ xrange range xrange
=============================== ====================================== ======================
-Ouptut encoding now Unicode
+Output encoding now Unicode
===========================
If you want to catch stdout/stderr output, the output content is UTF-8 encoded
Something went wrong with that request. Please try again.