Permalink
Browse files

[multi-db] Merge trunk to [3661]

  • Loading branch information...
1 parent 5a58772 commit b17f250907351923f39f8a50b87a35b26d2ca307 @jpellerin jpellerin committed Sep 4, 2006
Showing with 2,425 additions and 4,498 deletions.
  1. +2 −0 AUTHORS
  2. +4 −1 django/bin/compile-messages.py
  3. +15 −1 django/conf/global_settings.py
  4. +7 −3 django/contrib/admin/views/doc.py
  5. +1 −1 django/contrib/auth/models.py
  6. +90 −0 django/contrib/sitemaps/__init__.py
  7. +11 −0 django/contrib/sitemaps/templates/sitemap.xml
  8. +8 −0 django/contrib/sitemaps/templates/sitemap_index.xml
  9. +30 −0 django/contrib/sitemaps/views.py
  10. +6 −3 django/core/management.py
  11. +29 −25 django/core/serializers/base.py
  12. +1 −1 django/core/serializers/json.py
  13. +1 −4 django/db/backends/postgresql_psycopg2/base.py
  14. +1 −1 django/db/backends/util.py
  15. +2 −10 django/template/__init__.py
  16. +1 −1 django/template/defaulttags.py
  17. +3 −5 django/template/loader.py
  18. +1 −1 django/template/loader_tags.py
  19. +2 −1 django/test/simple.py
  20. +43 −20 django/test/utils.py
  21. +17 −11 django/utils/datastructures.py
  22. +3 −3 django/views/debug.py
  23. +1 −1 django/views/static.py
  24. +9 −0 docs/add_ons.txt
  25. +13 −0 docs/contributing.txt
  26. +29 −0 docs/django-admin.txt
  27. +3 −3 docs/faq.txt
  28. +24 −0 docs/settings.txt
  29. +320 −0 docs/sitemaps.txt
  30. +11 −0 docs/sites.txt
  31. +14 −5 docs/templates_python.txt
  32. +303 −0 docs/testing.txt
  33. +3 −0 setup.cfg
  34. +0 −2,665 tests/doctest.py
  35. +5 −6 tests/modeltests/basic/models.py
  36. +2 −2 tests/modeltests/choices/models.py
  37. +2 −2 tests/modeltests/custom_columns/models.py
  38. +2 −2 tests/modeltests/custom_managers/models.py
  39. +2 −2 tests/modeltests/custom_methods/models.py
  40. +2 −2 tests/modeltests/custom_pk/models.py
  41. +2 −2 tests/modeltests/empty/models.py
  42. +2 −2 tests/modeltests/field_defaults/models.py
  43. +2 −2 tests/modeltests/generic_relations/models.py
  44. +6 −6 tests/modeltests/get_latest/models.py
  45. +2 −2 tests/modeltests/get_or_create/models.py
  46. +1 −1 tests/modeltests/invalid_models/models.py
  47. +2 −2 tests/modeltests/lookup/models.py
  48. +2 −2 tests/modeltests/m2m_and_m2o/models.py
  49. +2 −2 tests/modeltests/m2m_intermediary/models.py
  50. +2 −2 tests/modeltests/m2m_multiple/models.py
  51. +2 −2 tests/modeltests/m2m_recursive/models.py
  52. +2 −2 tests/modeltests/m2o_recursive/models.py
  53. +2 −2 tests/modeltests/m2o_recursive2/models.py
  54. +2 −2 tests/modeltests/manipulators/models.py
  55. +2 −2 tests/modeltests/many_to_many/models.py
  56. +2 −2 tests/modeltests/many_to_one/models.py
  57. +2 −2 tests/modeltests/many_to_one_null/models.py
  58. +2 −2 tests/modeltests/model_inheritance/models.py
  59. +18 −23 tests/modeltests/multiple_databases/models.py
  60. +2 −2 tests/modeltests/mutually_referential/models.py
  61. +2 −2 tests/modeltests/one_to_one/models.py
  62. +2 −2 tests/modeltests/or_lookups/models.py
  63. +2 −2 tests/modeltests/ordering/models.py
  64. +2 −2 tests/modeltests/pagination/models.py
  65. +2 −2 tests/modeltests/properties/models.py
  66. +2 −2 tests/modeltests/reserved_names/models.py
  67. +2 −2 tests/modeltests/reverse_lookup/models.py
  68. +2 −2 tests/modeltests/save_delete_hooks/models.py
  69. +2 −2 tests/modeltests/serializers/models.py
  70. +2 −2 tests/modeltests/str/models.py
  71. +3 −3 tests/modeltests/transactions/models.py
  72. +2 −2 tests/modeltests/validation/models.py
  73. +0 −60 tests/othertests/cache.py
  74. +0 −23 tests/othertests/manager_db.py
  75. +0 −70 tests/othertests/markup.py
  76. +0 −140 tests/othertests/request_isolation.py
  77. +0 −634 tests/othertests/templates.py
  78. +0 −300 tests/othertests/thread_isolation.py
  79. 0 tests/{othertests → regressiontests/ansi_sql}/__init__.py
  80. +27 −36 tests/{othertests/ansi_sql.py → regressiontests/ansi_sql/models.py}
  81. 0 tests/{othertests → regressiontests/ansi_sql}/sql/car.sql
  82. 0 tests/regressiontests/cache/__init__.py
  83. 0 tests/regressiontests/cache/models.py
  84. +71 −0 tests/regressiontests/cache/tests.py
  85. 0 tests/regressiontests/dateformat/__init__.py
  86. 0 tests/regressiontests/dateformat/models.py
  87. 0 tests/{othertests/dateformat.py → regressiontests/dateformat/tests.py}
  88. 0 tests/regressiontests/db_typecasts/__init__.py
  89. 0 tests/regressiontests/db_typecasts/models.py
  90. +10 −5 tests/{othertests/db_typecasts.py → regressiontests/db_typecasts/tests.py}
  91. 0 tests/regressiontests/defaultfilters/__init__.py
  92. 0 tests/regressiontests/defaultfilters/models.py
  93. 0 tests/{othertests/defaultfilters.py → regressiontests/defaultfilters/tests.py}
  94. 0 tests/regressiontests/httpwrappers/__init__.py
  95. 0 tests/regressiontests/httpwrappers/models.py
  96. 0 tests/{othertests/httpwrappers.py → regressiontests/httpwrappers/tests.py}
  97. +1 −1 tests/regressiontests/initial_sql_regress/models.py
  98. 0 tests/regressiontests/manager_db/__init__.py
  99. +5 −0 tests/regressiontests/manager_db/models.py
  100. +17 −0 tests/regressiontests/manager_db/tests.py
  101. 0 tests/regressiontests/manager_schema_manipulation/__init__.py
  102. 0 tests/regressiontests/manager_schema_manipulation/models.py
  103. +5 −5 ...othertests/manager_schema_manipulation.py → regressiontests/manager_schema_manipulation/tests.py}
  104. +1 −1 tests/regressiontests/many_to_one_regress/models.py
  105. 0 tests/regressiontests/markup/__init__.py
  106. 0 tests/regressiontests/markup/models.py
  107. +69 −0 tests/regressiontests/markup/tests.py
  108. +2 −2 tests/regressiontests/one_to_one_regress/models.py
  109. 0 tests/regressiontests/request_isolation/__init__.py
  110. +13 −0 tests/regressiontests/request_isolation/models.py
  111. +100 −0 tests/regressiontests/request_isolation/tests.py
  112. +2 −2 tests/regressiontests/string_lookup/models.py
  113. 0 tests/regressiontests/templates/__init__.py
  114. 0 tests/regressiontests/templates/models.py
  115. +621 −0 tests/regressiontests/templates/tests.py
  116. 0 tests/regressiontests/thread_isolation/__init__.py
  117. +19 −0 tests/regressiontests/thread_isolation/models.py
  118. +251 −0 tests/regressiontests/thread_isolation/tests.py
  119. 0 tests/regressiontests/urlpatterns_reverse/__init__.py
  120. 0 tests/regressiontests/urlpatterns_reverse/models.py
  121. +10 −18 tests/{othertests/urlpatterns_reverse.py → regressiontests/urlpatterns_reverse/tests.py}
  122. +94 −330 tests/runtests.py
