Django

Code

Changeset 5498

Show
Ignore:
Timestamp:
06/20/07 01:09:33 (2 years ago)
Author:
jkocherhans
Message:

newforms-admin: Extracted a base class for functionality common to both inlines and ModelAdmin?.

Files:

Legend:

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

    r5479 r5498  
    9797        return self.field.label_tag(contents=contents, attrs=attrs) 
    9898 
    99 class InlineOptions(object): 
    100     """ 
    101     Options for inline editing of ``model`` instances. 
    102      
    103     Provide ``name`` to specify the attribute name of the ``ForeignKey`` from 
    104     ``model`` to its parent. This is required if ``model`` has more than one 
    105     ``ForeignKey`` to its parent. 
    106     """ 
    107     def __init__(self, model, name=None, extra=3, fields=None, template=None, formfield_callback=lambda f: f.formfield()): 
    108         self.model = model 
    109         self.name = name 
    110         self.extra = extra 
    111         self.fields = fields 
    112         self.template = template or self.default_template 
    113         self.verbose_name = model._meta.verbose_name 
    114         self.verbose_name_plural = model._meta.verbose_name_plural 
    115         self.prepopulated_fields = {} 
    116         self.formfield_callback = formfield_callback 
    117  
    118 class StackedInline(InlineOptions): 
    119     default_template = 'admin/edit_inline_stacked.html' 
    120  
    121 class TabularInline(InlineOptions): 
    122     default_template = 'admin/edit_inline_tabular.html' 
    123  
    124 class BoundInline(object): 
    125     def __init__(self, opts, formset): 
    126         self.opts = opts 
    127         self.formset = formset 
    128  
    129     def __iter__(self): 
    130         for form, original in zip(self.formset.change_forms, self.formset.get_inline_objects()): 
    131             yield BoundInlineObject(form, original, self.opts) 
    132         for form in self.formset.add_forms: 
    133             yield BoundInlineObject(form, None, self.opts) 
    134  
    135     def fields(self): 
    136         # HACK: each form instance has some extra fields. Getting those fields 
    137         # from the form class will take some rearranging. Get them from the  
    138         # first form instance for now. 
    139         return list(self.formset.forms[0]) 
    140  
    141     def verbose_name(self): 
    142         return self.opts.verbose_name 
    143  
    144     def verbose_name_plural(self): 
    145         return self.opts.verbose_name_plural 
    146  
    147 class BoundInlineObject(object): 
    148     def __init__(self, form, original, opts): 
    149         self.opts = opts 
    150         self.base_form = form 
    151         self.form = AdminForm(form, self.fieldsets(), opts.prepopulated_fields) 
    152         self.original = original 
    153  
    154     def fieldsets(self): 
    155         """ 
    156         Generator that yields Fieldset objects for use on add and change admin 
    157         form pages. 
    158  
    159         This default implementation looks at self.fields, but subclasses can 
    160         override this implementation and do something special based on the 
    161         given HttpRequest object. 
    162         """ 
    163         if self.opts.fields is None: 
    164             default_fields = [f for f in self.base_form.fields] 
    165             yield Fieldset(fields=default_fields) 
    166         else: 
    167             for name, options in self.opts.fields: 
    168                 yield Fieldset(name, options['fields'], classes=options.get('classes', '').split(' '), description=options.get('description')) 
    169  
    170 class ModelAdmin(object): 
     99class BaseModelAdmin(object): 
     100    """Functionality common to both ModelAdmin and InlineAdmin.""" 
     101    raw_id_fields = () 
     102    fields = None 
     103 
     104    def formfield_for_dbfield(self, db_field, **kwargs): 
     105        """ 
     106        Hook for specifying the form Field instance for a given database Field 
     107        instance. 
     108 
     109        If kwargs are given, they're passed to the form Field's constructor. 
     110        """ 
     111        # For ManyToManyFields with a filter interface, use a special Widget. 
     112        if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal): 
     113            kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) 
     114            return db_field.formfield(**kwargs) 
     115 
     116        # For DateTimeFields, use a special field and widget. 
     117        if isinstance(db_field, models.DateTimeField): 
     118            return forms.SplitDateTimeField(required=not db_field.blank, 
     119                widget=widgets.AdminSplitDateTime(), label=capfirst(db_field.verbose_name), 
     120                help_text=db_field.help_text, **kwargs) 
     121 
     122        # For DateFields, add a custom CSS class. 
     123        if isinstance(db_field, models.DateField): 
     124            kwargs['widget'] = forms.TextInput(attrs={'class': 'vDateField', 'size': '10'}) 
     125            return db_field.formfield(**kwargs) 
     126 
     127        # For TimeFields, add a custom CSS class. 
     128        if isinstance(db_field, models.TimeField): 
     129            kwargs['widget'] = forms.TextInput(attrs={'class': 'vTimeField', 'size': '8'}) 
     130            return db_field.formfield(**kwargs) 
     131 
     132        # For ForeignKey or ManyToManyFields, use a special widget. 
     133        if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): 
     134            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: 
     135                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) 
     136                return db_field.formfield(**kwargs) 
     137            else: 
     138                # Wrap the widget's render() method with a method that adds 
     139                # extra HTML to the end of the rendered output. 
     140                formfield = db_field.formfield(**kwargs) 
     141                formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel) 
     142                return formfield 
     143 
     144        # For any other type of field, just call its formfield() method. 
     145        return db_field.formfield(**kwargs) 
     146 
     147class ModelAdmin(BaseModelAdmin): 
    171148    "Encapsulates all admin options and functionality for a given model." 
    172149 
     
    182159    ordering = None 
    183160    js = None 
    184     fields = None 
    185     raw_id_fields = () 
    186161    prepopulated_fields = {} 
    187162    filter_vertical = () 
     
    275250        for fs in self.fieldsets(request): 
    276251            yield fs 
    277  
    278     def formfield_for_dbfield(self, db_field, **kwargs): 
    279         """ 
    280         Hook for specifying the form Field instance for a given database Field 
    281         instance. 
    282  
    283         If kwargs are given, they're passed to the form Field's constructor. 
    284         """ 
    285         # For ManyToManyFields with a filter interface, use a special Widget. 
    286         if isinstance(db_field, models.ManyToManyField) and db_field.name in (self.filter_vertical + self.filter_horizontal): 
    287             kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) 
    288             return db_field.formfield(**kwargs) 
    289  
    290         # For DateTimeFields, use a special field and widget. 
    291         if isinstance(db_field, models.DateTimeField): 
    292             return forms.SplitDateTimeField(required=not db_field.blank, 
    293                 widget=widgets.AdminSplitDateTime(), label=capfirst(db_field.verbose_name), 
    294                 help_text=db_field.help_text, **kwargs) 
    295  
    296         # For DateFields, add a custom CSS class. 
    297         if isinstance(db_field, models.DateField): 
    298             kwargs['widget'] = forms.TextInput(attrs={'class': 'vDateField', 'size': '10'}) 
    299             return db_field.formfield(**kwargs) 
    300  
    301         # For TimeFields, add a custom CSS class. 
    302         if isinstance(db_field, models.TimeField): 
    303             kwargs['widget'] = forms.TextInput(attrs={'class': 'vTimeField', 'size': '8'}) 
    304             return db_field.formfield(**kwargs) 
    305  
    306         # For ForeignKey or ManyToManyFields, use a special widget. 
    307         if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): 
    308             if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: 
    309                 kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) 
    310                 return db_field.formfield(**kwargs) 
    311             else: 
    312                 # Wrap the widget's render() method with a method that adds 
    313                 # extra HTML to the end of the rendered output. 
    314                 formfield = db_field.formfield(**kwargs) 
    315                 formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel) 
    316                 return formfield 
    317  
    318         # For any other type of field, just call its formfield() method. 
    319         return db_field.formfield(**kwargs) 
    320252 
    321253    def has_add_permission(self, request): 
     
    680612        inline_formset_classes = [] 
    681613        for opts in self.inlines: 
    682             inline = inline_formset(self.model, opts.model, formfield_callback=self.formfield_for_dbfield, fields=opts.fields, extra=opts.extra) 
     614            inline = inline_formset(self.model, opts.model, formfield_callback=opts.formfield_for_dbfield, fields=opts.fields, extra=opts.extra) 
    683615            inline_formset_classes.append(inline) 
    684616        return inline_formset_classes 
     617 
     618class InlineModelAdmin(BaseModelAdmin): 
     619    """ 
     620    Options for inline editing of ``model`` instances. 
     621     
     622    Provide ``name`` to specify the attribute name of the ``ForeignKey`` from 
     623    ``model`` to its parent. This is required if ``model`` has more than one 
     624    ``ForeignKey`` to its parent. 
     625    """ 
     626    def __init__(self, model, name=None, extra=3, fields=None, template=None): 
     627        self.model = model 
     628        self.opts = model._meta 
     629        self.name = name 
     630        self.extra = extra 
     631        self.fields = fields 
     632        self.template = template or self.default_template 
     633        self.verbose_name = model._meta.verbose_name 
     634        self.verbose_name_plural = model._meta.verbose_name_plural 
     635        self.prepopulated_fields = {} 
     636 
     637class StackedInline(InlineModelAdmin): 
     638    default_template = 'admin/edit_inline_stacked.html' 
     639 
     640class TabularInline(InlineModelAdmin): 
     641    default_template = 'admin/edit_inline_tabular.html' 
     642 
     643class BoundInline(object): 
     644    def __init__(self, inline_admin, formset): 
     645        self.inline_admin = inline_admin 
     646        self.formset = formset 
     647        self.template = inline_admin.template 
     648 
     649    def __iter__(self): 
     650        for form, original in zip(self.formset.change_forms, self.formset.get_inline_objects()): 
     651            yield BoundInlineObject(form, original, self.inline_admin) 
     652        for form in self.formset.add_forms: 
     653            yield BoundInlineObject(form, None, self.inline_admin) 
     654 
     655    def fields(self): 
     656        # HACK: each form instance has some extra fields. Getting those fields 
     657        # from the form class will take some rearranging. Get them from the  
     658        # first form instance for now. 
     659        return list(self.formset.forms[0]) 
     660 
     661    def verbose_name(self): 
     662        return self.inline_admin.verbose_name 
     663 
     664    def verbose_name_plural(self): 
     665        return self.inline_admin.verbose_name_plural 
     666 
     667class BoundInlineObject(object): 
     668    def __init__(self, form, original, inline_admin): 
     669        self.inline_admin = inline_admin 
     670        self.base_form = form 
     671        self.form = AdminForm(form, self.fieldsets(), inline_admin.prepopulated_fields) 
     672        self.original = original 
     673 
     674    def fieldsets(self): 
     675        """ 
     676        Generator that yields Fieldset objects for use on add and change admin 
     677        form pages. 
     678 
     679        This default implementation looks at self.fields, but subclasses can 
     680        override this implementation and do something special based on the 
     681        given HttpRequest object. 
     682        """ 
     683        if self.inline_admin.fields is None: 
     684            default_fields = [f for f in self.base_form.fields] 
     685            yield Fieldset(fields=default_fields) 
     686        else: 
     687            for name, options in self.opts.fields: 
     688                yield Fieldset(name, options['fields'], classes=options.get('classes', '').split(' '), description=options.get('description')) 
  • django/branches/newforms-admin/django/contrib/admin/templatetags/admin_modify.py

    r5473 r5498  
    112112    def render(self, context): 
    113113        inline = context[self.inline_var] 
    114         t = loader.get_template(inline.opts.template) 
     114        t = loader.get_template(inline.template) 
    115115        output = t.render(context) 
    116116        return output