Commits

Anonymous committed c164edb

i18n: merged to [1054] of trunk

  • Participants
  • Parent commits 58dec54
  • Branches i18n

Comments (0)

Files changed (17)

django/core/db/__init__.py

 """
 This is the core database connection.
 
-All CMS code assumes database SELECT statements cast the resulting values as such:
+All Django code assumes database SELECT statements cast the resulting values as such:
     * booleans are mapped to Python booleans
     * dates are mapped to Python datetime.date objects
     * times are mapped to Python datetime.time objects
     * timestamps are mapped to Python datetime.datetime objects
-
-Right now, we're handling this by using psycopg's custom typecast definitions.
-If we move to a different database module, we should ensure that it either
-performs the appropriate typecasting out of the box, or that it has hooks that
-let us do that.
 """
 
 from django.conf.settings import DATABASE_ENGINE
 get_random_function_sql = dbmod.get_random_function_sql
 get_table_list = dbmod.get_table_list
 get_relations = dbmod.get_relations
+quote_name = dbmod.quote_name
 OPERATOR_MAPPING = dbmod.OPERATOR_MAPPING
 DATA_TYPES = dbmod.DATA_TYPES
 DATA_TYPES_REVERSE = dbmod.DATA_TYPES_REVERSE

django/core/db/backends/ado_mssql.py

 def get_relations(cursor, table_name):
     raise NotImplementedError
 
