Django

Code

Changeset 6080

Show
Ignore:
Timestamp:
09/09/07 19:27:48 (1 year ago)
Author:
jkocherhans
Message:

newforms-admin: Changed the 'fields' option on ModelAdmin? to 'fieldsets'. 'fields' is still valid, but should be a list of field names instead. Also, added some new hooks that were needed to support the change.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/newforms-admin/django/contrib/admin/options.py

    r6074 r6080  
    3737    return "".join(res) 
    3838 
     39def flatten_fieldsets(fieldsets): 
     40    """Returns a list of field names from an admin fieldsets structure.""" 
     41    field_names = [] 
     42    for name, opts in fieldsets: 
     43        for field in opts['fields']: 
     44            # type checking feels dirty, but it seems like the best way here 
     45            if type(field) == tuple: 
     46                field_names.extend(field) 
     47            else: 
     48                field_names.append(field) 
     49    return field_names 
     50 
    3951class AdminForm(object): 
    4052    def __init__(self, form, fieldsets, prepopulated_fields): 
     
    4355 
    4456    def __iter__(self): 
    45         for fieldset in self.fieldsets: 
    46             yield BoundFieldset(self.form, fieldset
     57        for name, options in self.fieldsets: 
     58            yield Fieldset(self.form, name, **options
    4759 
    4860    def first_field(self): 
    4961        for bf in self.form: 
    5062            return bf 
    51              
     63 
    5264    def _media(self): 
    5365        media = self.form.media 
    54         for fs in self.fieldsets
     66        for fs in self
    5567            media = media + fs.media 
    5668        return media 
     
    5870 
    5971class Fieldset(object): 
    60     def __init__(self, name=None, fields=(), classes=(), description=None): 
     72    def __init__(self, form, name=None, fields=(), classes=(), description=None): 
     73        self.form = form 
    6174        self.name, self.fields = name, fields 
    6275        self.classes = u' '.join(classes) 
     
    6982        return forms.Media() 
    7083    media = property(_media) 
    71      
    72 class BoundFieldset(object): 
    73     def __init__(self, form, fieldset): 
    74         self.form, self.fieldset = form, fieldset 
    7584 
    7685    def __iter__(self): 
    77         for field in self.fieldset.fields
    78             yield BoundFieldline(self.form, field) 
    79  
    80 class BoundFieldline(object): 
     86        for field in self.fields
     87            yield Fieldline(self.form, field) 
     88 
     89class Fieldline(object): 
    8190    def __init__(self, form, field): 
    8291        self.form = form # A django.forms.Form instance 
     
    8897    def __iter__(self): 
    8998        for i, field in enumerate(self.fields): 
    90             yield BoundField(self.form, field, is_first=(i == 0)) 
     99            yield AdminField(self.form, field, is_first=(i == 0)) 
    91100 
    92101    def errors(self): 
    93102        return u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]) 
    94103 
    95 class BoundField(object): 
     104class AdminField(object): 
    96105    def __init__(self, form, field, is_first): 
    97106        self.field = form[field] # A django.forms.BoundField instance 
     
    117126    raw_id_fields = () 
    118127    fields = None 
     128    fieldsets = None 
    119129    filter_vertical = () 
    120130    filter_horizontal = () 
    121131    prepopulated_fields = {} 
     132 
     133    def __init__(self): 
     134        # TODO: This should really go in django.core.validation, but validation 
     135        # doesn't work on ModelAdmin classes yet. 
     136        if self.fieldsets and self.fields: 
     137            raise ImproperlyConfigured('Both fieldsets and fields is specified for %s.' % self.model) 
    122138 
    123139    def formfield_for_dbfield(self, db_field, **kwargs): 
     
    164180        return db_field.formfield(**kwargs) 
    165181 
    166     def fieldsets(self, request): 
    167         """ 
    168         Generator that yields Fieldset objects for use on add and change admin 
    169         form pages. 
    170  
    171         This default implementation looks at self.fields, but subclasses can 
    172         override this implementation and do something special based on the 
    173         given HttpRequest object. 
    174         """ 
    175         if self.fields is None: 
    176             default_fields = [f.name for f in self.opts.fields + self.opts.many_to_many if f.editable and not isinstance(f, models.AutoField)] 
    177             yield Fieldset(fields=default_fields) 
    178         else: 
    179             for name, options in self.fields: 
    180                 yield Fieldset(name, options['fields'], classes=options.get('classes', '').split(' '), description=options.get('description')) 
     182    def _fieldsets(self, request): 
     183        if self.fieldsets: 
     184            return self.fieldsets 
     185        if self.fields: 
     186            return [(None, {'fields': self.fields})] 
     187        # TODO: switch this to pull from the form, not the model 
     188        fields = [f.name for f in self.opts.fields + self.opts.many_to_many if f.editable and not isinstance(f, models.AutoField)] 
     189        return [(None, {'fields': fields})] 
     190 
     191    def fieldsets_add(self, request): 
     192        "Hook for specifying fieldsets for the add form." 
     193        return list(self._fieldsets(request)) 
     194 
     195    def fieldsets_change(self, request, obj): 
     196        "Hook for specifying fieldsets for the change form." 
     197        return list(self._fieldsets(request)) 
    181198 
    182199class ModelAdmin(BaseModelAdmin): 
     
    204221            inline_instance = inline_class(self.model, self.admin_site) 
    205222            self.inline_instances.append(inline_instance) 
     223        super(ModelAdmin, self).__init__() 
    206224 
    207225    def __call__(self, request, url): 
     
    244262    media = property(_media) 
    245263     
    246     def fieldsets_add(self, request): 
    247         "Hook for specifying Fieldsets for the add form." 
    248         return list(self.fieldsets(request)) 
    249  
    250     def fieldsets_change(self, request, obj): 
    251         "Hook for specifying Fieldsets for the change form." 
    252         return list(self.fieldsets(request)) 
    253  
    254264    def has_add_permission(self, request): 
    255265        "Returns True if the given request has permission to add an object." 
     
    414424            post_url = '../../../' 
    415425 
    416         ModelForm = forms.form_for_model(model, formfield_callback=self.formfield_for_dbfield) 
     426        fields = flatten_fieldsets(self.fieldsets_add(request)) 
     427        ModelForm = forms.form_for_model(model, fields=fields, formfield_callback=self.formfield_for_dbfield) 
    417428 
    418429        inline_formsets = [] 
    419430        if request.method == 'POST': 
    420431            form = ModelForm(request.POST, request.FILES) 
    421             for FormSet in self.get_inline_formsets(): 
     432            for FormSet in self.formsets_add(request): 
    422433                inline_formset = FormSet(data=request.POST, files=request.FILES) 
    423434                inline_formsets.append(inline_formset) 
     
    426437        else: 
    427438            form = ModelForm(initial=request.GET) 
    428             for FormSet in self.get_inline_formsets(): 
     439            for FormSet in self.formsets_add(request): 
    429440                inline_formset = FormSet() 
    430441                inline_formsets.append(inline_formset) 
     
    437448        inline_admin_formsets = [] 
    438449        for inline, formset in zip(self.inline_instances, inline_formsets): 
    439             fieldsets = list(inline.fieldsets(request)) 
     450            fieldsets = list(inline.fieldsets_add(request)) 
    440451            inline_admin_formset = InlineAdminFormSet(inline, formset, fieldsets) 
    441452            inline_admin_formsets.append(inline_admin_formset) 
     
    475486            return self.add_view(request, form_url='../../add/') 
    476487 
    477         ModelForm = forms.form_for_instance(obj, formfield_callback=self.formfield_for_dbfield) 
     488        fields = flatten_fieldsets(self.fieldsets_change(request, obj)) 
     489        ModelForm = forms.form_for_instance(obj, fields=fields, formfield_callback=self.formfield_for_dbfield) 
    478490 
    479491        inline_formsets = [] 
    480492        if request.method == 'POST': 
    481493            form = ModelForm(request.POST, request.FILES) 
    482             for FormSet in self.get_inline_formsets(): 
     494            for FormSet in self.formsets_change(request, obj): 
    483495                inline_formset = FormSet(obj, request.POST, request.FILES) 
    484496                inline_formsets.append(inline_formset) 
     
    488500        else: 
    489501            form = ModelForm() 
    490             for FormSet in self.get_inline_formsets(): 
     502            for FormSet in self.formsets_change(request, obj): 
    491503                inline_formset = FormSet(obj) 
    492504                inline_formsets.append(inline_formset) 
     
    506518                #oldform.order_objects.extend(orig_list) 
    507519                 
    508         adminForm = AdminForm(form, self.fieldsets_change(request, obj), self.prepopulated_fields)         
     520        adminForm = AdminForm(form, self.fieldsets_change(request, obj), self.prepopulated_fields) 
    509521        media = self.media + adminForm.media 
    510522        for fs in inline_formsets: 
     
    513525        inline_admin_formsets = [] 
    514526        for inline, formset in zip(self.inline_instances, inline_formsets): 
    515             fieldsets = list(inline.fieldsets(request)) 
     527            fieldsets = list(inline.fieldsets_change(request, obj)) 
    516528            inline_admin_formset = InlineAdminFormSet(inline, formset, fieldsets) 
    517529            inline_admin_formsets.append(inline_admin_formset) 
     
    627639        return render_to_response(template_list, extra_context, context_instance=template.RequestContext(request)) 
    628640 
    629     def get_inline_formsets(self): 
     641    def formsets_add(self, request): 
    630642        for inline in self.inline_instances: 
    631             yield inline.formset_class 
     643            yield inline.formset_add(request) 
     644 
     645    def formsets_change(self, request, obj): 
     646        for inline in self.inline_instances: 
     647            yield inline.formset_change(request, obj) 
    632648 
    633649class InlineModelAdmin(BaseModelAdmin): 
     
    649665        self.parent_model = parent_model 
    650666        self.opts = self.model._meta 
    651         # TODO: pass a fields arg into forms.inline_formset if/when we have one 
    652         self.formset_class = forms.inline_formset(parent_model, self.model, fk_name=self.fk_name, formfield_callback=self.formfield_for_dbfield, extra=self.extra) 
    653  
    654     def fieldsets(self, request): 
    655         """ 
    656         Generator that yields Fieldset objects for use on add and change admin 
    657         form pages. 
    658  
    659         This default implementation looks at self.fields, but subclasses can 
    660         override this implementation and do something special based on the 
    661         given HttpRequest object. 
    662         """ 
    663         if self.fields is None: 
    664             yield Fieldset(fields=self.formset_class.form_class.base_fields) 
    665         else: 
    666             for name, options in self.fields: 
    667                 yield Fieldset(name, options['fields'], classes=options.get('classes', '').split(' '), description=options.get('description')) 
     667        super(InlineModelAdmin, self).__init__() 
     668 
     669    def formset_add(self, request): 
     670        """Returns an InlineFormSet class for use in admin add views.""" 
     671        fields = flatten_fieldsets(self.fieldsets_add(request)) 
     672        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) 
     673 
     674    def formset_change(self, request, obj): 
     675        """Returns an InlineFormSet class for use in admin change views.""" 
     676        fields = flatten_fieldsets(self.fieldsets_change(request, obj)) 
     677        return forms.inline_formset(self.parent_model, self.model, fk_name=self.fk_name, fields=fields, formfield_callback=self.formfield_for_dbfield, extra=self.extra) 
     678 
     679    def _fieldsets(self, request): 
     680        if self.fieldsets: 
     681            return self.fieldsets 
     682        if self.fields: 
     683            return [(None, {'fields': self.fields})] 
     684        fields = [f for f in self.formset_class(request).form_class.base_fields.keys()] 
     685        return [(None, {'fields': fields})] 
    668686 
    669687class StackedInline(InlineModelAdmin): 
     
    695713 
    696714    def fields(self): 
    697         # TODO: this needs to respect the field order of self.fieldsets 
    698         return self.formset.form_class.base_fields.values() 
     715        for field_name in flatten_fieldsets(self.fieldsets): 
     716            yield self.formset.form_class.base_fields[field_name] 
    699717 
    700718class InlineAdminForm(AdminForm): 
     
    708726 
    709727    def pk_field(self): 
    710         return BoundField(self.form, self.formset._pk_field_name, False) 
     728        return AdminField(self.form, self.formset._pk_field_name, False) 
    711729 
    712730    def deletion_field(self): 
    713731        from django.newforms.formsets import DELETION_FIELD_NAME 
    714         return BoundField(self.form, DELETION_FIELD_NAME, False) 
     732        return AdminField(self.form, DELETION_FIELD_NAME, False) 
    715733 
    716734    def ordering_field(self): 
    717735        from django.newforms.formsets import ORDERING_FIELD_NAME 
    718         return BoundField(self.form, ORDERING_FIELD_NAME, False) 
     736        return AdminField(self.form, ORDERING_FIELD_NAME, False) 
  • django/branches/newforms-admin/django/contrib/admin/templates/admin/change_form.html

    r6073 r6080  
    4141{% endif %} 
    4242 
    43 {% for bfset in adminform %} 
    44     <fieldset class="module aligned {{ bfset.fieldset.classes }}"> 
    45     {% if bfset.fieldset.name %}<h2>{{ bfset.fieldset.name }}</h2>{% endif %} 
    46     {% if bfset.fieldset.description %}<div class="description">{{ bfset.fieldset.description }}</div>{% endif %} 
    47     {% for line in bfset %} 
     43{% for fieldset in adminform %} 
     44    <fieldset class="module aligned {{ fieldset.classes }}"> 
     45    {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %} 
     46    {% if fieldset.description %}<div class="description">{{ fieldset.description }}</div>{% endif %} 
     47    {% for line in fieldset %} 
    4848        <div class="form-row{% if line.errors %} errors{% endif %}"> 
    4949        {{ line.errors }} 
  • django/branches/newforms-admin/django/contrib/admin/templates/admin/edit_inline_tabular.html

    r6072 r6080  
    2626        {{ inline_admin_form.pk_field.field }} 
    2727        {% if inline_admin_formset.formset.deletable %}<td>{{ inline_admin_form.deletion_field.field }}</td>{% endif %} 
    28         {% for bfset in inline_admin_form %} 
    29           {% for line in bfset %} 
     28        {% for fieldset in inline_admin_form %} 
     29          {% for line in fieldset %} 
    3030            {% for field in line %} 
    3131              <td>{{ field.field }}</td>