View
@@ -126,6 +126,7 @@ answer newbie questions, and generally made Django that much better:
Oliver Rutherfurd <http://rutherfurd.net/>
Ivan Sagalaev (Maniac) <http://www.softwaremaniacs.org/>
David Schein
+ Pete Shinners <pete@shinners.org>
sopel
Thomas Steinacher <tom@eggdrop.ch>
Radek Švarz <http://www.svarz.cz/translate/>
@@ -138,6 +139,7 @@ answer newbie questions, and generally made Django that much better:
Amit Upadhyay
Geert Vanderkelen
Milton Waddams
+ Dan Watson <http://theidioteque.net/>
Rachel Willmer <http://www.willmer.com/kb/>
wojtek
ye7cakf02@sneakemail.com
@@ -26,7 +26,10 @@ def compile_messages():
# See http://cyberelk.net/tim/articles/cmdline/ar01s02.html
os.environ['djangocompilemo'] = pf + '.mo'
os.environ['djangocompilepo'] = pf + '.po'
- cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
+ if sys.platform == 'win32': # Different shell-variable syntax
+ cmd = 'msgfmt -o "%djangocompilemo%" "%djangocompilepo%"'
+ else:
+ cmd = 'msgfmt -o "$djangocompilemo" "$djangocompilepo"'
os.system(cmd)
if __name__ == "__main__":
@@ -304,4 +304,18 @@
# TESTING #
###########
-TEST_RUNNER='django.test.simple.run_tests'
+# The name of the method to use to invoke the test suite
+TEST_RUNNER = 'django.test.simple.run_tests'
+
+# The name of the database to use for testing purposes.
+# If None, a name of 'test_' + DATABASE_NAME will be assumed
+TEST_DATABASE_NAME = None
+
+# Tuple of other test databases to create. Names in this tuple
+# are suffixes that will be appended to TEST_DATABASE_NAME
+TEST_DATABASES = []
+
+# Models to assign to each test database. This must be a list of
+# dicts, with each dict key being a name from TEST_DATABASES and value
+# a list of models or app_labels that will use that database.
+TEST_DATABASE_MODELS = []
@@ -328,13 +328,17 @@ def extract_views_from_urlpatterns(urlpatterns, base=''):
"""
views = []
for p in urlpatterns:
- if hasattr(p, 'get_callback'):
+ if hasattr(p, '_get_callback'):
try:
- views.append((p.get_callback(), base + p.regex.pattern))
+ views.append((p._get_callback(), base + p.regex.pattern))
except ViewDoesNotExist:
continue
elif hasattr(p, '_get_url_patterns'):
- views.extend(extract_views_from_urlpatterns(p.url_patterns, base + p.regex.pattern))
+ try:
+ patterns = p.url_patterns
+ except ImportError:
+ continue
+ views.extend(extract_views_from_urlpatterns(patterns, base + p.regex.pattern))
else:
raise TypeError, _("%s does not appear to be a urlpattern object") % p
return views
@@ -33,7 +33,7 @@ class Permission(models.Model):
Permissions are set globally per type of object, not per specific object instance. It is possible to say "Mary may change news stories," but it's not currently possible to say "Mary may change news stories, but only the ones she created herself" or "Mary may only change news stories that have a certain status or publication date."
- Three basic permissions -- add, create and delete -- are automatically created for each Django model.
+ Three basic permissions -- add, change and delete -- are automatically created for each Django model.
"""
name = models.CharField(_('name'), maxlength=50)
content_type = models.ForeignKey(ContentType)
@@ -0,0 +1,90 @@
+from django.core import urlresolvers
+import urllib
+
+PING_URL = "http://www.google.com/webmasters/sitemaps/ping"
+
+class SitemapNotFound(Exception):
+ pass
+
+def ping_google(sitemap_url=None, ping_url=PING_URL):
+ """
+ Alerts Google that the sitemap for the current site has been updated.
+ If sitemap_url is provided, it should be an absolute path to the sitemap
+ for this site -- e.g., '/sitemap.xml'. If sitemap_url is not provided, this
+ function will attempt to deduce it by using urlresolvers.reverse().
+ """
+ if sitemap_url is None:
+ try:
+ # First, try to get the "index" sitemap URL.
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemap.views.index')
+ except urlresolvers.NoReverseMatch:
+ try:
+ # Next, try for the "global" sitemap URL.
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemap.views.sitemap')
+ except urlresolvers.NoReverseMatch:
+ pass
+
+ if sitemap_url is None:
+ raise SitemapNotFound("You didn't provide a sitemap_url, and the sitemap URL couldn't be auto-detected.")
+
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ url = "%s%s" % (current_site.domain, sitemap)
+ params = urllib.urlencode({'sitemap':url})
+ urllib.urlopen("%s?%s" % (ping_url, params))
+
+class Sitemap:
+ def __get(self, name, obj, default=None):
+ try:
+ attr = getattr(self, name)
+ except AttributeError:
+ return default
+ if callable(attr):
+ return attr(obj)
+ return attr
+
+ def items(self):
+ return []
+
+ def location(self, obj):
+ return obj.get_absolute_url()
+
+ def get_urls(self):
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ urls = []
+ for item in self.items():
+ loc = "http://%s%s" % (current_site.domain, self.__get('location', item))
+ url_info = {
+ 'location': loc,
+ 'lastmod': self.__get('lastmod', item, None),
+ 'changefreq': self.__get('changefreq', item, None),
+ 'priority': self.__get('priority', item, None)
+ }
+ urls.append(url_info)
+ return urls
+
+class FlatPageSitemap(Sitemap):
+ def items(self):
+ from django.contrib.sites.models import Site
+ current_site = Site.objects.get_current()
+ return current_site.flatpage_set.all()
+
+class GenericSitemap(Sitemap):
+ priority = None
+ changefreq = None
+
+ def __init__(self, info_dict, priority=None, changefreq=None):
+ self.queryset = info_dict['queryset']
+ self.date_field = info_dict.get('date_field', None)
+ self.priority = priority
+ self.changefreq = changefreq
+
+ def items(self):
+ # Make sure to return a clone; we don't want premature evaluation.
+ return self.queryset.filter()
+
+ def lastmod(self, item):
+ if self.date_field is not None:
+ return getattr(item, self.date_field)
+ return None
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<urlset xmlns="http://www.google.com/schemas/sitemap/0.84">
+{% for url in urlset %}
+ <url>
+ <loc>{{ url.location|escape }}</loc>
+ {% if url.lastmod %}<lastmod>{{ url.lastmod|date:"Y-m-d" }}</lastmod>{% endif %}
+ {% if url.changefreq %}<changefreq>{{ url.changefreq }}</changefreq>{% endif %}
+ {% if url.priority %}<priority>{{ url.priority }}</priority>{% endif %}
+ </url>
+{% endfor %}
+</urlset>
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sitemapindex xmlns="http://www.google.com/schemas/sitemap/0.84">
+{% for location in sitemaps %}
+ <sitemap>
+ <loc>{{ location|escape }}</loc>
+ </sitemap>
+{% endfor %}
+</sitemapindex>
@@ -0,0 +1,30 @@
+from django.http import HttpResponse, Http404
+from django.template import loader
+from django.contrib.sites.models import Site
+from django.core import urlresolvers
+
+def index(request, sitemaps):
+ current_site = Site.objects.get_current()
+ sites = []
+ protocol = request.is_secure() and 'https' or 'http'
+ for section in sitemaps.keys():
+ sitemap_url = urlresolvers.reverse('django.contrib.sitemap.views.sitemap', kwargs={'section': section})
+ sites.append('%s://%s%s' % (protocol, current_site.domain, sitemap_url))
+ xml = loader.render_to_string('sitemap_index.xml', {'sitemaps': sites})
+ return HttpResponse(xml, mimetype='application/xml')
+
+def sitemap(request, sitemaps, section=None):
+ maps, urls = [], []
+ if section is not None:
+ if not sitemaps.has_key(section):
+ raise Http404("No sitemap available for section: %r" % section)
+ maps.append(sitemaps[section])
+ else:
+ maps = sitemaps.values()
+ for site in maps:
+ if callable(site):
+ urls.extend(site().get_urls())
+ else:
+ urls.extend(site.get_urls())
+ xml = loader.render_to_string('sitemap.xml', {'urlset': urls})
+ return HttpResponse(xml, mimetype='application/xml')
@@ -294,19 +294,22 @@ def syncdb(verbosity=2, interactive=True):
except ImportError:
pass
- # Send the post_syncdb signal, so individual apps can do whatever they need
- # to do at this point.
+ # Install each app
for app in models.get_apps():
# Install each application (models already installed will be skipped)
created = _install(app, commit=False, initial_data=False)
if verbosity >= 2:
for model in created:
print "Created table %s" % model._meta.db_table
created_models.extend(created)
+ transaction.commit_unless_managed()
+
+ # Send the post_syncdb signal, so individual apps can do whatever they need
+ # to do at this point.
+ for app in models.get_apps():
dispatcher.send(signal=signals.post_syncdb, sender=app,
app=app, created_models=created_models,
verbosity=verbosity, interactive=interactive)
- transaction.commit_unless_managed()
# Install initial data for the app (but only if this is a model we've
# just created)
Oops, something went wrong.

0 comments on commit b17f250

Please sign in to comment.