mirror of
				https://github.com/django/django.git
				synced 2025-10-31 09:41:08 +00:00 
			
		
		
		
	[soc2009/multidb] Merged up to trunk r11917.
git-svn-id: http://code.djangoproject.com/svn/django/branches/soc2009/multidb@11920 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -353,6 +353,13 @@ class ModelAdmin(BaseModelAdmin): | ||||
|         defaults.update(kwargs) | ||||
|         return modelform_factory(self.model, **defaults) | ||||
|  | ||||
|     def get_changelist(self, request, **kwargs): | ||||
|         """ | ||||
|         Returns the ChangeList class for use on the changelist page. | ||||
|         """ | ||||
|         from django.contrib.admin.views.main import ChangeList | ||||
|         return ChangeList | ||||
|  | ||||
|     def get_changelist_form(self, request, **kwargs): | ||||
|         """ | ||||
|         Returns a Form class for use in the Formset on the changelist page. | ||||
| @@ -896,7 +903,7 @@ class ModelAdmin(BaseModelAdmin): | ||||
|     @csrf_protect | ||||
|     def changelist_view(self, request, extra_context=None): | ||||
|         "The 'change list' admin view for this model." | ||||
|         from django.contrib.admin.views.main import ChangeList, ERROR_FLAG | ||||
|         from django.contrib.admin.views.main import ERROR_FLAG | ||||
|         opts = self.model._meta | ||||
|         app_label = opts.app_label | ||||
|         if not self.has_change_permission(request, None): | ||||
| @@ -913,6 +920,7 @@ class ModelAdmin(BaseModelAdmin): | ||||
|             except ValueError: | ||||
|                 pass | ||||
|  | ||||
|         ChangeList = self.get_changelist(request) | ||||
|         try: | ||||
|             cl = ChangeList(request, self.model, list_display, self.list_display_links, self.list_filter, | ||||
|                 self.date_hierarchy, self.search_fields, self.list_select_related, self.list_per_page, self.list_editable, self) | ||||
|   | ||||
| @@ -9,7 +9,7 @@ def shortcut(request, content_type_id, object_id): | ||||
|     try: | ||||
|         content_type = ContentType.objects.get(pk=content_type_id) | ||||
|         obj = content_type.get_object_for_this_type(pk=object_id) | ||||
|     except ObjectDoesNotExist: | ||||
|     except (ObjectDoesNotExist, ValueError): | ||||
|         raise http.Http404("Content type %s object %s doesn't exist" % (content_type_id, object_id)) | ||||
|     try: | ||||
|         absurl = obj.get_absolute_url() | ||||
|   | ||||
| @@ -88,7 +88,17 @@ class Command(BaseCommand): | ||||
|         if has_bz2: | ||||
|             compression_types['bz2'] = bz2.BZ2File | ||||
|  | ||||
|         app_fixtures = [os.path.join(os.path.dirname(app.__file__), 'fixtures') for app in get_apps()] | ||||
|         app_module_paths = [] | ||||
|         for app in get_apps(): | ||||
|             if hasattr(app, '__path__'): | ||||
|                 # It's a 'models/' subpackage | ||||
|                 for path in app.__path__: | ||||
|                     app_module_paths.append(path) | ||||
|             else: | ||||
|                 # It's a models.py module | ||||
|                 app_module_paths.append(app.__file__) | ||||
|  | ||||
|         app_fixtures = [os.path.join(os.path.dirname(path), 'fixtures') for path in app_module_paths] | ||||
|         for fixture_label in fixture_labels: | ||||
|             parts = fixture_label.split('.') | ||||
|  | ||||
|   | ||||
| @@ -34,3 +34,42 @@ class DatabaseCreation(BaseDatabaseCreation): | ||||
|         if self.connection.settings_dict['TEST_CHARSET']: | ||||
|             return "WITH ENCODING '%s'" % self.connection.settings_dict['TEST_CHARSET'] | ||||
|         return '' | ||||
|  | ||||
|     def sql_indexes_for_field(self, model, f, style): | ||||
|         if f.db_index and not f.unique: | ||||
|             qn = self.connection.ops.quote_name | ||||
|             db_table = model._meta.db_table | ||||
|             tablespace = f.db_tablespace or model._meta.db_tablespace | ||||
|             if tablespace: | ||||
|                 sql = self.connection.ops.tablespace_sql(tablespace) | ||||
|                 if sql: | ||||
|                     tablespace_sql = ' ' + sql | ||||
|                 else: | ||||
|                     tablespace_sql = '' | ||||
|             else: | ||||
|                 tablespace_sql = '' | ||||
|  | ||||
|             def get_index_sql(index_name, opclass=''): | ||||
|                 return (style.SQL_KEYWORD('CREATE INDEX') + ' ' + | ||||
|                         style.SQL_TABLE(qn(index_name)) + ' ' + | ||||
|                         style.SQL_KEYWORD('ON') + ' ' + | ||||
|                         style.SQL_TABLE(qn(db_table)) + ' ' + | ||||
|                         "(%s%s)" % (style.SQL_FIELD(qn(f.column)), opclass) + | ||||
|                         "%s;" % tablespace_sql) | ||||
|  | ||||
|             output = [get_index_sql('%s_%s' % (db_table, f.column))] | ||||
|  | ||||
|             # Fields with database column types of `varchar` and `text` need | ||||
|             # a second index that specifies their operator class, which is | ||||
|             # needed when performing correct LIKE queries outside the | ||||
|             # C locale. See #12234. | ||||
|             db_type = f.db_type() | ||||
|             if db_type.startswith('varchar'): | ||||
|                 output.append(get_index_sql('%s_%s_like' % (db_table, f.column), | ||||
|                                             ' varchar_pattern_ops')) | ||||
|             elif db_type.startswith('text'): | ||||
|                 output.append(get_index_sql('%s_%s_like' % (db_table, f.column), | ||||
|                                             ' text_pattern_ops')) | ||||
|         else: | ||||
|             output = [] | ||||
|         return output | ||||
|   | ||||
| @@ -328,6 +328,8 @@ class QuerySet(object): | ||||
|         keyword arguments. | ||||
|         """ | ||||
|         clone = self.filter(*args, **kwargs) | ||||
|         if self.query.can_filter(): | ||||
|             clone = clone.order_by() | ||||
|         num = len(clone) | ||||
|         if num == 1: | ||||
|             return clone._result_cache[0] | ||||
| @@ -394,7 +396,7 @@ class QuerySet(object): | ||||
|         """ | ||||
|         assert self.query.can_filter(), \ | ||||
|                 "Cannot use 'limit' or 'offset' with in_bulk" | ||||
|         assert isinstance(id_list, (tuple,  list)), \ | ||||
|         assert isinstance(id_list, (tuple,  list, set, frozenset)), \ | ||||
|                 "in_bulk() must be provided with a list of IDs." | ||||
|         if not id_list: | ||||
|             return {} | ||||
|   | ||||
| @@ -82,6 +82,21 @@ You should also audit your existing code for any instances of this behavior | ||||
| before enabling this feature. It's faster, but it provides less automatic | ||||
| protection for multi-call operations. | ||||
|  | ||||
| Indexes for ``varchar`` and ``text`` columns | ||||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||||
| .. versionadded:: 1.1.2 | ||||
|  | ||||
| When specifying ``db_index=True`` on your model fields, Django typically | ||||
| outputs a single ``CREATE INDEX`` statement.  However, if the database type | ||||
| for the field is either ``varchar`` or ``text`` (e.g., used by ``CharField``, | ||||
| ``FileField``, and ``TextField``), then Django will create | ||||
| an additional index that uses an appropriate `PostgreSQL operator class`_ | ||||
| for the column.  The extra index is necessary to correctly perfrom | ||||
| lookups that use the ``LIKE`` operator in their SQL, as is done with the | ||||
| ``contains`` and ``startswith`` lookup types. | ||||
|  | ||||
| .. _PostgreSQL operator class: http://www.postgresql.org/docs/8.4/static/indexes-opclass.html | ||||
|  | ||||
| .. _mysql-notes: | ||||
|  | ||||
| MySQL notes | ||||
|   | ||||
| @@ -225,8 +225,9 @@ Methods | ||||
|     .. method:: models.User.has_perm(perm, obj=None) | ||||
|  | ||||
|         Returns ``True`` if the user has the specified permission, where perm is | ||||
|         in the format ``"<app label>.<permission codename>"``. | ||||
|         If the user is inactive, this method will always return ``False``. | ||||
|         in the format ``"<app label>.<permission codename>"``. (see | ||||
|         `permissions`_ section below). If the user is inactive, this method will | ||||
|         always return ``False``. | ||||
|  | ||||
|         .. versionadded:: 1.2 | ||||
|  | ||||
| @@ -1122,6 +1123,8 @@ generic view itself. For example:: | ||||
|     def limited_object_detail(*args, **kwargs): | ||||
|         return object_detail(*args, **kwargs) | ||||
|  | ||||
| .. _permissions: | ||||
|  | ||||
| Permissions | ||||
| =========== | ||||
|  | ||||
| @@ -1164,6 +1167,14 @@ models being installed at that time. Afterward, it will create default | ||||
| permissions for new models each time you run :djadmin:`manage.py syncdb | ||||
| <syncdb>`. | ||||
|  | ||||
| Assuming you have an application with an | ||||
| :attr:`~django.db.models.Options.app_label` ``foo`` and a model named ``Bar``, | ||||
| to test for basic permissions you should use: | ||||
|  | ||||
|     * add: ``user.has_perm('foo.add_bar')`` | ||||
|     * change: ``user.has_perm('foo.change_bar')`` | ||||
|     * delete: ``user.has_perm('foo.delete_bar')`` | ||||
|  | ||||
| .. _custom-permissions: | ||||
|  | ||||
| Custom permissions | ||||
|   | ||||
| @@ -264,7 +264,7 @@ name:: | ||||
|  | ||||
|     class PersonManager(models.Manager): | ||||
|         def get_by_natural_key(self, first_name, last_name): | ||||
|             return self.filter(first_name=first_name, last_name=last_name) | ||||
|             return self.get(first_name=first_name, last_name=last_name) | ||||
|  | ||||
|     class Person(models.Model): | ||||
|         objects = PersonManager() | ||||
|   | ||||
							
								
								
									
										2
									
								
								tests/modeltests/fixtures_model_package/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								tests/modeltests/fixtures_model_package/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
|  | ||||
|  | ||||
| @@ -0,0 +1,18 @@ | ||||
| [ | ||||
|     { | ||||
|         "pk": "2",  | ||||
|         "model": "fixtures_model_package.article",  | ||||
|         "fields": { | ||||
|             "headline": "Poker has no place on ESPN",  | ||||
|             "pub_date": "2006-06-16 12:00:00" | ||||
|         } | ||||
|     },  | ||||
|     { | ||||
|         "pk": "3",  | ||||
|         "model": "fixtures_model_package.article",  | ||||
|         "fields": { | ||||
|             "headline": "Time to reform copyright",  | ||||
|             "pub_date": "2006-06-16 13:00:00" | ||||
|         } | ||||
|     } | ||||
| ] | ||||
| @@ -0,0 +1,18 @@ | ||||
| [ | ||||
|     { | ||||
|         "pk": "3",  | ||||
|         "model": "fixtures_model_package.article",  | ||||
|         "fields": { | ||||
|             "headline": "Copyright is fine the way it is",  | ||||
|             "pub_date": "2006-06-16 14:00:00" | ||||
|         } | ||||
|     },  | ||||
|     { | ||||
|         "pk": "4",  | ||||
|         "model": "fixtures_model_package.article",  | ||||
|         "fields": { | ||||
|             "headline": "Django conquers world!",  | ||||
|             "pub_date": "2006-06-16 15:00:00" | ||||
|         } | ||||
|     } | ||||
| ] | ||||
| @@ -0,0 +1,11 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <django-objects version="1.0"> | ||||
|     <object pk="2" model="fixtures_model_package.article"> | ||||
|         <field type="CharField" name="headline">Poker on TV is great!</field> | ||||
|         <field type="DateTimeField" name="pub_date">2006-06-16 11:00:00</field> | ||||
|     </object> | ||||
|     <object pk="5" model="fixtures_model_package.article"> | ||||
|         <field type="CharField" name="headline">XML identified as leading cause of cancer</field> | ||||
|         <field type="DateTimeField" name="pub_date">2006-06-16 16:00:00</field> | ||||
|     </object> | ||||
| </django-objects> | ||||
| @@ -0,0 +1,10 @@ | ||||
| [ | ||||
|     { | ||||
|         "pk": "1",  | ||||
|         "model": "fixtures_model_package.article",  | ||||
|         "fields": { | ||||
|             "headline": "Python program becomes self aware",  | ||||
|             "pub_date": "2006-06-16 11:00:00" | ||||
|         } | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										54
									
								
								tests/modeltests/fixtures_model_package/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								tests/modeltests/fixtures_model_package/models/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| from django.db import models | ||||
| from django.conf import settings | ||||
|  | ||||
| class Article(models.Model): | ||||
|     headline = models.CharField(max_length=100, default='Default headline') | ||||
|     pub_date = models.DateTimeField() | ||||
|  | ||||
|     def __unicode__(self): | ||||
|         return self.headline | ||||
|  | ||||
|     class Meta: | ||||
|         app_label = 'fixtures_model_package' | ||||
|         ordering = ('-pub_date', 'headline') | ||||
|  | ||||
| __test__ = {'API_TESTS': """ | ||||
| >>> from django.core import management | ||||
| >>> from django.db.models import get_app | ||||
|  | ||||
| # Reset the database representation of this app. | ||||
| # This will return the database to a clean initial state. | ||||
| >>> management.call_command('flush', verbosity=0, interactive=False) | ||||
|  | ||||
| # Syncdb introduces 1 initial data object from initial_data.json. | ||||
| >>> Article.objects.all() | ||||
| [<Article: Python program becomes self aware>] | ||||
|  | ||||
| # Load fixture 1. Single JSON file, with two objects. | ||||
| >>> management.call_command('loaddata', 'fixture1.json', verbosity=0) | ||||
| >>> Article.objects.all() | ||||
| [<Article: Time to reform copyright>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] | ||||
|  | ||||
| # Load fixture 2. JSON file imported by default. Overwrites some existing objects | ||||
| >>> management.call_command('loaddata', 'fixture2.json', verbosity=0) | ||||
| >>> Article.objects.all() | ||||
| [<Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] | ||||
|  | ||||
| # Load a fixture that doesn't exist | ||||
| >>> management.call_command('loaddata', 'unknown.json', verbosity=0) | ||||
|  | ||||
| # object list is unaffected | ||||
| >>> Article.objects.all() | ||||
| [<Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>] | ||||
| """} | ||||
|  | ||||
|  | ||||
| from django.test import TestCase | ||||
|  | ||||
| class SampleTestCase(TestCase): | ||||
|     fixtures = ['fixture1.json', 'fixture2.json'] | ||||
|  | ||||
|     def testClassFixtures(self): | ||||
|         "Check that test case has installed 4 fixture objects" | ||||
|         self.assertEqual(Article.objects.count(), 4) | ||||
|         self.assertEquals(str(Article.objects.all()), "[<Article: Django conquers world!>, <Article: Copyright is fine the way it is>, <Article: Poker has no place on ESPN>, <Article: Python program becomes self aware>]") | ||||
| @@ -104,6 +104,12 @@ Article 4 | ||||
| <Article: Article 2> | ||||
| >>> Article.objects.in_bulk([3]) | ||||
| {3: <Article: Article 3>} | ||||
| >>> Article.objects.in_bulk(set([3])) | ||||
| {3: <Article: Article 3>} | ||||
| >>> Article.objects.in_bulk(frozenset([3])) | ||||
| {3: <Article: Article 3>} | ||||
| >>> Article.objects.in_bulk((3,)) | ||||
| {3: <Article: Article 3>} | ||||
| >>> Article.objects.in_bulk([1000]) | ||||
| {} | ||||
| >>> Article.objects.in_bulk([]) | ||||
|   | ||||
| @@ -4,6 +4,7 @@ import os | ||||
| from django.core.files.storage import FileSystemStorage | ||||
| from django.db import models | ||||
| from django.contrib import admin | ||||
| from django.contrib.admin.views.main import ChangeList | ||||
| from django.core.mail import EmailMessage | ||||
|  | ||||
| class Section(models.Model): | ||||
| @@ -420,6 +421,20 @@ class CategoryInline(admin.StackedInline): | ||||
| class CollectorAdmin(admin.ModelAdmin): | ||||
|     inlines = [WidgetInline, DooHickeyInline, GrommetInline, WhatsitInline, FancyDoodadInline, CategoryInline] | ||||
|  | ||||
| class Gadget(models.Model): | ||||
|     name = models.CharField(max_length=100) | ||||
|  | ||||
|     def __unicode__(self): | ||||
|         return self.name | ||||
|  | ||||
| class CustomChangeList(ChangeList): | ||||
|     def get_query_set(self): | ||||
|         return self.root_query_set.filter(pk=9999) # Does not exist | ||||
|  | ||||
| class GadgetAdmin(admin.ModelAdmin): | ||||
|     def get_changelist(self, request, **kwargs): | ||||
|         return CustomChangeList | ||||
|  | ||||
| admin.site.register(Article, ArticleAdmin) | ||||
| admin.site.register(CustomArticle, CustomArticleAdmin) | ||||
| admin.site.register(Section, save_as=True, inlines=[ArticleInline]) | ||||
| @@ -443,6 +458,7 @@ admin.site.register(Recommendation, RecommendationAdmin) | ||||
| admin.site.register(Recommender) | ||||
| admin.site.register(Collector, CollectorAdmin) | ||||
| admin.site.register(Category, CategoryAdmin) | ||||
| admin.site.register(Gadget, GadgetAdmin) | ||||
|  | ||||
| # We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2. | ||||
| # That way we cover all four cases: | ||||
|   | ||||
| @@ -1203,6 +1203,33 @@ class AdminActionsTest(TestCase): | ||||
|         self.failUnlessEqual(Subscriber.objects.count(), 2) | ||||
|  | ||||
|  | ||||
| class TestCustomChangeList(TestCase): | ||||
|     fixtures = ['admin-views-users.xml'] | ||||
|     urlbit = 'admin' | ||||
|  | ||||
|     def setUp(self): | ||||
|         result = self.client.login(username='super', password='secret') | ||||
|         self.failUnlessEqual(result, True) | ||||
|  | ||||
|     def tearDown(self): | ||||
|         self.client.logout() | ||||
|  | ||||
|     def test_custom_changelist(self): | ||||
|         """ | ||||
|         Validate that a custom ChangeList class can be used (#9749) | ||||
|         """ | ||||
|         # Insert some data | ||||
|         post_data = {"name": u"First Gadget"} | ||||
|         response = self.client.post('/test_admin/%s/admin_views/gadget/add/' % self.urlbit, post_data) | ||||
|         self.failUnlessEqual(response.status_code, 302) # redirect somewhere | ||||
|         # Hit the page once to get messages out of the queue message list | ||||
|         response = self.client.get('/test_admin/%s/admin_views/gadget/' % self.urlbit) | ||||
|         # Ensure that that data is still not visible on the page | ||||
|         response = self.client.get('/test_admin/%s/admin_views/gadget/' % self.urlbit) | ||||
|         self.failUnlessEqual(response.status_code, 200) | ||||
|         self.assertNotContains(response, 'First Gadget') | ||||
|  | ||||
|  | ||||
| class TestInlineNotEditable(TestCase): | ||||
|     fixtures = ['admin-views-users.xml'] | ||||
|  | ||||
|   | ||||
| @@ -89,22 +89,22 @@ class GenericAdminViewTest(TestCase): | ||||
|         # Works with no queryset | ||||
|         formset = EpisodeMediaFormSet(instance=e) | ||||
|         self.assertEquals(len(formset.forms), 5) | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/podcast.mp3" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="1" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>') | ||||
|         self.assertEquals(formset.forms[1].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-1-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-1-url" type="text" name="generic_inline_admin-media-content_type-object_id-1-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-1-id" value="2" id="id_generic_inline_admin-media-content_type-object_id-1-id" /></p>') | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/podcast.mp3" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="%s" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>' % self.mp3_media_pk) | ||||
|         self.assertEquals(formset.forms[1].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-1-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-1-url" type="text" name="generic_inline_admin-media-content_type-object_id-1-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-1-id" value="%s" id="id_generic_inline_admin-media-content_type-object_id-1-id" /></p>' % self.png_media_pk) | ||||
|         self.assertEquals(formset.forms[2].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-2-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-2-url" type="text" name="generic_inline_admin-media-content_type-object_id-2-url" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-2-id" id="id_generic_inline_admin-media-content_type-object_id-2-id" /></p>') | ||||
|  | ||||
|         # A queryset can be used to alter display ordering | ||||
|         formset = EpisodeMediaFormSet(instance=e, queryset=Media.objects.order_by('url')) | ||||
|         self.assertEquals(len(formset.forms), 5) | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="2" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>') | ||||
|         self.assertEquals(formset.forms[1].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-1-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-1-url" type="text" name="generic_inline_admin-media-content_type-object_id-1-url" value="http://example.com/podcast.mp3" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-1-id" value="1" id="id_generic_inline_admin-media-content_type-object_id-1-id" /></p>') | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="%s" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>' % self.png_media_pk) | ||||
|         self.assertEquals(formset.forms[1].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-1-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-1-url" type="text" name="generic_inline_admin-media-content_type-object_id-1-url" value="http://example.com/podcast.mp3" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-1-id" value="%s" id="id_generic_inline_admin-media-content_type-object_id-1-id" /></p>' % self.mp3_media_pk) | ||||
|         self.assertEquals(formset.forms[2].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-2-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-2-url" type="text" name="generic_inline_admin-media-content_type-object_id-2-url" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-2-id" id="id_generic_inline_admin-media-content_type-object_id-2-id" /></p>') | ||||
|  | ||||
|  | ||||
|         # Works with a queryset that omits items | ||||
|         formset = EpisodeMediaFormSet(instance=e, queryset=Media.objects.filter(url__endswith=".png")) | ||||
|         self.assertEquals(len(formset.forms), 4) | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="2" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>') | ||||
|         self.assertEquals(formset.forms[0].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-0-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-0-url" type="text" name="generic_inline_admin-media-content_type-object_id-0-url" value="http://example.com/logo.png" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-0-id" value="%s" id="id_generic_inline_admin-media-content_type-object_id-0-id" /></p>' % self.png_media_pk) | ||||
|         self.assertEquals(formset.forms[1].as_p(), '<p><label for="id_generic_inline_admin-media-content_type-object_id-1-url">Url:</label> <input id="id_generic_inline_admin-media-content_type-object_id-1-url" type="text" name="generic_inline_admin-media-content_type-object_id-1-url" maxlength="200" /><input type="hidden" name="generic_inline_admin-media-content_type-object_id-1-id" id="id_generic_inline_admin-media-content_type-object_id-1-id" /></p>') | ||||
|  | ||||
|     def testGenericInlineFormsetFactory(self): | ||||
|   | ||||
| @@ -10,8 +10,8 @@ class DefaultsTests(TestCase): | ||||
|     """Test django views in django/views/defaults.py""" | ||||
|     fixtures = ['testdata.json'] | ||||
|  | ||||
|     def test_shorcut_with_absolute_url(self): | ||||
|         "Can view a shortcut an Author object that has with a get_absolute_url method" | ||||
|     def test_shortcut_with_absolute_url(self): | ||||
|         "Can view a shortcut for an Author object that has a get_absolute_url method" | ||||
|         for obj in Author.objects.all(): | ||||
|             short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, obj.pk) | ||||
|             response = self.client.get(short_url) | ||||
| @@ -19,12 +19,34 @@ class DefaultsTests(TestCase): | ||||
|                                  status_code=302, target_status_code=404) | ||||
|  | ||||
|     def test_shortcut_no_absolute_url(self): | ||||
|         "Shortcuts for an object that has with a get_absolute_url method raises 404" | ||||
|         "Shortcuts for an object that has no get_absolute_url method raises 404" | ||||
|         for obj in Article.objects.all(): | ||||
|             short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Article).id, obj.pk) | ||||
|             response = self.client.get(short_url) | ||||
|             self.assertEquals(response.status_code, 404) | ||||
|  | ||||
|     def test_wrong_type_pk(self): | ||||
|         short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, 'nobody/expects') | ||||
|         response = self.client.get(short_url) | ||||
|         self.assertEquals(response.status_code, 404) | ||||
|  | ||||
|     def test_shortcut_bad_pk(self): | ||||
|         short_url = '/views/shortcut/%s/%s/' % (ContentType.objects.get_for_model(Author).id, '4242424242') | ||||
|         response = self.client.get(short_url) | ||||
|         self.assertEquals(response.status_code, 404) | ||||
|  | ||||
|     def test_nonint_content_type(self): | ||||
|         an_author = Author.objects.all()[0] | ||||
|         short_url = '/views/shortcut/%s/%s/' % ('spam', an_author.pk) | ||||
|         response = self.client.get(short_url) | ||||
|         self.assertEquals(response.status_code, 404) | ||||
|  | ||||
|     def test_bad_content_type(self): | ||||
|         an_author = Author.objects.all()[0] | ||||
|         short_url = '/views/shortcut/%s/%s/' % (4242424242, an_author.pk) | ||||
|         response = self.client.get(short_url) | ||||
|         self.assertEquals(response.status_code, 404) | ||||
|  | ||||
|     def test_page_not_found(self): | ||||
|         "A 404 status is returned by the page_not_found view" | ||||
|         non_existing_urls = ['/views/non_existing_url/', # this is in urls.py | ||||
|   | ||||
		Reference in New Issue
	
	Block a user