+def quote_name(name):
+    # TODO: Figure out how MS-SQL quotes database identifiers.
+    return name
+
 OPERATOR_MAPPING = {
     'exact': '=',
     'iexact': 'LIKE',

django/core/db/backends/mysql.py

 def get_relations(cursor, table_name):
     raise NotImplementedError
 
+def quote_name(name):
+    if name.startswith("`") and name.endswith("`"):
+        return name # Quoting once is enough.
+    return "`%s`" % name
+
 OPERATOR_MAPPING = {
     'exact': '=',
     'iexact': 'LIKE',
-    'contains': 'LIKE',
+    'contains': 'LIKE BINARY',
     'icontains': 'LIKE',
     'ne': '!=',
     'gt': '>',
     'gte': '>=',
     'lt': '<',
     'lte': '<=',
-    'startswith': 'LIKE',
-    'endswith': 'LIKE',
+    'startswith': 'LIKE BINARY',
+    'endswith': 'LIKE BINARY',
     'istartswith': 'LIKE',
     'iendswith': 'LIKE',
 }

django/core/db/backends/postgresql.py

             continue
     return relations
 
+def quote_name(name):
+    if name.startswith('"') and name.endswith('"'):
+        return name # Quoting once is enough.
+    return '"%s"' % name
+
 # Register these custom typecasts, because Django expects dates/times to be
 # in Python's native (standard-library) datetime/time format, whereas psycopg
 # use mx.DateTime by default.

django/core/db/backends/sqlite3.py

 def get_relations(cursor, table_name):
     raise NotImplementedError
 
+def quote_name(name):
+    if name.startswith('"') and name.endswith('"'):
+        return name # Quoting once is enough.
+    return '"%s"' % name
+
 # Operators and fields ########################################################
 
 OPERATOR_MAPPING = {

django/core/template/defaultfilters.py

     Displays a floating point number as 34.2 (with one decimal place) -- but
     only if there's a point to be displayed
     """
-    f = float(text)
+    try:
+        f = float(text)
+    except ValueError:
+        return ''
     m = f - int(f)
     if m:
         return '%.1f' % f

django/core/template/defaulttags.py

         self.filepath, self.parsed = filepath, parsed
 
     def render(self, context):
+        from django.conf.settings import DEBUG
         if not include_is_allowed(self.filepath):
-            return '' # Fail silently for invalid includes.
+            if DEBUG:
+                return "[Didn't have permission to include file]"
+            else:
+                return '' # Fail silently for invalid includes.
         try:
             fp = open(self.filepath, 'r')
             output = fp.read()
             try:
                 t = Template(output)
                 return t.render(context)
-            except TemplateSyntaxError:
-                return '' # Fail silently for invalid included templates.
+            except (TemplateSyntaxError, e):
+                if DEBUG:
+                    return "[Included template had syntax error: %s]" % e
+                else:
+                    return '' # Fail silently for invalid included templates.
         return output
 
 class LoadNode(Node):

django/middleware/sessions.py

             session_key = request.session.session_key or sessions.get_new_session_key()
             new_session = sessions.save(session_key, request.session._session,
                 datetime.datetime.now() + datetime.timedelta(seconds=SESSION_COOKIE_AGE))
+            expires = datetime.datetime.strftime(datetime.datetime.utcnow() + datetime.timedelta(seconds=SESSION_COOKIE_AGE), "%a, %d-%b-%Y %H:%M:%S GMT")
             response.set_cookie(SESSION_COOKIE_NAME, session_key,
-                max_age=SESSION_COOKIE_AGE, domain=SESSION_COOKIE_DOMAIN)
+                max_age=SESSION_COOKIE_AGE, expires=expires, domain=SESSION_COOKIE_DOMAIN)
         return response

django/utils/cache.py

 from django.core.cache import cache
 
 cc_delim_re = re.compile(r'\s*,\s*')
+
 def patch_cache_control(response, **kwargs):
     """
     This function patches the Cache-Control header by adding all
     keyword arguments to it. The transformation is as follows:
 
-    - all keyword parameter names are turned to lowercase and
-      all _ will be translated to -
-    - if the value of a parameter is True (exatly True, not just a
-      true value), only the parameter name is added to the header
-    - all other parameters are added with their value, after applying
-      str to it.
+    * All keyword parameter names are turned to lowercase, and underscores
+      are converted to hyphens.
+    * If the value of a parameter is True (exactly True, not just a
+      true value), only the parameter name is added to the header.
+    * All other parameters are added with their value, after applying
+      str() to it.
     """
-
     def dictitem(s):
         t = s.split('=',1)
         if len(t) > 1:

django/utils/httpwrappers.py

                 return True
         return False
 
-    def set_cookie(self, key, value='', max_age=None, path='/', domain=None, secure=None):
+    def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None):
         self.cookies[key] = value
-        for var in ('max_age', 'path', 'domain', 'secure'):
+        for var in ('max_age', 'path', 'domain', 'secure', 'expires'):
             val = locals()[var]
             if val is not None:
                 self.cookies[key][var.replace('_', '-')] = val
 
 .. _`HTTP Vary headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.44
 
-Controlling cache: Using Vary headers
-=====================================
+Controlling cache: Using other headers
+======================================
 
-Another problem with caching is the privacy of data, and the question where data can
-be stored in a cascade of caches. A user usually faces two kinds of caches: his own
-browser cache (a private cache) and his providers cache (a public cache). A public cache
-is used by multiple users and controlled by someone else. This poses problems with private
-(in the sense of sensitive) data - you don't want your social security number or your
-banking account numbers stored in some public cache. So web applications need a way
-to tell the caches what data is private and what is public.
+Another problem with caching is the privacy of data and the question of where
+data should be stored in a cascade of caches.
 
-Other aspects are the definition how long a page should be cached at max, or wether the
-cache should allways check for newer versions and only deliver the cache content when
-there were no changes (some caches might deliver cached content even if the server page
-changed - just because the cache copy isn't yet expired).
+A user usually faces two kinds of caches: his own browser cache (a private
+cache) and his provider's cache (a public cache). A public cache is used by
+multiple users and controlled by someone else. This poses problems with
+sensitive data: You don't want, say, your banking-account number stored in a
+public cache. So Web applications need a way to tell caches which data is
+private and which is public.
 
-So there are a multitude of options you can control for your pages. This is where the
-Cache-Control header (more infos in `HTTP Cache-Control headers`_) comes in. The usage
-is quite simple::
+The solution is to indicate a page's cache should be "private." To do this in
+Django, use the ``cache_control`` view decorator. Example::
 
-    @cache_control(private=True, must_revalidate=True, max_age=3600)
+    from django.views.decorators.cache import cache_control
+    @cache_control(private=True)
     def my_view(request):
         ...
 
-This would define the view as private, to be revalidated on every access and cache
-copies will only be stored for 3600 seconds at max.
+This decorator takes care of sending out the appropriate HTTP header behind the
+scenes.
 
-The caching middleware already set's this header up with a max-age of the CACHE_MIDDLEWARE_SETTINGS
-setting. And the cache_page decorator does the same. The cache_control decorator correctly merges
-different values into one big header, though. But you should take into account that middlewares
-might overwrite some of your headers or set their own defaults if you don't give that header yourself.
+There are a few other ways to control cache parameters. For example, HTTP
+allows applications to do the following:
 
-.. _`HTTP Cache-Control headers`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
+    * Define the maximum time a page should be cached.
+    * Specify whether a cache should always check for newer versions, only
+      delivering the cached content when there are no changes. (Some caches
+      might deliver cached content even if the server page changed -- simply
+      because the cache copy isn't yet expired.)
+
+In Django, use the ``cache_control`` view decorator to specify these cache
+parameters. In this example, ``cache_control`` tells caches to revalidate the
+cache on every access and to store cached versions for, at most, 3600 seconds::
+
+    from django.views.decorators.cache import cache_control
+    @cache_control(must_revalidate=True, max_age=3600)
+    def my_view(request):
+        ...
+
+Any valid ``Cache-Control`` directive is valid in ``cache_control()``. For a
+full list, see the `Cache-Control spec`_. Just pass the directives as keyword
+arguments to ``cache_control()``, substituting underscores for hyphens. For
+directives that don't take an argument, set the argument to ``True``.
+
+Examples:
+
+    * ``@cache_control(max_age=3600)`` turns into ``max-age=3600``.
+    * ``@cache_control(public=True)`` turns into ``public``.
+
+(Note that the caching middleware already sets the cache header's max-age with
+the value of the ``CACHE_MIDDLEWARE_SETTINGS`` setting. If you use a custom
+``max_age`` in a ``cache_control`` decorator, the decorator will take
+precedence, and the header values will be merged correctly.)
+
+.. _`Cache-Control spec`: http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
 
 Other optimizations
 ===================
                  ``foo``, ``FOO``, ``fOo``, etc.
     contains     Case-sensitive containment test:
                  ``polls.get_list(question__contains="spam")`` returns all polls
-                 that contain "spam" in the question. (PostgreSQL only. MySQL
-                 doesn't support case-sensitive LIKE statements; ``contains``
-                 will act like ``icontains`` for MySQL.)
+                 that contain "spam" in the question. (PostgreSQL and MySQL
+                 only. SQLite doesn't support case-sensitive LIKE statements;
+                 ``contains`` will act like ``icontains`` for SQLite.)
     icontains    Case-insensitive containment test.
     gt           Greater than: ``polls.get_list(id__gt=4)``.
     gte          Greater than or equal to.
                  a list of polls whose IDs are either 1, 3 or 4.
     startswith   Case-sensitive starts-with:
                  ``polls.get_list(question_startswith="Would")``. (PostgreSQL
-                 only. MySQL doesn't support case-sensitive LIKE statements;
-                 ``startswith`` will act like ``istartswith`` for MySQL.)
-    endswith     Case-sensitive ends-with. (PostgreSQL only. MySQL doesn't
-                 support case-sensitive LIKE statements; ``endswith`` will act
-                 like ``iendswith`` for MySQL.)
+                 and MySQL only. SQLite doesn't support case-sensitive LIKE
+                 statements; ``startswith`` will act like ``istartswith`` for
+                 SQLite.)
+    endswith     Case-sensitive ends-with. (PostgreSQL and MySQL only.)
     istartswith  Case-insensitive starts-with.
     iendswith    Case-insensitive ends-with.
     range        Range test:
 
     polls.get_list(order_by=['?'])
 
+There's no way to specify whether ordering should be case sensitive. With
+respect to case-sensitivity, Django will order results however your database
+backend normally orders them.
+
 Relationships (joins)
 =====================
 

docs/legacy_databases.txt

 
 You'll need to tell Django what your database connection parameters are, and
 what the name of the database is. Do that by editing these settings in your
-settings file:
+`settings file`_:
 
-    * ``DATABASE_ENGINE``
-    * ``DATABASE_USER``
-    * ``DATABASE_PASSWORD``
-    * ``DATABASE_NAME``
-    * ``DATABASE_HOST``
+    * `DATABASE_ENGINE`_
+    * `DATABASE_USER`_
+    * `DATABASE_PASSWORD`_
+    * `DATABASE_NAME`_
+    * `DATABASE_HOST`_
+    * `DATABASE_PORT`_
 
-For more information on these settings see `Tutorial 1`_.
-
-.. _Tutorial 1: http://www.djangoproject.com/documentation/tutorial1/
+.. _settings file: http://www.djangoproject.com/documentation/settings/
+.. _DATABASE_ENGINE: http://www.djangoproject.com/documentation/settings/#database-engine
+.. _DATABASE_USER: http://www.djangoproject.com/documentation/settings/#database-user
+.. _DATABASE_PASSWORD: http://www.djangoproject.com/documentation/settings/#database-password
+.. _DATABASE_NAME: http://www.djangoproject.com/documentation/settings/#database-name
+.. _DATABASE_HOST: http://www.djangoproject.com/documentation/settings/#database-host
+.. _DATABASE_PORT: http://www.djangoproject.com/documentation/settings/#database-port
 
 Auto-generate the models
 ========================
     * ``auth_groups``
     * ``auth_users``
     * ``auth_messages``
-    * ``auth_admin_log``
     * ``auth_groups_permissions``
     * ``auth_users_groups``
     * ``auth_users_user_permissions``

docs/request_response.txt

     Returns ``True`` or ``False`` based on a case-insensitive check for a
     header with the given name.
 
-``set_cookie(key, value='', max_age=None, path='/', domain=None, secure=None)``
+``set_cookie(key, value='', max_age=None, expires=None, path='/', domain=None, secure=None)``
     Sets a cookie. The parameters are the same as in the `cookie Morsel`_
     object in the Python standard library.
 
         * ``max_age`` should be a number of seconds, or ``None`` (default) if
           the cookie should last only as long as the client's browser session.
+        * ``expires`` should be a string in the format
+          ``"Wdy, DD-Mon-YY HH:MM:SS GMT"``.
         * Use ``domain`` if you want to set a cross-domain cookie. For example,
           ``domain=".lawrence.com"`` will set a cookie that is readable by
           the domains www.lawrence.com, blogs.lawrence.com and

docs/sessions.txt

     >>> s.get_decoded()
     {'user_id': 42}
 
+Session cookies
+===============
+
+A few `Django settings`_ give you control over the session cookie:
+
+SESSION_COOKIE_AGE
+------------------
+
+Default: ``1209600`` (2 weeks, in seconds)
+
+The age of session cookies, in seconds.
+
+SESSION_COOKIE_DOMAIN
+---------------------
+
+Default: ``None``
+
+The domain to use for session cookies. Set this to a string such as
+``".lawrence.com"`` for cross-domain cookies, or use ``None`` for a standard
+domain cookie.
+
+SESSION_COOKIE_NAME
+-------------------
+
+Default: ``'hotclub'``
+
+The name of the cookie to use for sessions. This can be whatever you want.
+
+``'hotclub'`` is a reference to the Hot Club of France, the band Django
+Reinhardt played in.
+
+.. _Django settings: http://www.djangoproject.com/documentation/settings/
+
 Technical details
 =================
 
       data, it won't send a session cookie.
 
 .. _`the pickle module`: http://www.python.org/doc/current/lib/module-pickle.html
+
+Session IDs in URLs
+===================
+
+The Django sessions framework is entirely, and solely, cookie-based. It does
+not fall back to putting session IDs in URLs as a last resort, as PHP does.
+This is an intentional design decision. Not only does that behavior make URLs
+ugly, it makes your site vulnerable to session-ID theft via the "Referer"
+header.

docs/tutorial04.txt

 change your templates so that ``latest_poll_list`` becomes ``object_list`` and
 ``poll`` becomes ``object``.
 
+In the ``vote()`` view, change the template call from ``polls/detail`` to
+``polls/polls_detail``, and pass ``object`` in the context instead of ``poll``.
+
 Finally, you can delete the ``index()``, ``detail()`` and ``results()`` views
 from ``polls/views/polls.py``. We don't need them anymore.
 

tests/testapp/models/basic.py

 <Article object>
 >>> articles.get_object(pub_date__year=2005)
 <Article object>
+>>> articles.get_object(pub_date__year=2005, pub_date__month=7)
+<Article object>
+>>> articles.get_object(pub_date__year=2005, pub_date__month=7, pub_date__day=28)
+<Article object>
+
+>>> articles.get_list(pub_date__year=2005)
+[<Article object>]
+>>> articles.get_list(pub_date__year=2004)
+[]
+>>> articles.get_list(pub_date__year=2005, pub_date__month=7)
+[<Article object>]
 
 # Django raises an ArticleDoesNotExist exception for get_object()
 >>> articles.get_object(id__exact=2)
     ...
 ArticleDoesNotExist: Article does not exist for {'id__exact': 2}
 
+>>> articles.get_object(pub_date__year=2005, pub_date__month=8)
+Traceback (most recent call last):
+    ...
+ArticleDoesNotExist: Article does not exist for ...
+
 # Lookup by a primary key is the most common case, so Django provides a
 # shortcut for primary-key exact lookups.
 # The following is identical to articles.get_object(id__exact=1).