Ticket #9969: 9969-r9891.diff

File 9969-r9891.diff, 16.7 KB (added by ramiro, 6 years ago)

Updated and correct patch

  • django/contrib/admin/templatetags/admin_list.py

    diff -r 8ff680917e4e django/contrib/admin/templatetags/admin_list.py
    a b  
    7070
    7171def result_headers(cl):
    7272    lookup_opts = cl.lookup_opts
    73    
     73
    7474    for i, field_name in enumerate(cl.list_display):
    7575        attr = None
    7676        try:
     
    9797                            raise AttributeError, \
    9898                                "'%s' model or '%s' objects have no attribute '%s'" % \
    9999                                    (lookup_opts.object_name, cl.model_admin.__class__, field_name)
    100                
     100
    101101                try:
    102102                    header = attr.short_description
    103103                except AttributeError:
     
    205205                    result_repr = EMPTY_CHANGELIST_VALUE
    206206            # Fields with choices are special: Use the representation
    207207            # of the choice.
    208             elif f.choices:
    209                 result_repr = dict(f.choices).get(field_val, EMPTY_CHANGELIST_VALUE)
     208            elif f.flatchoices:
     209                result_repr = dict(f.flatchoices).get(field_val, EMPTY_CHANGELIST_VALUE)
    210210            else:
    211211                result_repr = escape(field_val)
    212212        if force_unicode(result_repr) == '':
  • tests/regressiontests/admin_views/customadmin.py

    diff -r 8ff680917e4e tests/regressiontests/admin_views/customadmin.py
    a b  
    1010class Admin2(admin.AdminSite):
    1111    login_template = 'custom_admin/login.html'
    1212    index_template = 'custom_admin/index.html'
    13    
     13
    1414    # A custom index view.
    1515    def index(self, request, extra_context=None):
    1616        return super(Admin2, self).index(request, {'foo': '*bar*'})
    17    
     17
    1818    def get_urls(self):
    1919        return patterns('',
    2020            (r'^my_view/$', self.admin_view(self.my_view)),
    2121        ) + super(Admin2, self).get_urls()
    22    
     22
    2323    def my_view(self, request):
    2424        return HttpResponse("Django is a magical pony!")
    25    
     25
    2626site = Admin2(name="admin2")
    2727
    2828site.register(models.Article, models.ArticleAdmin)
    2929site.register(models.Section, inlines=[models.ArticleInline])
    3030site.register(models.Thing, models.ThingAdmin)
     31site.register(models.Fabric, models.FabricAdmin)
  • new file tests/regressiontests/admin_views/fixtures/admin-views-fabrics.xml

    diff -r 8ff680917e4e tests/regressiontests/admin_views/fixtures/admin-views-fabrics.xml
    - +  
     1<?xml version="1.0" encoding="utf-8"?>
     2<django-objects version="1.0">
     3  <object pk="1" model="admin_views.fabric">
     4    <field type="CharField" name="surface">x</field>
     5  </object>
     6  <object pk="2" model="admin_views.fabric">
     7    <field type="CharField" name="surface">y</field>
     8  </object>
     9  <object pk="3" model="admin_views.fabric">
     10    <field type="CharField" name="surface">plain</field>
     11  </object>
     12</django-objects>
  • tests/regressiontests/admin_views/models.py

    diff -r 8ff680917e4e tests/regressiontests/admin_views/models.py
    a b  
    2020
    2121    def __unicode__(self):
    2222        return self.title
    23    
     23
    2424    def model_year(self):
    2525        return self.date.year
    2626    model_year.admin_order_field = 'date'
     
    5454
    5555class ChapterXtra1(models.Model):
    5656    chap = models.OneToOneField(Chapter, verbose_name=u'¿Chap?')
    57     xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?') 
     57    xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?')
    5858
    5959    def __unicode__(self):
    6060        return u'¿Xtra1: %s' % self.xtra
    6161
    6262class ChapterXtra2(models.Model):
    6363    chap = models.OneToOneField(Chapter, verbose_name=u'¿Chap?')
    64     xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?') 
     64    xtra = models.CharField(max_length=100, verbose_name=u'¿Xtra?')
    6565
    6666    def __unicode__(self):
    6767        return u'¿Xtra2: %s' % self.xtra
     
    8787                'extra_var': 'Hello!'
    8888            }
    8989        )
    90        
     90
    9191    def modeladmin_year(self, obj):
    9292        return obj.date.year
    9393    modeladmin_year.admin_order_field = 'date'
     
    121121
    122122class Color(models.Model):
    123123    value = models.CharField(max_length=10)
    124     warm = models.BooleanField()   
     124    warm = models.BooleanField()
    125125    def __unicode__(self):
    126126        return self.value
    127127
     
    134134class ThingAdmin(admin.ModelAdmin):
    135135    list_filter = ('color',)
    136136
     137class Fabric(models.Model):
     138    NG_CHOICES = (
     139        ('Textured', (
     140                ('x', 'Horizontal'),
     141                ('y', 'Vertical'),
     142            )
     143        ),
     144        ('plain', 'Smooth'),
     145    )
     146    surface = models.CharField(max_length=20, choices=NG_CHOICES)
     147
     148class FabricAdmin(admin.ModelAdmin):
     149    list_display = ('surface',)
     150    list_filter = ('surface',)
     151
    137152admin.site.register(Article, ArticleAdmin)
    138153admin.site.register(CustomArticle, CustomArticleAdmin)
    139154admin.site.register(Section, inlines=[ArticleInline])
    140155admin.site.register(ModelWithStringPrimaryKey)
    141156admin.site.register(Color)
    142157admin.site.register(Thing, ThingAdmin)
     158admin.site.register(Fabric, FabricAdmin)
    143159
    144160# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
    145161# That way we cover all four cases:
  • tests/regressiontests/admin_views/tests.py

    diff -r 8ff680917e4e tests/regressiontests/admin_views/tests.py
    a b  
    1212from models import Article, CustomArticle, Section, ModelWithStringPrimaryKey
    1313
    1414class AdminViewBasicTest(TestCase):
    15     fixtures = ['admin-views-users.xml', 'admin-views-colors.xml']
    16    
    17     # Store the bit of the URL where the admin is registered as a class 
     15    fixtures = ['admin-views-users.xml', 'admin-views-colors.xml', 'admin-views-fabrics.xml']
     16
     17    # Store the bit of the URL where the admin is registered as a class
    1818    # variable. That way we can test a second AdminSite just by subclassing
    1919    # this test case and changing urlbit.
    2020    urlbit = 'admin'
    21    
     21
    2222    def setUp(self):
    2323        self.client.login(username='super', password='secret')
    24    
     24
    2525    def tearDown(self):
    2626        self.client.logout()
    27    
     27
    2828    def testTrailingSlashRequired(self):
    2929        """
    3030        If you leave off the trailing slash, app should redirect and add it.
     
    3333        self.assertRedirects(request,
    3434            '/test_admin/%s/admin_views/article/add/' % self.urlbit, status_code=301
    3535        )
    36    
     36
    3737    def testBasicAddGet(self):
    3838        """
    3939        A smoke test to ensure GET on the add_view works.
    4040        """
    4141        response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit)
    4242        self.failUnlessEqual(response.status_code, 200)
    43    
     43
    4444    def testAddWithGETArgs(self):
    4545        response = self.client.get('/test_admin/%s/admin_views/section/add/' % self.urlbit, {'name': 'My Section'})
    4646        self.failUnlessEqual(response.status_code, 200)
    4747        self.failUnless(
    48             'value="My Section"' in response.content, 
     48            'value="My Section"' in response.content,
    4949            "Couldn't find an input with the right value in the response."
    5050        )
    51    
     51
    5252    def testBasicEditGet(self):
    5353        """
    5454        A smoke test to ensureGET on the change_view works.
    5555        """
    5656        response = self.client.get('/test_admin/%s/admin_views/section/1/' % self.urlbit)
    5757        self.failUnlessEqual(response.status_code, 200)
    58    
     58
    5959    def testBasicAddPost(self):
    6060        """
    6161        A smoke test to ensure POST on add_view works.
     
    6868        }
    6969        response = self.client.post('/test_admin/%s/admin_views/section/add/' % self.urlbit, post_data)
    7070        self.failUnlessEqual(response.status_code, 302) # redirect somewhere
    71    
     71
    7272    def testBasicEditPost(self):
    7373        """
    7474        A smoke test to ensure POST on edit_view works.
     
    116116
    117117    def testChangeListSortingCallable(self):
    118118        """
    119         Ensure we can sort on a list_display field that is a callable 
     119        Ensure we can sort on a list_display field that is a callable
    120120        (column 2 is callable_year in ArticleAdmin)
    121121        """
    122122        response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'asc', 'o': 2})
     
    126126            response.content.index('Middle content') < response.content.index('Newest content'),
    127127            "Results of sorting on callable are out of order."
    128128        )
    129    
     129
    130130    def testChangeListSortingModel(self):
    131131        """
    132         Ensure we can sort on a list_display field that is a Model method 
     132        Ensure we can sort on a list_display field that is a Model method
    133133        (colunn 3 is 'model_year' in ArticleAdmin)
    134134        """
    135135        response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'dsc', 'o': 3})
     
    139139            response.content.index('Middle content') < response.content.index('Oldest content'),
    140140            "Results of sorting on Model method are out of order."
    141141        )
    142    
     142
    143143    def testChangeListSortingModelAdmin(self):
    144144        """
    145         Ensure we can sort on a list_display field that is a ModelAdmin method 
     145        Ensure we can sort on a list_display field that is a ModelAdmin method
    146146        (colunn 4 is 'modeladmin_year' in ArticleAdmin)
    147147        """
    148148        response = self.client.get('/test_admin/%s/admin_views/article/' % self.urlbit, {'ot': 'asc', 'o': 4})
    149149        self.failUnlessEqual(response.status_code, 200)
    150150        self.failUnless(
    151             response.content.index('Oldest content') < response.content.index('Middle content') and 
     151            response.content.index('Oldest content') < response.content.index('Middle content') and
    152152            response.content.index('Middle content') < response.content.index('Newest content'),
    153153            "Results of sorting on ModelAdmin method are out of order."
    154154        )
    155        
     155
     156    def testNamedGroupFieldChoicesChangeList(self):
     157        """
     158        Ensures the admin changelist shows correct values in the relevant column
     159        for rows corresponding to instances of a model in which a named group
     160        has been used in the choices option of a field.
     161        """
     162        response = self.client.get('/test_admin/%s/admin_views/fabric/' % self.urlbit)
     163        self.failUnlessEqual(response.status_code, 200)
     164        self.failUnless(
     165            '<a href="1/">Horizontal</a>' in response.content and
     166            '<a href="2/">Vertical</a>' in response.content,
     167            "Changelist table isn't showing the right human-readable values set by a model field 'choices' option named group."
     168        )
     169
    156170    def testLimitedFilter(self):
    157171        """Ensure admin changelist filters do not contain objects excluded via limit_choices_to."""
    158172        response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit)
    159173        self.failUnlessEqual(response.status_code, 200)
    160174        self.failUnless(
    161             '<div id="changelist-filter">' in response.content, 
     175            '<div id="changelist-filter">' in response.content,
    162176            "Expected filter not found in changelist view."
    163177        )
    164178        self.failIf(
    165179            '<a href="?color__id__exact=3">Blue</a>' in response.content,
    166180            "Changelist filter not correctly limited by limit_choices_to."
    167181        )
    168        
     182
    169183    def testIncorrectLookupParameters(self):
    170184        """Ensure incorrect lookup parameters are handled gracefully."""
    171185        response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit, {'notarealfield': '5'})
    172         self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)       
     186        self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)
    173187        response = self.client.get('/test_admin/%s/admin_views/thing/' % self.urlbit, {'color__id__exact': 'StringNotInteger!'})
    174188        self.assertRedirects(response, '/test_admin/%s/admin_views/thing/?e=1' % self.urlbit)
    175189
     
    186200        request = self.client.get('/test_admin/admin2/')
    187201        self.assertTemplateUsed(request, 'custom_admin/index.html')
    188202        self.assert_('Hello from a custom index template *bar*' in request.content)
    189    
     203
    190204    def testCustomAdminSiteView(self):
    191205        self.client.login(username='super', password='secret')
    192206        response = self.client.get('/test_admin/%s/my_view/' % self.urlbit)
     
    411425        post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
    412426        self.assertRedirects(post, '/test_admin/admin/admin_views/article/')
    413427        self.failUnlessEqual(Article.objects.get(pk=1).content, '<p>edited article</p>')
    414        
     428
    415429        # one error in form should produce singular error message, multiple errors plural
    416430        change_dict['title'] = ''
    417431        post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
     
    422436        post = self.client.post('/test_admin/admin/admin_views/article/1/', change_dict)
    423437        self.failUnlessEqual(request.status_code, 200)
    424438        self.failUnless('Please correct the errors below.' in post.content,
    425                         'Plural error message not found in response to post with multiple errors.')       
     439                        'Plural error message not found in response to post with multiple errors.')
    426440        self.client.get('/test_admin/admin/logout/')
    427441
    428442    def testCustomModelAdminTemplates(self):
     
    523537        response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/delete/' % quote(self.pk))
    524538        should_contain = """<a href="../../%s/">%s</a>""" % (quote(self.pk), escape(self.pk))
    525539        self.assertContains(response, should_contain)
    526    
     540
    527541    def test_url_conflicts_with_add(self):
    528542        "A model with a primary key that ends with add should be visible"
    529543        add_model = ModelWithStringPrimaryKey(id="i have something to add")
     
    531545        response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(add_model.pk))
    532546        should_contain = """<h1>Change model with string primary key</h1>"""
    533547        self.assertContains(response, should_contain)
    534    
     548
    535549    def test_url_conflicts_with_delete(self):
    536550        "A model with a primary key that ends with delete should be visible"
    537551        delete_model = ModelWithStringPrimaryKey(id="delete")
     
    539553        response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(delete_model.pk))
    540554        should_contain = """<h1>Change model with string primary key</h1>"""
    541555        self.assertContains(response, should_contain)
    542    
     556
    543557    def test_url_conflicts_with_history(self):
    544558        "A model with a primary key that ends with history should be visible"
    545559        history_model = ModelWithStringPrimaryKey(id="history")
     
    547561        response = self.client.get('/test_admin/admin/admin_views/modelwithstringprimarykey/%s/' % quote(history_model.pk))
    548562        should_contain = """<h1>Change model with string primary key</h1>"""
    549563        self.assertContains(response, should_contain)
    550        
     564
    551565
    552566class SecureViewTest(TestCase):
    553567    fixtures = ['admin-views-users.xml']
     
    582596                     LOGIN_FORM_KEY: 1,
    583597                     'username': 'joepublic',
    584598                     'password': 'secret'}
    585    
     599
    586600    def tearDown(self):
    587601        self.client.logout()
    588    
     602
    589603    def test_secure_view_shows_login_if_not_logged_in(self):
    590604        "Ensure that we see the login form"
    591605        response = self.client.get('/test_admin/admin/secure-view/' )
    592606        self.assertTemplateUsed(response, 'admin/login.html')
    593    
     607
    594608    def test_secure_view_login_successfully_redirects_to_original_url(self):
    595609        request = self.client.get('/test_admin/admin/secure-view/')
    596610        self.failUnlessEqual(request.status_code, 200)
    597611        query_string = "the-answer=42"
    598612        login = self.client.post('/test_admin/admin/secure-view/', self.super_login, QUERY_STRING = query_string )
    599613        self.assertRedirects(login, '/test_admin/admin/secure-view/?%s' % query_string)
    600    
     614
    601615    def test_staff_member_required_decorator_works_as_per_admin_login(self):
    602616        """
    603617        Make sure only staff members can log in.
    604618
    605619        Successful posts to the login page will redirect to the orignal url.
    606         Unsuccessfull attempts will continue to render the login page with 
     620        Unsuccessfull attempts will continue to render the login page with
    607621        a 200 status code.
    608622        """
    609623        # Super User
Back to Top