Ticket #15611: django-ticket-15611.diff

File django-ticket-15611.diff, 8.8 KB (added by Noah Kantrowitz, 13 years ago)
  • django/contrib/admin/helpers.py

    diff --git a/django/contrib/admin/helpers.py b/django/contrib/admin/helpers.py
    index 0055e83..1a7fde7 100644
    a b from django.contrib.admin.util import (flatten_fieldsets, lookup_field,  
    44    display_for_field, label_for_field, help_text_for_field)
    55from django.contrib.contenttypes.models import ContentType
    66from django.core.exceptions import ObjectDoesNotExist
     7from django.db import models
    78from django.db.models.fields.related import ManyToManyRel
    89from django.forms.util import flatatt
    910from django.template.defaultfilters import capfirst
    class AdminForm(object):  
    3637
    3738    def __iter__(self):
    3839        for name, options in self.fieldsets:
    39             yield Fieldset(self.form, name,
     40            fieldset = Fieldset(self.form, name,
    4041                readonly_fields=self.readonly_fields,
    4142                model_admin=self.model_admin,
    4243                **options
    4344            )
     45            if not fieldset.hidden:
     46                yield fieldset
    4447
    4548    def first_field(self):
    4649        try:
    class Fieldset(object):  
    7376        self.model_admin = model_admin
    7477        self.readonly_fields = readonly_fields
    7578
    76     def _media(self):
     79    @property
     80    def media(self):
    7781        if 'collapse' in self.classes:
    7882            js = ['js/jquery.min.js', 'js/jquery.init.js', 'js/collapse.min.js']
    7983            return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js])
    8084        return forms.Media()
    81     media = property(_media)
     85
     86    @property
     87    def hidden(self):
     88        # The fieldset is visible only if there is at least one visible line in it
     89        for line in self:
     90            return False
     91        return True
    8292
    8393    def __iter__(self):
    8494        for field in self.fields:
    85             yield Fieldline(self.form, field, self.readonly_fields, model_admin=self.model_admin)
     95            line = Fieldline(self.form, field, self.readonly_fields, model_admin=self.model_admin)
     96            if not line.hidden:
     97                yield line
    8698
    8799class Fieldline(object):
    88100    def __init__(self, form, field, readonly_fields=None, model_admin=None):
    class Fieldline(object):  
    96108            readonly_fields = ()
    97109        self.readonly_fields = readonly_fields
    98110
     111    @property
     112    def hidden(self):
     113        # The line is visible only if there is at least one visible field in it
     114        for field in self:
     115            return False
     116        return True
     117
    99118    def __iter__(self):
    100119        for i, field in enumerate(self.fields):
    101120            if field in self.readonly_fields:
    102                 yield AdminReadonlyField(self.form, field, is_first=(i == 0),
     121                field_obj = AdminReadonlyField(self.form, field, is_first=(i == 0),
    103122                    model_admin=self.model_admin)
    104123            else:
    105                 yield AdminField(self.form, field, is_first=(i == 0))
     124                field_obj = AdminField(self.form, field, is_first=(i == 0))
     125            if not field_obj.hidden:
     126                yield field_obj
    106127
    107128    def errors(self):
    108129        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields if f not in self.readonly_fields]).strip('\n'))
    class AdminField(object):  
    112133        self.field = form[field] # A django.forms.BoundField instance
    113134        self.is_first = is_first # Whether this field is first on the line
    114135        self.is_checkbox = isinstance(self.field.field.widget, forms.CheckboxInput)
     136        self.hidden = False
    115137
    116138    def label_tag(self):
    117139        classes = []
    class AdminReadonlyField(object):  
    138160        # For convenience, store other field-related data here too.
    139161        if callable(field):
    140162            class_name = field.__name__ != '<lambda>' and field.__name__ or ''
     163            self.hidden = False
    141164        else:
    142165            class_name = field
     166            if form.instance.pk is None:
     167                # Creation form, field is hidden unless it has a default or isn't a real field
     168                try:
     169                    f = form.instance._meta.get_field(field)
     170                except models.FieldDoesNotExist:
     171                    self.hidden = False
     172                else:
     173                    self.hidden = f.default is models.fields.NOT_PROVIDED
     174            else:
     175                self.hidden = False
    143176        self.field = {
    144177            'name': class_name,
    145178            'label': label,
  • tests/regressiontests/admin_views/models.py

    diff --git a/tests/regressiontests/admin_views/models.py b/tests/regressiontests/admin_views/models.py
    index b65f8a4..911c806 100644
    a b class OtherStoryAdmin(admin.ModelAdmin):  
    758758    list_display_links = ('title', 'id') # 'id' in list_display_links
    759759    list_editable = ('content', )
    760760
     761class ReadonlyFieldsetTestModel(models.Model):
     762    field1 = models.CharField(max_length=100)
     763    field2 = models.CharField(max_length=100)
     764    field3 = models.CharField(max_length=100)
     765    field4 = models.CharField(max_length=100)
     766    field5 = models.CharField(max_length=100)
     767    field6 = models.CharField(max_length=100)
     768    field7 = models.CharField(max_length=100, default=lambda:'foo')
     769    field8 = models.CharField(max_length=100, default='foo')
     770
     771class ReadonlyFieldsetTestAdmin(admin.ModelAdmin):
     772    fieldsets = (
     773        (None, {
     774            'fields': ('field1', 'field2')
     775        }),
     776        ('Set1', {
     777            'fields': ('field3', 'field4')
     778        }),
     779        ('Set2', {
     780            'fields': ('field5', 'field6')
     781        }),
     782        ('Set3', {
     783            'fields': ('field7', 'field8')
     784        }),
     785    )
     786    readonly_fields = ('field4', 'field5', 'field6', 'field7', 'field8')
     787
    761788admin.site.register(Article, ArticleAdmin)
    762789admin.site.register(CustomArticle, CustomArticleAdmin)
    763790admin.site.register(Section, save_as=True, inlines=[ArticleInline])
    admin.site.register(Paper, PaperAdmin)  
    800827admin.site.register(CoverLetter, CoverLetterAdmin)
    801828admin.site.register(Story, StoryAdmin)
    802829admin.site.register(OtherStory, OtherStoryAdmin)
     830admin.site.register(ReadonlyFieldsetTestModel, ReadonlyFieldsetTestAdmin)
    803831
    804832# We intentionally register Promo and ChapterXtra1 but not Chapter nor ChapterXtra2.
    805833# That way we cover all four cases:
  • tests/regressiontests/admin_views/tests.py

    diff --git a/tests/regressiontests/admin_views/tests.py b/tests/regressiontests/admin_views/tests.py
    index 57bd87f..372ba33 100644
    a b from models import (Article, BarAccount, CustomArticle, EmptyModel,  
    3636    Language, Collector, Widget, Grommet, DooHickey, FancyDoodad, Whatsit,
    3737    Category, Post, Plot, FunkyTag, Chapter, Book, Promo, WorkHour, Employee,
    3838    Question, Answer, Inquisition, Actor, FoodDelivery,
    39     RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory)
     39    RowLevelChangePermissionModel, Paper, CoverLetter, Story, OtherStory,
     40    ReadonlyFieldsetTestModel)
    4041
    4142
    4243class AdminViewBasicTest(TestCase):
    class ReadonlyTest(TestCase):  
    26192620        response = self.client.get('/test_admin/admin/admin_views/post/%d/' % p.pk)
    26202621        self.assertContains(response, "%d amount of cool" % p.pk)
    26212622
     2623        response = self.client.get('/test_admin/admin/admin_views/readonlyfieldsettestmodel/add/')
     2624        self.assertContains(response, 'Field1:</label>')
     2625        self.assertContains(response, 'Field2:</label>')
     2626        self.assertContains(response, 'Set1')
     2627        self.assertContains(response, 'Field3:</label>')
     2628        self.assertNotContains(response, 'Field4:</label>')
     2629        self.assertNotContains(response, 'Set2')
     2630        self.assertNotContains(response, 'Field5:</label>')
     2631        self.assertNotContains(response, 'Field6:</label>')
     2632        self.assertContains(response, 'Set3')
     2633        self.assertContains(response, 'Field7:</label>')
     2634        self.assertContains(response, 'Field8:</label>')
     2635
     2636        obj = ReadonlyFieldsetTestModel.objects.create(field1='a', field2='b', field3='c',
     2637                                                       field4='d', field5='e', field6='f')
     2638        response = self.client.get('/test_admin/admin/admin_views/readonlyfieldsettestmodel/%d/' % obj.pk)
     2639        self.assertContains(response, 'Field1:</label>')
     2640        self.assertContains(response, 'Field2:</label>')
     2641        self.assertContains(response, 'Set1')
     2642        self.assertContains(response, 'Field3:</label>')
     2643        self.assertContains(response, 'Field4:</label>')
     2644        self.assertContains(response, 'Set2')
     2645        self.assertContains(response, 'Field5:</label>')
     2646        self.assertContains(response, 'Field6:</label>')
     2647        self.assertContains(response, 'Set3')
     2648        self.assertContains(response, 'Field7:</label>')
     2649        self.assertContains(response, 'Field8:</label>')
     2650
    26222651    def test_readonly_post(self):
    26232652        data = {
    26242653            "title": "Django Got Readonly Fields",
Back to Top