Changeset 6021
- Timestamp:
- 08/26/07 12:47:34 (1 year ago)
- Files:
-
- django/branches/gis (modified) (1 prop)
- django/branches/gis/AUTHORS (modified) (1 diff)
- django/branches/gis/django/contrib/admin/media/js/SelectBox.js (modified) (4 diffs)
- django/branches/gis/django/contrib/auth/views.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/tests/test_spatialrefsys.py (modified) (1 diff)
- django/branches/gis/django/core/management/commands/flush.py (modified) (1 diff)
- django/branches/gis/django/core/management/commands/runserver.py (modified) (2 diffs)
- django/branches/gis/django/core/management/commands/sqlflush.py (modified) (1 diff)
- django/branches/gis/django/core/management/sql.py (modified) (2 diffs)
- django/branches/gis/django/db/backends/dummy/base.py (modified) (2 diffs)
- django/branches/gis/django/db/backends/postgresql/base.py (modified) (1 diff)
- django/branches/gis/django/db/backends/postgresql/operations.py (modified) (2 diffs)
- django/branches/gis/django/db/backends/postgresql_psycopg2/base.py (modified) (1 diff)
- django/branches/gis/django/template/defaultfilters.py (modified) (2 diffs)
- django/branches/gis/docs/db-api.txt (modified) (1 diff)
- django/branches/gis/docs/django-admin.txt (modified) (5 diffs)
- django/branches/gis/docs/faq.txt (modified) (1 diff)
- django/branches/gis/docs/model-api.txt (modified) (1 diff)
- django/branches/gis/docs/newforms.txt (modified) (1 diff)
- django/branches/gis/docs/settings.txt (modified) (1 diff)
- django/branches/gis/docs/templates.txt (modified) (2 diffs)
- django/branches/gis/docs/tutorial01.txt (modified) (2 diffs)
- django/branches/gis/tests/regressiontests/defaultfilters/tests.py (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis
- Property svnmerge-integrated changed from /django/trunk:1-6000 to /django/trunk:1-6020
django/branches/gis/AUTHORS
r6018 r6021 95 95 deric@monowerks.com 96 96 Max Derkachev <mderk@yandex.ru> 97 Sander Dijkhuis <sander.dijkhuis@gmail.com> 97 98 Jordan Dimov <s3x3y1@gmail.com> 98 99 dne@mayonnaise.net django/branches/gis/django/contrib/admin/media/js/SelectBox.js
r450 r6021 7 7 var cache = SelectBox.cache[id]; 8 8 for (var i = 0; (node = box.options[i]); i++) { 9 cache.push({ value: node.value, text: node.text, displayed: 1});9 cache.push({value: node.value, text: node.text, displayed: 1}); 10 10 } 11 11 }, … … 51 51 }, 52 52 add_to_cache: function(id, option) { 53 SelectBox.cache[id].push({ value: option.value, text: option.text, displayed: 1});53 SelectBox.cache[id].push({value: option.value, text: option.text, displayed: 1}); 54 54 }, 55 55 cache_contains: function(id, value) { … … 69 69 for (var i = 0; (option = from_box.options[i]); i++) { 70 70 if (option.selected && SelectBox.cache_contains(from, option.value)) { 71 SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1});71 SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 72 72 SelectBox.delete_from_cache(from, option.value); 73 73 } … … 81 81 var option; 82 82 for (var i = 0; (option = from_box.options[i]); i++) { 83 SelectBox.add_to_cache(to, { value: option.value, text: option.text, displayed: 1 }); 84 SelectBox.delete_from_cache(from, option.value); 83 if (SelectBox.cache_contains(from, option.value)) { 84 SelectBox.add_to_cache(to, {value: option.value, text: option.text, displayed: 1}); 85 SelectBox.delete_from_cache(from, option.value); 86 } 85 87 } 86 88 SelectBox.redisplay(from); django/branches/gis/django/contrib/auth/views.py
r6018 r6021 18 18 if not errors: 19 19 # Light security check -- make sure redirect_to isn't garbage. 20 if not redirect_to or ' ://' in redirect_to or ' ' in redirect_to:20 if not redirect_to or '//' in redirect_to or ' ' in redirect_to: 21 21 from django.conf import settings 22 22 redirect_to = settings.LOGIN_REDIRECT_URL django/branches/gis/django/contrib/gis/tests/test_spatialrefsys.py
r6018 r6021 52 52 def test03_ellipsoid(self): 53 53 "Testing the ellipsoid property." 54 return55 54 for sd in test_srs: 56 55 # Getting the ellipsoid and precision parameters. django/branches/gis/django/core/management/commands/flush.py
r6018 r6021 25 25 pass 26 26 27 sql_list = sql_flush(self.style )27 sql_list = sql_flush(self.style, only_django=True) 28 28 29 29 if interactive: django/branches/gis/django/core/management/commands/runserver.py
r6018 r6021 31 31 32 32 use_reloader = options.get('use_reloader', True) 33 admin_media_ dir = options.get('admin_media_dir', '')33 admin_media_path = options.get('admin_media_path', '') 34 34 shutdown_message = options.get('shutdown_message', '') 35 35 quit_command = (sys.platform == 'win32') and 'CTRL-BREAK' or 'CONTROL-C' … … 43 43 print "Quit the server with %s." % quit_command 44 44 try: 45 path = admin_media_ diror django.__path__[0] + '/contrib/admin/media'45 path = admin_media_path or django.__path__[0] + '/contrib/admin/media' 46 46 handler = AdminMediaHandler(WSGIHandler(), path) 47 47 run(addr, int(port), handler) django/branches/gis/django/core/management/commands/sqlflush.py
r6018 r6021 8 8 def handle_noargs(self, **options): 9 9 from django.core.management.sql import sql_flush 10 return '\n'.join(sql_flush(self.style ))10 return '\n'.join(sql_flush(self.style, only_django=True)) django/branches/gis/django/core/management/sql.py
r6018 r6021 13 13 cursor = connection.cursor() 14 14 return get_introspection_module().get_table_list(cursor) 15 16 def django_table_list(only_existing=False): 17 """ 18 Returns a list of all table names that have associated Django models and 19 are in INSTALLED_APPS. 20 21 If only_existing is True, the resulting list will only include the tables 22 that actually exist in the database. 23 """ 24 from django.db import models 25 tables = [] 26 for app in models.get_apps(): 27 for model in models.get_models(app): 28 tables.append(model._meta.db_table) 29 tables.extend([f.m2m_db_table() for f in model._meta.many_to_many]) 30 if only_existing: 31 existing = table_list() 32 tables = [t for t in tables if t in existing] 33 return tables 15 34 16 35 def installed_models(table_list): … … 182 201 return sql_delete(app, style) + sql_all(app, style) 183 202 184 def sql_flush(style): 185 "Returns a list of the SQL statements used to flush the database." 203 def sql_flush(style, only_django=False): 204 """ 205 Returns a list of the SQL statements used to flush the database. 206 207 If only_django is True, then only table names that have associated Django 208 models and are in INSTALLED_APPS will be included. 209 """ 186 210 from django.db import connection 187 statements = connection.ops.sql_flush(style, table_list(), sequence_list()) 211 if only_django: 212 tables = django_table_list() 213 else: 214 tables = table_list() 215 statements = connection.ops.sql_flush(style, tables, sequence_list()) 188 216 return statements 189 217 django/branches/gis/django/db/backends/dummy/base.py
r6018 r6021 9 9 10 10 from django.core.exceptions import ImproperlyConfigured 11 from django.db.backends import BaseDatabaseFeatures, BaseDatabaseOperations 11 12 12 13 def complain(*args, **kwargs): … … 22 23 pass 23 24 24 class ComplainOnGetattr(object): 25 def __getattr__(self, *args, **kwargs): 26 complain() 25 class DatabaseOperations(BaseDatabaseOperations): 26 quote_name = complain 27 27 28 28 class DatabaseWrapper(object): 29 features = ComplainOnGetattr()30 ops = ComplainOnGetattr()29 features = BaseDatabaseFeatures() 30 ops = DatabaseOperations() 31 31 operators = {} 32 32 cursor = complain django/branches/gis/django/db/backends/postgresql/base.py
r6018 r6021 103 103 cursor.execute("SET client_encoding to 'UNICODE'") 104 104 cursor = UnicodeCursorWrapper(cursor, 'utf-8') 105 if self.ops.postgres_version is None:106 cursor.execute("SELECT version()")107 self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]108 105 return cursor 109 106 django/branches/gis/django/db/backends/postgresql/operations.py
r6018 r6021 5 5 6 6 class DatabaseOperations(BaseDatabaseOperations): 7 def __init__(self, postgres_version=None): 8 self.postgres_version = postgres_version 7 def __init__(self): 8 self._postgres_version = None 9 10 def _get_postgres_version(self): 11 if self._postgres_version is None: 12 from django.db import connection 13 cursor = connection.cursor() 14 cursor.execute("SELECT version()") 15 self._postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')] 16 return self._postgres_version 17 postgres_version = property(_get_postgres_version) 9 18 10 19 def date_extract_sql(self, lookup_type, field_name): … … 53 62 table_name = sequence_info['table'] 54 63 column_name = sequence_info['column'] 55 if column_name and len(column_name)>0: 56 # sequence name in this case will be <table>_<column>_seq 57 sql.append("%s %s %s %s %s %s;" % \ 58 (style.SQL_KEYWORD('ALTER'), 59 style.SQL_KEYWORD('SEQUENCE'), 60 style.SQL_FIELD(self.quote_name('%s_%s_seq' % (table_name, column_name))), 61 style.SQL_KEYWORD('RESTART'), 62 style.SQL_KEYWORD('WITH'), 63 style.SQL_FIELD('1') 64 ) 65 ) 64 if column_name and len(column_name) > 0: 65 sequence_name = '%s_%s_seq' % (table_name, column_name) 66 66 else: 67 # sequence name in this case will be <table>_id_seq 68 sql.append("%s %s %s %s %s %s;" % \ 69 (style.SQL_KEYWORD('ALTER'), 70 style.SQL_KEYWORD('SEQUENCE'), 71 style.SQL_FIELD(self.quote_name('%s_id_seq' % table_name)), 72 style.SQL_KEYWORD('RESTART'), 73 style.SQL_KEYWORD('WITH'), 74 style.SQL_FIELD('1') 75 ) 76 ) 67 sequence_name = '%s_id_seq' % table_name 68 sql.append("%s setval('%s', 1, false);" % \ 69 (style.SQL_KEYWORD('SELECT'), 70 style.SQL_FIELD(self.quote_name(sequence_name))) 71 ) 77 72 return sql 78 73 else: django/branches/gis/django/db/backends/postgresql_psycopg2/base.py
r6018 r6021 65 65 if set_tz: 66 66 cursor.execute("SET TIME ZONE %s", [settings.TIME_ZONE]) 67 if self.ops.postgres_version is None:68 cursor.execute("SELECT version()")69 self.ops.postgres_version = [int(val) for val in cursor.fetchone()[0].split()[1].split('.')]70 67 return cursor django/branches/gis/django/template/defaultfilters.py
r6018 r6021 356 356 WITHOUT opening and closing <ul> tags. 357 357 358 The list is assumed to be in the proper format. For example, if ``var`` contains359 ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,358 The list is assumed to be in the proper format. For example, if ``var`` 359 contains: ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, 360 360 then ``{{ var|unordered_list }}`` would return:: 361 361 … … 372 372 </li> 373 373 """ 374 def _helper(value, tabs): 374 def convert_old_style_list(list_): 375 """ 376 Converts old style lists to the new easier to understand format. 377 378 The old list format looked like: 379 ['Item 1', [['Item 1.1', []], ['Item 1.2', []]] 380 381 And it is converted to: 382 ['Item 1', ['Item 1.1', 'Item 1.2]] 383 """ 384 if not isinstance(list_, (tuple, list)) or len(list_) != 2: 385 return list_, False 386 first_item, second_item = list_ 387 if second_item == []: 388 return [first_item], True 389 old_style_list = True 390 new_second_item = [] 391 for sublist in second_item: 392 item, old_style_list = convert_old_style_list(sublist) 393 if not old_style_list: 394 break 395 new_second_item.extend(item) 396 if old_style_list: 397 second_item = new_second_item 398 return [first_item, second_item], old_style_list 399 def _helper(list_, tabs=1): 375 400 indent = u'\t' * tabs 376 if value[1]: 377 return u'%s<li>%s\n%s<ul>\n%s\n%s</ul>\n%s</li>' % (indent, force_unicode(value[0]), indent, 378 u'\n'.join([_helper(v, tabs+1) for v in value[1]]), indent, indent) 379 else: 380 return u'%s<li>%s</li>' % (indent, force_unicode(value[0])) 381 return _helper(value, 1) 401 output = [] 402 403 list_length = len(list_) 404 i = 0 405 while i < list_length: 406 title = list_[i] 407 sublist = '' 408 sublist_item = None 409 if isinstance(title, (list, tuple)): 410 sublist_item = title 411 title = '' 412 elif i < list_length - 1: 413 next_item = list_[i+1] 414 if next_item and isinstance(next_item, (list, tuple)): 415 # The next item is a sub-list. 416 sublist_item = next_item 417 # We've processed the next item now too. 418 i += 1 419 if sublist_item: 420 sublist = _helper(sublist_item, tabs+1) 421 sublist = '\n%s<ul>\n%s\n%s</ul>\n%s' % (indent, sublist, 422 indent, indent) 423 output.append('%s<li>%s%s</li>' % (indent, force_unicode(title), 424 sublist)) 425 i += 1 426 return '\n'.join(output) 427 value, converted = convert_old_style_list(value) 428 return _helper(value) 382 429 383 430 ################### django/branches/gis/docs/db-api.txt
r6018 r6021 208 208 The ``save()`` method has no return value. 209 209 210 Updating ``ForeignKey`` fields works exactly the same way; simply assign an 211 object of the right type to the field in question:: 210 Saving ForeignKey and ManyToManyField fields 211 -------------------------------------------- 212 213 Updating ``ForeignKey`` fields works exactly the same way as saving a normal 214 field; simply assign an object of the right type to the field in question:: 215 216 cheese_blog = Blog.objects.get(name="Cheddar Talk") 217 entry.blog = cheese_blog 218 entry.save() 219 220 Updating a ``ManyToManyField`` works a little differently; use the ``add()`` 221 method on the field to add a record to the relation:: 212 222 213 223 joe = Author.objects.create(name="Joe") 214 entry.author = joe 215 entry.save() 216 217 Django will complain if you try to assign an object of the wrong type. 224 entry.authors.add(joe) 225 226 Django will complain if you try to assign or add an object of the wrong type. 218 227 219 228 How Django knows to UPDATE vs. INSERT django/branches/gis/docs/django-admin.txt
r6018 r6021 124 124 post-synchronization handlers will be re-executed, and the ``initial_data`` 125 125 fixture will be re-installed. 126 127 The behavior of this command has changed in the Django development version. 128 Previously, this command cleared *every* table in the database, including any 129 table that Django didn't know about (i.e., tables that didn't have associated 130 models and/or weren't in ``INSTALLED_APPS``). Now, the command only clears 131 tables that are represented by Django models and are activated in 132 ``INSTALLED_APPS``. 126 133 127 134 inspectdb … … 241 248 runfcgi [options] 242 249 ----------------- 250 243 251 Starts a set of FastCGI processes suitable for use with any web server 244 252 which supports the FastCGI protocol. See the `FastCGI deployment … … 338 346 339 347 sqlclear [appname appname ...] 340 ------------------------------ --------348 ------------------------------ 341 349 342 350 Prints the DROP TABLE SQL statements for the given appnames. … … 361 369 Note that the order in which the SQL files are processed is undefined. 362 370 371 sqlflush 372 -------- 373 374 Prints the SQL statements that would be executed for the `flush`_ command. 375 363 376 sqlindexes [appname appname ...] 364 -------------------------------- --------377 -------------------------------- 365 378 366 379 Prints the CREATE INDEX SQL statements for the given appnames. 367 380 368 381 sqlreset [appname appname ...] 382 ------------------------------ 383 384 Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames. 385 386 sqlsequencereset [appname appname ...] 369 387 -------------------------------------- 370 371 Prints the DROP TABLE SQL, then the CREATE TABLE SQL, for the given appnames.372 373 sqlsequencereset [appname appname ...]374 ----------------------------------------------375 388 376 389 Prints the SQL statements for resetting sequences for the given … … 467 480 not yet accept a ``host`` or ``port`` parameter. 468 481 482 Also note that it does *not* automatically detect changes to your Python source 483 code (as ``runserver`` does). It does, however, detect changes to templates. 484 469 485 .. _unit tests: ../testing/ 470 486 django/branches/gis/docs/faq.txt
r6018 r6021 205 205 spend a lot of energy creating screencasts yet, because Django APIs will shift. 206 206 207 In the meantime, though, check out this `unofficial Django screencast`_.208 209 .. _unofficial Django screencast: http://www.throwingbeans.org/django_screencasts.html210 211 207 Is Django a content-management-system (CMS)? 212 208 -------------------------------------------- django/branches/gis/docs/model-api.txt
r6018 r6021 345 345 ~~~~~~~~~~~~~~ 346 346 347 Like ` `FileField``, but validates that the uploaded object is a valid347 Like `FileField`_, but validates that the uploaded object is a valid 348 348 image. Has two extra optional arguments, ``height_field`` and 349 349 ``width_field``, which, if set, will be auto-populated with the height and django/branches/gis/docs/newforms.txt
r6018 r6021 1555 1555 def __init__(self, *args, **kwargs): 1556 1556 kwargs.setdefault('attrs',{}).update({'size': '40'}) 1557 super( forms.TextInput, self).__init__(*args, **kwargs)1557 super(CommentWidget, self).__init__(*args, **kwargs) 1558 1558 1559 1559 Then you can use this widget in your forms:: django/branches/gis/docs/settings.txt
r6018 r6021 1102 1102 ---------- 1103 1103 1104 When ``DEBUG`` is ``False`` and your ``MIDDLEWARE_CLASSES`` setting includes 1105 ``CommonMiddleware``, Django will e-mail the users listed in the ``MANAGERS`` 1106 setting whenever your code raises a 404 and the request has a referer. 1107 (It doesn't bother to e-mail for 404s that don't have a referer.) 1104 When ``DEBUG`` is ``False``, ``SEND_BROKEN_LINK_EMAILS`` is ``True`` and your 1105 ``MIDDLEWARE_CLASSES`` setting includes ``CommonMiddleware``, Django will 1106 e-mail the users listed in the ``MANAGERS`` setting whenever your code raises 1107 a 404 and the request has a referer. (It doesn't bother to e-mail for 404s 1108 that don't have a referer.) 1108 1109 1109 1110 You can tell Django to stop reporting particular 404s by tweaking the django/branches/gis/docs/templates.txt
r6018 r6021 1302 1302 WITHOUT opening and closing <ul> tags. 1303 1303 1304 **Changed in Django development version** 1305 1306 The format accepted by ``unordered_list`` has changed to an easier to 1307 understand format. 1308 1304 1309 The list is assumed to be in the proper format. For example, if ``var`` contains 1305 ``['States', [ ['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``,1306 then``{{ var|unordered_list }}`` would return::1310 ``['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]``, then 1311 ``{{ var|unordered_list }}`` would return:: 1307 1312 1308 1313 <li>States … … 1318 1323 </li> 1319 1324 1325 Note: the previous more restrictive and verbose format is still supported: 1326 ``['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]``, 1327 1320 1328 upper 1321 1329 ~~~~~ django/branches/gis/docs/tutorial01.txt
r6018 r6021 259 259 choice = models.CharField(max_length=200) 260 260 votes = models.IntegerField() 261 262 .. admonition:: Errors about ``max_length`` 263 264 If Django gives you an error message saying that ``max_length`` is 265 not a valid argument, you're most likely using an old version of 266 Django. (This version of the tutorial is written for the latest 267 development version of Django.) If you're using a Subversion checkout 268 of Django's development version (see `the installation docs`_ for 269 more information), you shouldn't have any problems. 270 271 If you want to stick with an older version of Django, you'll want to 272 switch to `the Django 0.96 tutorial`_, because this tutorial covers 273 several features that only exist in the Django development version. 274 275 .. _the installation docs: ../install/ 276 .. _the Django 0.96 tutorial: ../0.96/tutorial01/ 261 277 262 278 The code is straightforward. Each model is represented by a class that … … 488 504 return self.choice 489 505 506 .. admonition:: If ``__unicode__()`` doesn't seem to work 507 508 If you add the ``__unicode__()`` method to your models and don't 509 see any change in how they're represented, you're most likely using 510 an old version of Django. (This version of the tutorial is written 511 for the latest development version of Django.) If you're using a 512 Subversion checkout of of Django's development version (see `the 513 installation docs`_ for more information), you shouldn't have any 514 problems. 515 516 If you want to stick with an older version of Django, you'll want to 517 switch to `the Django 0.96 tutorial`_, because this tutorial covers 518 several features that only exist in the Django development version. 519 520 .. _the installation docs: ../install/ 521 .. _the Django 0.96 tutorial: ../0.96/tutorial01/ 522 490 523 It's important to add ``__unicode__()`` methods to your models, not only for 491 524 your own sanity when dealing with the interactive prompt, but also because django/branches/gis/tests/regressiontests/defaultfilters/tests.py
r6018 r6021 267 267 u'aceg' 268 268 269 >>> unordered_list([u'item 1', u'item 2']) 270 u'\t<li>item 1</li>\n\t<li>item 2</li>' 271 272 >>> unordered_list([u'item 1', [u'item 1.1']]) 273 u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t</ul>\n\t</li>' 274 275 >>> unordered_list([u'item 1', [u'item 1.1', u'item1.2'], u'item 2']) 276 u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item1.2</li>\n\t</ul>\n\t</li>\n\t<li>item 2</li>' 277 278 >>> unordered_list([u'item 1', [u'item 1.1', [u'item 1.1.1', [u'item 1.1.1.1']]]]) 279 u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1\n\t\t<ul>\n\t\t\t<li>item 1.1.1\n\t\t\t<ul>\n\t\t\t\t<li>item 1.1.1.1</li>\n\t\t\t</ul>\n\t\t\t</li>\n\t\t</ul>\n\t\t</li>\n\t</ul>\n\t</li>' 280 281 >>> unordered_list(['States', ['Kansas', ['Lawrence', 'Topeka'], 'Illinois']]) 282 u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>' 283 284 # Old format for unordered lists should still work 269 285 >>> unordered_list([u'item 1', []]) 270 286 u'\t<li>item 1</li>' … … 275 291 >>> unordered_list([u'item 1', [[u'item 1.1', []], [u'item 1.2', []]]]) 276 292 u'\t<li>item 1\n\t<ul>\n\t\t<li>item 1.1</li>\n\t\t<li>item 1.2</li>\n\t</ul>\n\t</li>' 293 294 >>> unordered_list(['States', [['Kansas', [['Lawrence', []], ['Topeka', []]]], ['Illinois', []]]]) 295 u'\t<li>States\n\t<ul>\n\t\t<li>Kansas\n\t\t<ul>\n\t\t\t<li>Lawrence</li>\n\t\t\t<li>Topeka</li>\n\t\t</ul>\n\t\t</li>\n\t\t<li>Illinois</li>\n\t</ul>\n\t</li>' 277 296 278 297 >>> add(u'1', u'2')
