Changeset 6337
- Timestamp:
- 09/15/07 16:42:51 (1 year ago)
- Files:
-
- django/branches/queryset-refactor/AUTHORS (modified) (3 diffs)
- django/branches/queryset-refactor/django/contrib/admin/media/css/widgets.css (modified) (1 diff)
- django/branches/queryset-refactor/django/contrib/admin/media/js/admin/DateTimeShortcuts.js (modified) (1 diff)
- django/branches/queryset-refactor/django/contrib/auth/decorators.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/contrib/auth/views.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/contrib/localflavor/ca (copied) (copied from django/trunk/django/contrib/localflavor/ca)
- django/branches/queryset-refactor/django/contrib/localflavor/ca/ca_provinces.py (copied) (copied from django/trunk/django/contrib/localflavor/ca/ca_provinces.py)
- django/branches/queryset-refactor/django/contrib/localflavor/ca/forms.py (copied) (copied from django/trunk/django/contrib/localflavor/ca/forms.py)
- django/branches/queryset-refactor/django/contrib/localflavor/ca/__init__.py (copied) (copied from django/trunk/django/contrib/localflavor/ca/__init__.py)
- django/branches/queryset-refactor/django/contrib/localflavor/generic (copied) (copied from django/trunk/django/contrib/localflavor/generic)
- django/branches/queryset-refactor/django/contrib/localflavor/generic/forms.py (copied) (copied from django/trunk/django/contrib/localflavor/generic/forms.py)
- django/branches/queryset-refactor/django/contrib/localflavor/generic/__init__.py (copied) (copied from django/trunk/django/contrib/localflavor/generic/__init__.py)
- django/branches/queryset-refactor/django/core/handlers/base.py (modified) (1 diff)
- django/branches/queryset-refactor/django/core/management/commands/adminindex.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/core/management/commands/testserver.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/core/management/validation.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/backends/oracle/base.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/backends/sqlite3/base.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/models/base.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/queryset-refactor/django/db/models/options.py (modified) (1 diff)
- django/branches/queryset-refactor/django/http/__init__.py (modified) (3 diffs)
- django/branches/queryset-refactor/django/shortcuts/__init__.py (modified) (1 diff)
- django/branches/queryset-refactor/django/template/__init__.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/test/client.py (modified) (2 diffs)
- django/branches/queryset-refactor/django/utils/itercompat.py (modified) (1 diff)
- django/branches/queryset-refactor/docs/authentication.txt (modified) (1 diff)
- django/branches/queryset-refactor/docs/databrowse.txt (modified) (1 diff)
- django/branches/queryset-refactor/docs/django-admin.txt (modified) (1 diff)
- django/branches/queryset-refactor/docs/model-api.txt (modified) (2 diffs)
- django/branches/queryset-refactor/docs/shortcuts.txt (copied) (copied from django/trunk/docs/shortcuts.txt)
- django/branches/queryset-refactor/tests/modeltests/custom_pk/models.py (modified) (2 diffs)
- django/branches/queryset-refactor/tests/modeltests/test_client/models.py (modified) (1 diff)
- django/branches/queryset-refactor/tests/modeltests/test_client/urls.py (modified) (1 diff)
- django/branches/queryset-refactor/tests/modeltests/test_client/views.py (modified) (1 diff)
- django/branches/queryset-refactor/tests/regressiontests/backends (copied) (copied from django/trunk/tests/regressiontests/backends)
- django/branches/queryset-refactor/tests/regressiontests/backends/__init__.py (copied) (copied from django/trunk/tests/regressiontests/backends/__init__.py)
- django/branches/queryset-refactor/tests/regressiontests/backends/models.py (copied) (copied from django/trunk/tests/regressiontests/backends/models.py)
- django/branches/queryset-refactor/tests/regressiontests/forms/localflavor.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/queryset-refactor/AUTHORS
r6335 r6337 233 233 phil.h.smith@gmail.com 234 234 Gustavo Picon 235 pigletto 235 236 Luke Plant <http://lukeplant.me.uk/> 236 237 plisk … … 263 264 smurf@smurf.noris.de 264 265 sopel 266 Leo Soto <leo.soto@gmail.com> 265 267 Wiliam Alves de Souza <wiliamsouza83@gmail.com> 266 268 Georgi Stanojevski <glisha@gmail.com> … … 275 277 Aaron Swartz <http://www.aaronsw.com/> 276 278 Ville Säävuori <http://www.unessa.net/> 279 Tyler Tarabula <tyler.tarabula@gmail.com> 277 280 Tyson Tate <tyson@fallingbullets.com> 278 281 Frank Tegtmeyer <fte@fte.to> django/branches/queryset-refactor/django/contrib/admin/media/css/widgets.css
r2809 r6337 44 44 /* CALENDARS & CLOCKS */ 45 45 .calendarbox, .clockbox { margin:5px auto; font-size:11px; width:16em; text-align:center; background:white; position:relative; } 46 .clockbox { width: 9em; }46 .clockbox { width:auto; } 47 47 .calendar { margin:0; padding: 0; } 48 48 .calendar table { margin:0; padding:0; border-collapse:collapse; background:white; width:99%; } django/branches/queryset-refactor/django/contrib/admin/media/js/admin/DateTimeShortcuts.js
r4087 r6337 196 196 var cal_box = document.getElementById(DateTimeShortcuts.calendarDivName1+num) 197 197 var cal_link = document.getElementById(DateTimeShortcuts.calendarLinkName+num) 198 var inp = DateTimeShortcuts.calendarInputs[num]; 199 200 // Determine if the current value in the input has a valid date. 201 // If so, draw the calendar with that date's year and month. 202 if (inp.value) { 203 var date_parts = inp.value.split('-'); 204 var year = date_parts[0]; 205 var month = parseFloat(date_parts[1]); 206 if (year.match(/\d\d\d\d/) && month >= 1 && month <= 12) { 207 DateTimeShortcuts.calendars[num].drawDate(month, year); 208 } 209 } 210 198 211 199 212 // Recalculate the clockbox position django/branches/queryset-refactor/django/contrib/auth/decorators.py
r5072 r6337 3 3 from urllib import quote 4 4 5 def user_passes_test(test_func, login_url=None ):5 def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 6 6 """ 7 7 Decorator for views that checks that the user passes the given test, … … 16 16 if test_func(request.user): 17 17 return view_func(request, *args, **kwargs) 18 return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, quote(request.get_full_path())))18 return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, quote(request.get_full_path()))) 19 19 _checklogin.__doc__ = view_func.__doc__ 20 20 _checklogin.__dict__ = view_func.__dict__ … … 23 23 return _dec 24 24 25 login_required = user_passes_test(lambda u: u.is_authenticated()) 26 login_required.__doc__ = ( 25 def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME): 27 26 """ 28 27 Decorator for views that checks that the user is logged in, redirecting 29 28 to the log-in page if necessary. 30 29 """ 30 actual_decorator = user_passes_test( 31 lambda u: u.is_authenticated(), 32 redirect_field_name=redirect_field_name 31 33 ) 34 if function: 35 return actual_decorator(function) 36 return actual_decorator 32 37 33 38 def permission_required(perm, login_url=None): django/branches/queryset-refactor/django/contrib/auth/views.py
r6004 r6337 10 10 from django.utils.translation import ugettext as _ 11 11 12 def login(request, template_name='registration/login.html' ):12 def login(request, template_name='registration/login.html', redirect_field_name=REDIRECT_FIELD_NAME): 13 13 "Displays the login form and handles the login action." 14 14 manipulator = AuthenticationForm(request) 15 redirect_to = request.REQUEST.get( REDIRECT_FIELD_NAME, '')15 redirect_to = request.REQUEST.get(redirect_field_name, '') 16 16 if request.POST: 17 17 errors = manipulator.get_validation_errors(request.POST) … … 36 36 return render_to_response(template_name, { 37 37 'form': oldforms.FormWrapper(manipulator, request.POST, errors), 38 REDIRECT_FIELD_NAME: redirect_to,38 redirect_field_name: redirect_to, 39 39 'site_name': current_site.name, 40 40 }, context_instance=RequestContext(request)) … … 57 57 return logout(request, login_url) 58 58 59 def redirect_to_login(next, login_url=None ):59 def redirect_to_login(next, login_url=None, redirect_field_name=REDIRECT_FIELD_NAME): 60 60 "Redirects the user to the login page, passing the given 'next' page" 61 61 if not login_url: 62 62 from django.conf import settings 63 63 login_url = settings.LOGIN_URL 64 return HttpResponseRedirect('%s?%s=%s' % (login_url, REDIRECT_FIELD_NAME, next))64 return HttpResponseRedirect('%s?%s=%s' % (login_url, redirect_field_name, next)) 65 65 66 66 def password_reset(request, is_admin_site=False, template_name='registration/password_reset_form.html', django/branches/queryset-refactor/django/core/handlers/base.py
r6334 r6337 143 143 this function converts them to absolute paths. 144 144 """ 145 if ' Location' in response.headers and http.get_host(request):145 if 'location' in response.headers and http.get_host(request): 146 146 response['Location'] = request.build_absolute_uri(response['Location']) 147 147 return response django/branches/queryset-refactor/django/core/management/commands/adminindex.py
r5898 r6337 1 1 from django.core.management.base import AppCommand 2 from django.utils.encoding import force_unicode 2 3 from django.utils.text import capfirst 3 4 … … 25 26 'app': app_label, 26 27 'mod': model._meta.module_name, 27 'name': capfirst(model._meta.verbose_name_plural),28 'name': force_unicode(capfirst(model._meta.verbose_name_plural)), 28 29 'addperm': model._meta.get_add_permission(), 29 30 'changeperm': model._meta.get_change_permission(), django/branches/queryset-refactor/django/core/management/commands/testserver.py
r6075 r6337 8 8 type='choice', choices=['0', '1', '2'], 9 9 help='Verbosity level; 0=minimal output, 1=normal output, 2=all output'), 10 make_option('--addrport', action='store', dest='addrport', 11 type='string', default='', 12 help='port number or ipaddr:port to run the server on'), 10 13 ) 11 14 help = 'Runs a development server with data from the given fixture(s).' … … 20 23 21 24 verbosity = int(options.get('verbosity', 1)) 25 addrport = options.get('addrport') 22 26 23 27 # Create a test database. … … 31 35 # multiple times. 32 36 shutdown_message = '\nServer stopped.\nNote that the test database, %r, has not been deleted. You can explore it on your own.' % db_name 33 call_command('runserver', shutdown_message=shutdown_message, use_reloader=False)37 call_command('runserver', addrport=addrport, shutdown_message=shutdown_message, use_reloader=False) django/branches/queryset-refactor/django/core/management/validation.py
r5898 r6337 1 1 import sys 2 2 from django.core.management.color import color_style 3 from django.utils.itercompat import is_iterable 3 4 4 5 class ModelErrorCollection: … … 52 53 e.add(opts, '"%s": prepopulate_from should be a list or tuple.' % f.name) 53 54 if f.choices: 54 if not hasattr(f.choices, '__iter__'): 55 if isinstance(f.choices, basestring) or \ 56 not is_iterable(f.choices): 55 57 e.add(opts, '"%s": "choices" should be iterable (e.g., a tuple or list).' % f.name) 56 58 else: django/branches/queryset-refactor/django/db/backends/oracle/base.py
r6336 r6337 439 439 charset = 'utf-8' 440 440 441 def _rewrite_args(self, query, params=None):442 if params is None:443 params = []444 else:445 params = self._format_params(params)446 args = [(':arg%d' % i) for i in range(len(params))]447 query = smart_str(query, self.charset) % tuple(args)448 # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it449 # it does want a trailing ';' but not a trailing '/'. However, these450 # characters must be included in the original query in case the query451 # is being passed to SQL*Plus.452 if query.endswith(';') or query.endswith('/'):453 query = query[:-1]454 return query, params455 456 441 def _format_params(self, params): 457 442 if isinstance(params, dict): … … 465 450 466 451 def execute(self, query, params=None): 467 query, params = self._rewrite_args(query, params) 452 if params is None: 453 params = [] 454 else: 455 params = self._format_params(params) 456 args = [(':arg%d' % i) for i in range(len(params))] 457 # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it 458 # it does want a trailing ';' but not a trailing '/'. However, these 459 # characters must be included in the original query in case the query 460 # is being passed to SQL*Plus. 461 if query.endswith(';') or query.endswith('/'): 462 query = query[:-1] 463 query = smart_str(query, self.charset) % tuple(args) 468 464 return Database.Cursor.execute(self, query, params) 469 465 470 466 def executemany(self, query, params=None): 471 query, params = self._rewrite_args(query, params) 472 return Database.Cursor.executemany(self, query, params) 467 try: 468 args = [(':arg%d' % i) for i in range(len(params[0]))] 469 except (IndexError, TypeError): 470 # No params given, nothing to do 471 return None 472 # cx_Oracle wants no trailing ';' for SQL statements. For PL/SQL, it 473 # it does want a trailing ';' but not a trailing '/'. However, these 474 # characters must be included in the original query in case the query 475 # is being passed to SQL*Plus. 476 if query.endswith(';') or query.endswith('/'): 477 query = query[:-1] 478 query = smart_str(query, self.charset) % tuple(args) 479 new_param_list = [self._format_params(i) for i in params] 480 return Database.Cursor.executemany(self, query, new_param_list) 473 481 474 482 def fetchone(self): django/branches/queryset-refactor/django/db/backends/sqlite3/base.py
r6035 r6337 134 134 135 135 def executemany(self, query, param_list): 136 query = self.convert_query(query, len(param_list[0])) 137 return Database.Cursor.executemany(self, query, param_list) 136 try: 137 query = self.convert_query(query, len(param_list[0])) 138 return Database.Cursor.executemany(self, query, param_list) 139 except (IndexError,TypeError): 140 # No parameter list provided 141 return None 138 142 139 143 def convert_query(self, query, num_params): django/branches/queryset-refactor/django/db/models/base.py
r6334 r6337 13 13 from django.utils.datastructures import SortedDict 14 14 from django.utils.functional import curry 15 from django.utils.encoding import smart_str, force_unicode 15 from django.utils.encoding import smart_str, force_unicode, smart_unicode 16 16 from django.conf import settings 17 17 from itertools import izip … … 214 214 # Note: the comparison with '' is required for compatibility with 215 215 # oldforms-style model creation. 216 pk_set = pk_val is not None and pk_val!= u''216 pk_set = pk_val is not None and smart_unicode(pk_val) != u'' 217 217 record_exists = True 218 218 if pk_set: django/branches/queryset-refactor/django/db/models/fields/__init__.py
r6335 r6337 694 694 class EmailField(CharField): 695 695 def __init__(self, *args, **kwargs): 696 kwargs['max_length'] = 75 696 if 'max_length' not in kwargs: 697 kwargs['max_length'] = 75 697 698 CharField.__init__(self, *args, **kwargs) 698 699 django/branches/queryset-refactor/django/db/models/options.py
r6335 r6337 53 53 for attr_name in DEFAULT_NAMES: 54 54 setattr(self, attr_name, meta_attrs.pop(attr_name, getattr(self, attr_name))) 55 56 # unique_together can be either a tuple of tuples, or a single 57 # tuple of two strings. Normalize it to a tuple of tuples, so that 58 # calling code can uniformly expect that. 59 ut = meta_attrs.pop('unique_together', getattr(self, 'unique_together')) 60 if ut and not isinstance(ut[0], (tuple, list)): 61 ut = (ut,) 62 setattr(self, 'unique_together', ut) 63 55 64 # verbose_name_plural is a special case because it uses a 's' 56 65 # by default. 57 66 setattr(self, 'verbose_name_plural', meta_attrs.pop('verbose_name_plural', string_concat(self.verbose_name, 's'))) 67 58 68 # Any leftover attributes must be invalid. 59 69 if meta_attrs != {}: django/branches/queryset-refactor/django/http/__init__.py
r6334 r6337 247 247 self._container = [content] 248 248 self._is_string = True 249 self.headers = {' Content-Type': content_type}249 self.headers = {'content-type': content_type} 250 250 self.cookies = SimpleCookie() 251 251 if status: … … 259 259 260 260 def __setitem__(self, header, value): 261 self.headers[header ] = value261 self.headers[header.lower()] = value 262 262 263 263 def __delitem__(self, header): 264 264 try: 265 del self.headers[header ]265 del self.headers[header.lower()] 266 266 except KeyError: 267 267 pass 268 268 269 269 def __getitem__(self, header): 270 return self.headers[header ]270 return self.headers[header.lower()] 271 271 272 272 def has_header(self, header): 273 273 "Case-insensitive check for a header" 274 header = header.lower() 275 for key in self.headers.keys(): 276 if key.lower() == header: 277 return True 278 return False 274 return self.headers.has_key(header.lower()) 279 275 280 276 def set_cookie(self, key, value='', max_age=None, expires=None, path='/', domain=None, secure=None): … … 305 301 306 302 def __iter__(self): 307 self._iterator = self._container.__iter__()303 self._iterator = iter(self._container) 308 304 return self 309 305 django/branches/queryset-refactor/django/shortcuts/__init__.py
r5756 r6337 15 15 django.template.loader.render_to_string() with the passed arguments. 16 16 """ 17 return HttpResponse(loader.render_to_string(*args, **kwargs)) 17 httpresponse_kwargs = {'mimetype': kwargs.pop('mimetype')} 18 return HttpResponse(loader.render_to_string(*args, **kwargs), **httpresponse_kwargs) 18 19 load_and_render = render_to_response # For backwards compatibility. 19 20 django/branches/queryset-refactor/django/template/__init__.py
r5630 r6337 59 59 from django.conf import settings 60 60 from django.template.context import Context, RequestContext, ContextPopException 61 from django.utils.itercompat import is_iterable 61 62 from django.utils.functional import curry, Promise 62 63 from django.utils.text import smart_split … … 901 902 if not getattr(self, 'nodelist', False): 902 903 from django.template.loader import get_template, select_template 903 if hasattr(file_name, '__iter__'):904 if not isinstance(file_name, basestring) and is_iterable(file_name): 904 905 t = select_template(file_name) 905 906 else: django/branches/queryset-refactor/django/test/client.py
r6039 r6337 17 17 from django.utils.encoding import smart_str 18 18 from django.utils.http import urlencode 19 from django.utils.itercompat import is_iterable 19 20 20 21 BOUNDARY = 'BoUnDaRyStRiNg' … … 75 76 value.read() 76 77 ]) 77 elif hasattr(value, '__iter__'): 78 for item in value: 78 else: 79 if not isinstance(value, basestring) and is_iterable(value): 80 for item in value: 81 lines.extend([ 82 '--' + boundary, 83 'Content-Disposition: form-data; name="%s"' % to_str(key), 84 '', 85 to_str(item) 86 ]) 87 else: 79 88 lines.extend([ 80 89 '--' + boundary, 81 90 'Content-Disposition: form-data; name="%s"' % to_str(key), 82 91 '', 83 to_str( item)92 to_str(value) 84 93 ]) 85 else:86 lines.extend([87 '--' + boundary,88 'Content-Disposition: form-data; name="%s"' % to_str(key),89 '',90 to_str(value)91 ])92 94 93 95 lines.extend([ django/branches/queryset-refactor/django/utils/itercompat.py
r5526 r6337 58 58 if hasattr(itertools, 'groupby'): 59 59 groupby = itertools.groupby 60 61 def is_iterable(x): 62 "A implementation independent way of checking for iterables" 63 try: 64 iter(x) 65 except TypeError: 66 return False 67 else: 68 return True 69 django/branches/queryset-refactor/docs/authentication.txt
r6037 r6337 403 403 # ... 404 404 405 In the Django development version, ``login_required`` also takes an optional 406 ``redirect_field_name`` parameter. Example:: 407 408 from django.contrib.auth.decorators import login_required 409 410 def my_view(request): 411 # ... 412 my_view = login_required(redirect_field_name='redirect_to')(my_view) 413 414 Again, an equivalent example of the more compact decorator syntax introduced in Python 2.4:: 415 416 from django.contrib.auth.decorators import login_required 417 418 @login_required(redirect_field_name='redirect_to') 419 def my_view(request): 420 # ... 421 405 422 ``login_required`` does the following: 406 423 407 424 * If the user isn't logged in, redirect to ``settings.LOGIN_URL`` 408 425 (``/accounts/login/`` by default), passing the current absolute URL 409 in the query string as ``next``. For example: 426 in the query string as ``next`` or the value of ``redirect_field_name``. 427 For example: 410 428 ``/accounts/login/?next=/polls/3/``. 411 429 * If the user is logged in, execute the view normally. The view code is django/branches/queryset-refactor/docs/databrowse.txt
r5866 r6337 59 59 4. Run the Django server and visit ``/databrowse/`` in your browser. 60 60 61 Requiring user login 62 ==================== 63 64 You can restrict access to logged-in users with only a few extra lines of 65 code. Simply add the following import to your URLconf:: 66 67 from django.contrib.auth.decorators import login_required 68 69 Then modify the URLconf so that the ``databrowse.site.root`` view is decorated 70 with ``login_required``:: 71 72 (r'^databrowse/(.*)', login_required(databrowse.site.root)), 73 74 If you haven't already added support for user logins to your URLconf, as 75 described in the `user authentication docs`_, then you will need to do so 76 now with the following mapping:: 77 78 (r'^accounts/login/$', 'django.contrib.auth.views.login'), 79 80 The final step is to create the login form required by 81 ``django.contrib.auth.views.login``. The `user authentication docs`_ 82 provide full details and a sample template that can be used for this 83 purpose. 84 61 85 .. _template loader docs: ../templates_python/#loader-types 86 .. _user authentication docs: ../authentication/ django/branches/queryset-refactor/docs/django-admin.txt
r6077 r6337 628 628 being made to a test database. 629 629 630 Note that this server can only run on the default port on localhost; it does 631 not yet accept a ``host`` or ``port`` parameter. 632 633 Also note that it does *not* automatically detect changes to your Python source 634 code (as ``runserver`` does). It does, however, detect changes to templates. 630 Note that this server does *not* automatically detect changes to your Python 631 source code (as ``runserver`` does). It does, however, detect changes to 632 templates. 635 633 636 634 .. _unit tests: ../testing/ 635 636 --addrport [port number or ipaddr:port] 637 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 638 639 Use ``--addrport`` to specify a different port, or IP address and port, from 640 the default of 127.0.0.1:8000. This value follows exactly the same format and 641 serves exactly the same function as the argument to the ``runserver`` subcommand. 642 643 Examples: 644 645 To run the test server on port 7000 with ``fixture1`` and ``fixture2``:: 646 647 django-admin.py testserver --addrport 7000 fixture1 fixture2 648 django-admin.py testserver fixture1 fixture2 --addrport 8080 649 650 (The above statements are equivalent. We include both of them to demonstrate 651 that it doesn't matter whether the options come before or after the 652 ``testserver`` command.) 653 654 To run on 1.2.3.4:7000 with a `test` fixture:: 655 656 django-admin.py testserver --addrport 1.2.3.4:7000 test 637 657 638 658 --verbosity django/branches/queryset-refactor/docs/model-api.txt
r6334 r6337 222 222 223 223 A ``CharField`` that checks that the value is a valid e-mail address. 224 This doesn't accept ``max_length``; its ``max_length`` is automatically set to 225 75. 224 225 In Django 0.96, this doesn't accept ``max_length``; its ``max_length`` is 226 automatically set to 75. In the Django development version, ``max_length`` is 227 set to 75 by default, but you can specify it to override default behavior. 226 228 227 229 ``FileField`` … … 1224 1226 level (i.e., the appropriate ``UNIQUE`` statements are included in the 1225 1227 ``CREATE TABLE`` statement). 1228 1229 **New in Django development version** 1230 1231 For convenience, unique_together can be a single list when dealing 1232 with a single set of fields:: 1233 1234 unique_together = ("driver", "restaurant") 1226 1235 1227 1236 ``verbose_name`` django/branches/queryset-refactor/tests/modeltests/custom_pk/models.py
r5876 r6337 1 # -*- coding: utf-8 -*- 1 2 """ 2 3 14. Using a custom primary key … … 93 94 [<Business: Sears>] 94 95 96 # Primary key may be unicode string 97 >>> emp = Employee(employee_code='jaźń') 98 >>> emp.save() 99 95 100 """} django/branches/queryset-refactor/tests/modeltests/test_client/models.py
r6334 r6337 251 251 self.assertEqual(response.context['user'].username, 'testclient') 252 252 253 def test_view_with_login_and_custom_redirect(self): 254 "Request a page that is protected with @login_required(redirect_field_name='redirect_to')" 255 256 # Get the page without logging in. Should result in 302. 257 response = self.client.get('/test_client/login_protected_view_custom_redirect/') 258 self.assertRedirects(response, 'http://testserver/accounts/login/?redirect_to=/test_client/login_protected_view_custom_redirect/') 259 260 # Log in 261 login = self.client.login(username='testclient', password='password') 262 self.failUnless(login, 'Could not log in') 263 264 # Request a page that requires a login 265 response = self.client.get('/test_client/login_protected_view_custom_redirect/') 266 self.assertEqual(response.status_code, 200) 267 self.assertEqual(response.context['user'].username, 'testclient') 268 253 269 def test_view_with_bad_login(self): 254 270 "Request a page that is protected with @login, but use bad credentials" django/branches/queryset-refactor/tests/modeltests/test_client/urls.py
r5876 r6337 14 14 (r'^form_view_with_template/$', views.form_view_with_template), 15 15 (r'^login_protected_view/$', views.login_protected_view), 16 (r'^login_protected_view_custom_redirect/$', views.login_protected_view_changed_redirect), 16 17 (r'^session_view/$', views.session_view), 17 18 (r'^broken_view/$', views.broken_view), django/branches/queryset-refactor/tests/modeltests/test_client/views.py
r6046 r6337 123 123 login_protected_view = login_required(login_protected_view) 124 124 125 def login_protected_view_changed_redirect(request): 126 "A simple view that is login protected with a custom redirect field set" 127 t = Template('This is a login protected test. Username is {{ user.username }}.', name='Login Template') 128 c = Context({'user': request.user}) 129 130 return HttpResponse(t.render(c)) 131 login_protected_view_changed_redirect = login_required(redirect_field_name="redirect_to")(login_protected_view_changed_redirect) 132 125 133 def session_view(request): 126 134 "A view that modifies the session" django/branches/queryset-refactor/tests/regressiontests/forms/localflavor.py
r6334 r6337 1819 1819 >>> f.clean(u'') 1820 1820 u'' 1821 1822 # CAPostalCodeField ############################################################## 1823 1824 CAPostalCodeField validates that the data is a six-character Canadian postal code. 1825 >>> from django.contrib.localflavor.ca.forms import CAPostalCodeField 1826 >>> f = CAPostalCodeField() 1827 >>> f.clean('T2S 2H7') 1828 u'T2S 2H7' 1829 >>> f.clean('T2S 2H') 1830 Traceback (most recent call last): 1831 ... 1832 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1833 >>> f.clean('2T6 H8I') 1834 Traceback (most recent call last): 1835 ... 1836 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1837 >>> f.clean('T2S2H') 1838 Traceback (most recent call last): 1839 ... 1840 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1841 >>> f.clean(90210) 1842 Traceback (most recent call last): 1843 ... 1844 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1845 >>> f.clean(None) 1846 Traceback (most recent call last): 1847 ... 1848 ValidationError: [u'This field is required.'] 1849 >>> f.clean('') 1850 Traceback (most recent call last): 1851 ... 1852 ValidationError: [u'This field is required.'] 1853 >>> f = CAPostalCodeField(required=False) 1854 >>> f.clean('T2S 2H7') 1855 u'T2S 2H7' 1856 >>> f.clean('T2S2H7') 1857 Traceback (most recent call last): 1858 ... 1859 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1860 >>> f.clean('T2S 2H') 1861 Traceback (most recent call last): 1862 ... 1863 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1864 >>> f.clean('2T6 H8I') 1865 Traceback (most recent call last): 1866 ... 1867 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1868 >>> f.clean('T2S2H') 1869 Traceback (most recent call last): 1870 ... 1871 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1872 >>> f.clean(90210) 1873 Traceback (most recent call last): 1874 ... 1875 ValidationError: [u'Enter a postal code in the format XXX XXX.'] 1876 >>> f.clean(None) 1877 u'' 1878 >>> f.clean('') 1879 u'' 1880 1881 # CAPhoneNumberField ########################################################## 1882 1883 CAPhoneNumberField validates that the data is a valid Canadian phone number, 1884 including the area code. It's normalized to XXX-XXX-XXXX format. 1885 Note: This test is exactly the same as the USPhoneNumberField except using a real 1886 Candian area code 1887 1888 >>> from django.contrib.localflavor.ca.forms import CAPhoneNumberField 1889 >>> f = CAPhoneNumberField() 1890 >>> f.clean('403-555-1212') 1891 u'403-555-1212' 1892 >>> f.clean('4035551212') 1893 u'403-555-1212' 1894 >>> f.clean('403 555-1212') 1895 u'403-555-1212' 1896 >>> f.clean('(403) 555-1212') 1897 u'403-555-1212' 1898 >>> f.clean('403 555 1212') 1899 u'403-555-1212' 1900 >>> f.clean('403.555.1212') 1901 u'403-555-1212' 1902 >>> f.clean('403.555-1212') 1903 u'403-555-1212' 1904 >>> f.clean(' (403) 555.1212 ') 1905 u'403-555-1212' 1906 >>> f.clean('555-1212') 1907 Traceback (most recent call last): 1908 ... 1909 ValidationError: [u'Phone numbers must be in XXX-XXX-XXXX format.'] 1910 >>> f.clean('403-55-1212'
