Changeset 4157
- Timestamp:
- 12/04/06 14:52:14 (2 years ago)
- Files:
-
- django/branches/multiple-db-support/django/conf/global_settings.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/contrib/admin/media/js/dateparse.js (modified) (1 diff)
- django/branches/multiple-db-support/django/contrib/admin/templatetags/admin_modify.py (modified) (1 diff)
- django/branches/multiple-db-support/django/contrib/comments/models.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/management.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/paginator.py (modified) (5 diffs)
- django/branches/multiple-db-support/django/core/serializers/base.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/core/serializers/python.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/serializers/xml_serializer.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/servers/fastcgi.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/core/urlresolvers.py (modified) (1 diff)
- django/branches/multiple-db-support/django/core/validators.py (modified) (3 diffs)
- django/branches/multiple-db-support/django/db/backends/ado_mssql/base.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/backends/ansi/sql.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/backends/mysql/base.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/backends/oracle/base.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/backends/postgresql/base.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/backends/postgresql_psycopg2/base.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/backends/sqlite3/base.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/backends/util.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/__init__.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/multiple-db-support/django/db/models/manipulators.py (modified) (1 diff)
- django/branches/multiple-db-support/django/forms/__init__.py (modified) (1 diff)
- django/branches/multiple-db-support/django/newforms/fields.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/template/defaultfilters.py (modified) (1 diff)
- django/branches/multiple-db-support/django/template/defaulttags.py (modified) (2 diffs)
- django/branches/multiple-db-support/django/template/__init__.py (modified) (1 diff)
- django/branches/multiple-db-support/docs/forms.txt (modified) (1 diff)
- django/branches/multiple-db-support/docs/settings.txt (modified) (2 diffs)
- django/branches/multiple-db-support/docs/syndication_feeds.txt (modified) (4 diffs)
- django/branches/multiple-db-support/docs/templates.txt (modified) (1 diff)
- django/branches/multiple-db-support/tests/modeltests/pagination/models.py (modified) (1 diff)
- django/branches/multiple-db-support/tests/regressiontests/templates/tests.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/multiple-db-support/django/conf/global_settings.py
r4155 r4157 102 102 DATABASE_HOST = '' # Set to empty string for localhost. Not used with sqlite3. 103 103 DATABASE_PORT = '' # Set to empty string for default. Not used with sqlite3. 104 DATABASE_OPTIONS = {} # Set to empy dictionary for default. 104 105 105 106 # Optional named database connections in addition to the default. … … 232 233 TRANSACTIONS_MANAGED = False 233 234 235 # The User-Agent string to use when checking for URL validity through the 236 # isExistingURL validator. 237 URL_VALIDATOR_USER_AGENT = "Django/0.96pre (http://www.djangoproject.com)" 238 234 239 ############## 235 240 # MIDDLEWARE # django/branches/multiple-db-support/django/contrib/admin/media/js/dateparse.js
r2448 r4157 170 170 var d = new Date(); 171 171 d.setYear(parseInt(bits[1])); 172 d.setMonth(parseInt(bits[2], 10) - 1); 172 173 d.setDate(parseInt(bits[3], 10)); 173 d.setMonth(parseInt(bits[2], 10) - 1);174 174 return d; 175 175 } django/branches/multiple-db-support/django/contrib/admin/templatetags/admin_modify.py
r4155 r4157 178 178 179 179 def auto_populated_field_script(auto_pop_fields, change = False): 180 t = [] 180 181 for field in auto_pop_fields: 181 t = []182 182 if change: 183 183 t.append('document.getElementById("id_%s")._changed = true;' % field.name) django/branches/multiple-db-support/django/contrib/comments/models.py
r3427 r4157 35 35 Given a rating_string, this returns a tuple of (rating_range, options). 36 36 >>> s = "scale:1-10|First_category|Second_category" 37 >>> get_rating_options(s)37 >>> Comment.objects.get_rating_options(s) 38 38 ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], ['First category', 'Second category']) 39 39 """ django/branches/multiple-db-support/django/core/management.py
r4156 r4157 186 186 get_sql_reset.help_doc = "Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given app name(s)." 187 187 get_sql_reset.args = APP_ARGS 188 189 def get_sql_initial_data_for_model(model): 190 from django.db import models 191 from django.conf import settings 192 193 opts = model._meta 194 app_dir = os.path.normpath(os.path.join(os.path.dirname(models.get_app(model._meta.app_label).__file__), 'sql')) 195 output = [] 196 197 # Some backends can't execute more than one SQL statement at a time, 198 # so split into separate statements. 199 statements = re.compile(r";[ \t]*$", re.M) 200 201 # Find custom SQL, if it's available. 202 sql_files = [os.path.join(app_dir, "%s.%s.sql" % (opts.object_name.lower(), settings.DATABASE_ENGINE)), 203 os.path.join(app_dir, "%s.sql" % opts.object_name.lower())] 204 for sql_file in sql_files: 205 if os.path.exists(sql_file): 206 fp = open(sql_file, 'U') 207 for statement in statements.split(fp.read()): 208 # Remove any comments from the file 209 statement = re.sub(r"--.*[\n\Z]", "", statement) 210 if statement.strip(): 211 output.append(statement + ";") 212 fp.close() 213 214 return output 188 215 189 216 def get_sql_initial_data(app): django/branches/multiple-db-support/django/core/paginator.py
r3427 r4157 1 from math import ceil2 3 1 class InvalidPage(Exception): 4 2 pass … … 6 4 class ObjectPaginator(object): 7 5 """ 8 This class makes pagination easy. Feed it a QuerySet , plus the number of9 o bjects you want on each page. Then read the hits and pages properties to6 This class makes pagination easy. Feed it a QuerySet or list, plus the number 7 of objects you want on each page. Then read the hits and pages properties to 10 8 see how many pages it involves. Call get_page with a page number (starting 11 9 at 0) to get back a list of objects for that page. … … 13 11 Finally, check if a page number has a next/prev page using 14 12 has_next_page(page_number) and has_previous_page(page_number). 13 14 Use orphans to avoid small final pages. For example: 15 13 records, num_per_page=10, orphans=2 --> pages==2, len(self.get_page(0))==10 16 12 records, num_per_page=10, orphans=2 --> pages==1, len(self.get_page(0))==12 15 17 """ 16 def __init__(self, query_set, num_per_page ):18 def __init__(self, query_set, num_per_page, orphans=0): 17 19 self.query_set = query_set 18 20 self.num_per_page = num_per_page 19 self. _hits, self._pages = None, None20 self._h as_next = {} # Caches page_number -> has_next_boolean21 self.orphans = orphans 22 self._hits = self._pages = None 21 23 22 def get_page(self, page_number):24 def validate_page_number(self, page_number): 23 25 try: 24 26 page_number = int(page_number) 25 27 except ValueError: 26 28 raise InvalidPage 27 if page_number < 0 :29 if page_number < 0 or page_number > self.pages - 1: 28 30 raise InvalidPage 31 return page_number 29 32 30 # Retrieve one extra record, and check for the existence of that extra 31 # record to determine whether there's a next page. 32 limit = self.num_per_page + 1 33 offset = page_number * self.num_per_page 34 35 object_list = list(self.query_set[offset:offset+limit]) 36 37 if not object_list: 38 raise InvalidPage 39 40 self._has_next[page_number] = (len(object_list) > self.num_per_page) 41 return object_list[:self.num_per_page] 33 def get_page(self, page_number): 34 page_number = self.validate_page_number(page_number) 35 bottom = page_number * self.num_per_page 36 top = bottom + self.num_per_page 37 if top + self.orphans >= self.hits: 38 top = self.hits 39 return self.query_set[bottom:top] 42 40 43 41 def has_next_page(self, page_number): 44 42 "Does page $page_number have a 'next' page?" 45 if not self._has_next.has_key(page_number): 46 if self._pages is None: 47 offset = (page_number + 1) * self.num_per_page 48 self._has_next[page_number] = len(self.query_set[offset:offset+1]) > 0 49 else: 50 self._has_next[page_number] = page_number < (self.pages - 1) 51 return self._has_next[page_number] 43 return page_number < self.pages - 1 52 44 53 45 def has_previous_page(self, page_number): … … 59 51 relative to total objects found (hits). 60 52 """ 61 if page_number == 0: 62 return 1 53 page_number = self.validate_page_number(page_number) 63 54 return (self.num_per_page * page_number) + 1 64 55 … … 68 59 relative to total objects found (hits). 69 60 """ 70 if page_number == 0 and self.num_per_page >= self._hits:71 return self._hits72 elif page_number == (self._pages - 1) and (page_number + 1) * self.num_per_page > self._hits:73 return self. _hits74 return (page_number + 1)* self.num_per_page61 page_number = self.validate_page_number(page_number) 62 page_number += 1 # 1-base 63 if page_number == self.pages: 64 return self.hits 65 return page_number * self.num_per_page 75 66 76 67 def _get_hits(self): 77 68 if self._hits is None: 78 self._hits = self.query_set.count() 69 # Try .count() or fall back to len(). 70 try: 71 self._hits = int(self.query_set.count()) 72 except (AttributeError, TypeError, ValueError): 73 # AttributeError if query_set has no object count. 74 # TypeError if query_set.count() required arguments. 75 # ValueError if int() fails. 76 self._hits = len(self.query_set) 79 77 return self._hits 80 78 81 79 def _get_pages(self): 82 80 if self._pages is None: 83 self._pages = int(ceil(self.hits / float(self.num_per_page))) 81 hits = (self.hits - 1 - self.orphans) 82 if hits < 1: 83 hits = 0 84 self._pages = hits // self.num_per_page + 1 84 85 return self._pages 85 86 django/branches/multiple-db-support/django/core/serializers/base.py
r3712 r4157 29 29 30 30 self.stream = options.get("stream", StringIO()) 31 self.selected_fields = options.get("fields") 31 32 32 33 self.start_serialization() … … 37 38 continue 38 39 elif field.rel is None: 39 self.handle_field(obj, field) 40 if self.selected_fields is None or field.attname in self.selected_fields: 41 self.handle_field(obj, field) 40 42 else: 41 self.handle_fk_field(obj, field) 43 if self.selected_fields is None or field.attname[:-3] in self.selected_fields: 44 self.handle_fk_field(obj, field) 42 45 for field in obj._meta.many_to_many: 43 self.handle_m2m_field(obj, field) 46 if self.selected_fields is None or field.attname in self.selected_fields: 47 self.handle_m2m_field(obj, field) 44 48 self.end_object(obj) 45 49 self.end_serialization() django/branches/multiple-db-support/django/core/serializers/python.py
r3427 r4157 77 77 78 78 # Handle FK fields 79 elif field.rel and isinstance(field.rel, models.ManyToOneRel) :79 elif field.rel and isinstance(field.rel, models.ManyToOneRel) and field_value is not None: 80 80 try: 81 81 data[field.name] = field.rel.to._default_manager.get(pk=field_value) django/branches/multiple-db-support/django/core/serializers/xml_serializer.py
r3258 r4157 167 167 # validation error, but that's expected). 168 168 RelatedModel = self._get_model_from_node(node, "to") 169 return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding)) 169 # Check if there is a child node named 'None', returning None if so. 170 if len(node.childNodes) == 1 and node.childNodes[0].nodeName == 'None': 171 return None 172 else: 173 return RelatedModel.objects.get(pk=getInnerText(node).strip().encode(self.encoding)) 170 174 171 175 def _handle_m2m_field_node(self, node): django/branches/multiple-db-support/django/core/servers/fastcgi.py
r4156 r4157 34 34 maxrequests=NUMBER number of requests a child handles before it is 35 35 killed and a new child is forked (0 = no limit). 36 maxspare=NUMBER max number of spare processes to keep running.37 minspare=NUMBER min number of spare processes to prefork.38 maxchildren=NUMBER hard limit number of processes in prefork mode.36 maxspare=NUMBER max number of spare processes / threads 37 minspare=NUMBER min number of spare processes / threads. 38 maxchildren=NUMBER hard limit number of processes / threads 39 39 daemonize=BOOL whether to detach from terminal. 40 40 pidfile=FILE write the spawned process-id to this file. … … 111 111 elif options['method'] in ('thread', 'threaded'): 112 112 from flup.server.fcgi import WSGIServer 113 wsgi_opts = {} 113 wsgi_opts = { 114 'maxSpare': int(options["maxspare"]), 115 'minSpare': int(options["minspare"]), 116 'maxThreads': int(options["maxchildren"]), 117 } 114 118 else: 115 119 return fastcgi_help("ERROR: Implementation must be one of prefork or thread.") django/branches/multiple-db-support/django/core/urlresolvers.py
r4156 r4157 22 22 # Converts 'django.views.news.stories.story_detail' to 23 23 # ['django.views.news.stories', 'story_detail'] 24 dot = callback.rindex('.') 24 try: 25 dot = callback.rindex('.') 26 except ValueError: 27 return callback, '' 25 28 return callback[:dot], callback[dot+1:] 26 29 django/branches/multiple-db-support/django/core/validators.py
r4142 r4157 9 9 """ 10 10 11 import urllib2 11 12 from django.conf import settings 12 13 from django.utils.translation import gettext, gettext_lazy, ngettext … … 224 225 225 226 def isExistingURL(field_data, all_data): 226 import urllib2 227 try: 228 u = urllib2.urlopen(field_data) 227 try: 228 headers = { 229 "Accept" : "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", 230 "Accept-Language" : "en-us,en;q=0.5", 231 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", 232 "Connection" : "close", 233 "User-Agent": settings.URL_VALIDATOR_USER_AGENT 234 } 235 req = urllib2.Request(field_data,None, headers) 236 u = urllib2.urlopen(req) 229 237 except ValueError: 230 raise ValidationError, gettext("Invalid URL: %s") % field_data238 raise ValidationError, _("Invalid URL: %s") % field_data 231 239 except urllib2.HTTPError, e: 232 240 # 401s are valid; they just mean authorization is required. 233 if e.code not in ('401',): 234 raise ValidationError, gettext("The URL %s is a broken link.") % field_data 241 # 301 and 302 are redirects; they just mean look somewhere else. 242 if str(e.code) not in ('401','301','302'): 243 raise ValidationError, _("The URL %s is a broken link.") % field_data 235 244 except: # urllib2.URLError, httplib.InvalidURL, etc. 236 raise ValidationError, gettext("The URL %s is a broken link.") % field_data237 245 raise ValidationError, _("The URL %s is a broken link.") % field_data 246 238 247 def isValidUSState(field_data, all_data): 239 248 "Checks that the given string is a valid two-letter U.S. state abbreviation" … … 344 353 if field_name != self.field_name and value == field_data: 345 354 raise ValidationError, self.error_message 355 356 class NumberIsInRange(object): 357 """ 358 Validator that tests if a value is in a range (inclusive). 359 """ 360 def __init__(self, lower=None, upper=None, error_message=''): 361 self.lower, self.upper = lower, upper 362 if not error_message: 363 if lower and upper: 364 self.error_message = gettext("This value must be between %s and %s.") % (lower, upper) 365 elif lower: 366 self.error_message = gettext("This value must be at least %s.") % lower 367 elif upper: 368 self.error_message = gettext("This value must be no more than %s.") % upper 369 else: 370 self.error_message = error_message 371 372 def __call__(self, field_data, all_data): 373 # Try to make the value numeric. If this fails, we assume another 374 # validator will catch the problem. 375 try: 376 val = float(field_data) 377 except ValueError: 378 return 379 380 # Now validate 381 if self.lower and self.upper and (val < self.lower or val > self.upper): 382 raise ValidationError(self.error_message) 383 elif self.lower and val < self.lower: 384 raise ValidationError(self.error_message) 385 elif self.upper and val > self.upper: 386 raise ValidationError(self.error_message) 346 387 347 388 class IsAPowerOf(object): django/branches/multiple-db-support/django/db/backends/ado_mssql/base.py
r4127 r4157 51 51 def __init__(self, settings): 52 52 self.settings = settings 53 self.options = settings.DATABASE_OPTIONS 53 54 self.connection = None 54 55 self.queries = [] django/branches/multiple-db-support/django/db/backends/ansi/sql.py
r4142 r4157 292 292 else: 293 293 for statement in statements.split(fp.read()): 294 # Remove any comments from the file 295 statement = re.sub(r"--.*[\n\Z]", "", statement) 294 296 if statement.strip(): 295 297 output.append(BoundStatement(statement + ";", django/branches/multiple-db-support/django/db/backends/mysql/base.py
r4151 r4157 65 65 self.queries = [] 66 66 self.server_version = None 67 self.options = settings.DATABASE_OPTIONS 67 68 68 69 def _valid_connection(self): … … 91 92 if settings.DATABASE_PORT: 92 93 kwargs['port'] = int(settings.DATABASE_PORT) 94 kwargs.update(self.options) 93 95 self.connection = Database.connect(**kwargs) 94 96 cursor = self.connection.cursor() django/branches/multiple-db-support/django/db/backends/oracle/base.py
r4127 r4157 19 19 self.connection = None 20 20 self.queries = [] 21 self.options = settings.DATABASE_OPTIONS 21 22 22 23 def _valid_connection(self): … … 30 31 if len(settings.DATABASE_PORT.strip()) != 0: 31 32 dsn = Database.makedsn(settings.DATABASE_HOST, int(settings.DATABASE_PORT), settings.DATABASE_NAME) 32 self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn )33 self.connection = Database.connect(settings.DATABASE_USER, settings.DATABASE_PASSWORD, dsn, **self.options) 33 34 else: 34 35 conn_string = "%s/%s@%s" % (settings.DATABASE_USER, settings.DATABASE_PASSWORD, settings.DATABASE_NAME) 35 self.connection = Database.connect(conn_string )36 self.connection = Database.connect(conn_string, **self.options) 36 37 return FormatStylePlaceholderCursor(self.connection) 37 38 django/branches/multiple-db-support/django/db/backends/postgresql/base.py
r4127 r4157 19 19 self.connection = None 20 20 self.queries = [] 21 self.options = settings.DATABASE_OPTIONS 21 22 22 23 def cursor(self): … … 35 36 if settings.DATABASE_PORT: 36 37 conn_string += " port=%s" % settings.DATABASE_PORT 37 self.connection = Database.connect(conn_string )38 self.connection = Database.connect(conn_string, **self.options) 38 39 self.connection.set_isolation_level(1) # make transactions transparent to all cursors 39 40 cursor = self.connection.cursor() django/branches/multiple-db-support/django/db/backends/postgresql_psycopg2/base.py
r4127 r4157 19 19 self.connection = None 20 20 self.queries = [] 21 self.options = settings.DATABASE_OPTIONS 21 22 22 23 def cursor(self): … … 35 36 if settings.DATABASE_PORT: 36 37 conn_string += " port=%s" % settings.DATABASE_PORT 37 self.connection = Database.connect(conn_string )38 self.connection = Database.connect(conn_string, **self.options) 38 39 self.connection.set_isolation_level(1) # make transactions transparent to all cursors 39 40 cursor = self.connection.cursor() django/branches/multiple-db-support/django/db/backends/sqlite3/base.py
r4141 r4157 47 47 self.connection = None 48 48 self.queries = [] 49 self.options = settings.DATABASE_OPTIONS 49 50 50 51 def cursor(self): 51 52 settings = self.settings 52 53 if self.connection is None: 53 self.connection = Database.connect(settings.DATABASE_NAME, 54 detect_types=Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES) 55 54 kwargs = { 55 'database': settings.DATABASE_NAME, 56 'detect_types': Database.PARSE_DECLTYPES | Database.PARSE_COLNAMES, 57 } 58 kwargs.update(self.options) 59 self.connection = Database.connect(**kwargs) 56 60 # Register extract and date_trunc functions. 57 61 self.connection.create_function("django_extract", 2, _sqlite_extract) django/branches/multiple-db-support/django/db/backends/util.py
r4139 r4157 18 18 params = tuple(params) 19 19 self.db.queries.append({ 20 'sql': sql % tuple(params),20 'sql': sql % params, 21 21 'time': "%.3f" % (stop - start), 22 22 }) django/branches/multiple-db-support/django/db/__init__.py
r4156 r4157 29 29 if not settings.DATABASE_ENGINE: 30 30 settings.DATABASE_ENGINE = 'dummy' 31 31 32 32 33 33 def connect(settings, **kw): … … 49 49 if settings is None: 50 50 from django.conf import settings 51 if not settings.DATABASE_OPTIONS: 52 settings.DATABASE_OPTIONS = {} 51 53 self.settings = settings 52 54 self.backend = self.load_backend() django/branches/multiple-db-support/django/db/models/fields/__init__.py
r4156 r4157 592 592 def isWithinMediaRoot(field_data, all_data): 593 593 f = os.path.abspath(os.path.join(settings.MEDIA_ROOT, field_data)) 594 if not f.startswith(os.path. normpath(settings.MEDIA_ROOT)):594 if not f.startswith(os.path.abspath(os.path.normpath(settings.MEDIA_ROOT))): 595 595 raise validators.ValidationError, _("Enter a valid filename.") 596 596 field_list[1].validator_list.append(isWithinMediaRoot) django/branches/multiple-db-support/django/db/models/manipulators.py
r4155 r4157 287 287 # form fields, e.g. DateTime. 288 288 # This validation needs to occur after html2python to be effective. 289 field_val = all_data.get(f. attname, None)289 field_val = all_data.get(f.name, None) 290 290 if field_val is None: 291 291 # This will be caught by another validator, assuming the field django/branches/multiple-db-support/django/forms/__init__.py
r4142 r4157 109 109 prepopulated data and validation error messages to the formfield objects. 110 110 """ 111 def __init__(self, manipulator, data, error_dict, edit_inline=True): 112 self.manipulator, self.data = manipulator, data 111 def __init__(self, manipulator, data=None, error_dict=None, edit_inline=True): 112 self.manipulator = manipulator 113 if data is None: 114 data = {} 115 if error_dict is None: 116 error_dict = {} 117 self.data = data 113 118 self.error_dict = error_dict 114 119 self._inline_collections = None django/branches/multiple-db-support/django/newforms/fields.py
r4156 r4157 189 189 r'(?:/?|/\S+)$', re.IGNORECASE) 190 190 191 try: 192 from django.conf import settings 193 URL_VALIDATOR_USER_AGENT = settings.URL_VALIDATOR_USER_AGENT 194 except ImportError: 195 # It's OK if Django settings aren't configured. 196 URL_VALIDATOR_USER_AGENT = 'Django (http://www.djangoproject.com/)' 197 191 198 class URLField(RegexField): 192 def __init__(self, required=True, verify_exists=False, widget=None): 199 def __init__(self, required=True, verify_exists=False, widget=None, 200 validator_user_agent=URL_VALIDATOR_USER_AGENT): 193 201 RegexField.__init__(self, url_re, u'Enter a valid URL.', required, widget) 194 202 self.verify_exists = verify_exists 203 self.user_agent = validator_user_agent 195 204 196 205 def clean(self, value): … … 198 207 if self.verify_exists: 199 208 import urllib2 209 from django.conf import settings 210 headers = { 211 "Accept": "text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5", 212 "Accept-Language": "en-us,en;q=0.5", 213 "Accept-Charset": "ISO-8859-1,utf-8;q=0.7,*;q=0.7", 214 "Connection": "close", 215 "User-Agent": self.user_agent, 216 } 200 217 try: 201 u = urllib2.urlopen(value) 218 req = urllib2.Request(field_data, None, headers) 219 u = urllib2.urlopen(req) 202 220 except ValueError: 203 221 raise ValidationError(u'Enter a valid URL.') django/branches/multiple-db-support/django/template/defaultfilters.py
r4139 r4157 422 422 bytes, etc). 423 423 """ 424 bytes = float(bytes) 424 try: 425 bytes = float(bytes) 426 except TypeError: 427 return "0 bytes" 428 425 429 if bytes < 1024: 426 430 return "%d byte%s" % (bytes, bytes != 1 and 's' or '') django/branches/multiple-db-support/django/template/defaulttags.py
r4155 r4157 125 125 126 126 class IfChangedNode(Node): 127 def __init__(self, nodelist ):127 def __init__(self, nodelist, *varlist): 128 128 self.nodelist = nodelist 129 129 self._last_seen = None 130 self._varlist = varlist 130 131 131 132 def render(self, context): 132 133 if context.has_key('forloop') and context['forloop']['first']: 133 134 self._last_seen = None 134 content = self.nodelist.render(context) 135 if content != self._last_seen: 135 try: 136 if self._varlist: 137 # Consider multiple parameters. 138 # This automatically behaves like a OR evaluation of the multiple variables. 139 compare_to = [resolve_variable(var, context) for var in self._varlist] 140 else: 141 compare_to = self.nodelist.render(context) 142 except VariableDoesNotExist: 143 compare_to = None 144 145 if compare_to != self._last_seen: 136 146 firstloop = (self._last_seen == None) 137 self._last_seen = co ntent147 self._last_seen = compare_to 138 148 context.push() 139 149 context['ifchanged'] = {'firstloop': firstloop} … … 635 645 Check if a value has changed from the last iteration of a loop. 636 646 637 The 'ifchanged' block tag is used within a loop. It checks its own rendered 638 contents against its previous state and only displays its content if the 639 value has changed:: 640 641 <h1>Archive for {{ year }}</h1> 642 643 {% for date in days %} 644 {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %} 645 <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> 646 {% endfor %} 647 The 'ifchanged' block tag is used within a loop. It has two possible uses. 648 649 1. Checks its own rendered contents against its previous state and only 650 displays the content if it has changed. For example, this displays a list of 651 days, only displaying the month if it changes:: 652 653 <h1>Archive for {{ year }}</h1> 654 655 {% for date in days %} 656 {% ifchanged %}<h3>{{ date|date:"F" }}</h3>{% endifchanged %} 657 <a href="{{ date|date:"M/d"|lower }}/">{{ date|date:"j" }}</a> 658 {% endfor %} 659 660 2. If given a variable, check if that variable has changed. For example, the 661 following shows the date every time it changes, but only shows the hour if both 662 the hour and the date has changed:: 663 664 {% for date in days %} 665 {% ifchanged date.date %} {{date.date}} {% endifchanged %} 666 {% ifchanged date.hour date.date %} 667 {{date.hour}} 668 {% endifchanged %} 669 {% endfor %} 647 670 """ 648 671 bits = token.contents.split() 649 if len(bits) != 1:650 raise TemplateSyntaxError, "'ifchanged' tag takes no arguments"651 672 nodelist = parser.parse(('endifchanged',)) 652 673 parser.delete_first_token() 653 return IfChangedNode(nodelist )674 return IfChangedNode(nodelist, *bits[1:]) 654 675 ifchanged = register.tag(ifchanged) 655 676 django/branches/multiple-db-support/django/template/__init__.py
r4156 r4157 869 869 870 870 if not getattr(self, 'nodelist', False): 871 from django.template.loader import get_template 872 t = get_template(file_name) 871 from django.template.loader import get_template, select_template 872 if hasattr(file_name, '__iter__'): 873 t = select_template(file_name) 874 else: 875 t = get_template(file_name) 873 876 self.nodelist = t.nodelist 874 877 return self.nodelist.render(context_class(dict))
