Django

Code

Changeset 4430

Show
Ignore:
Timestamp:
01/25/07 12:05:10 (2 years ago)
Author:
adrian
Message:

newforms-admin: Backwards-incompatible change: Refactored raw_id_admin. It is no longer a valid attribute for fields. Instead, specify 'raw_id_fields', a list of field names, in the 'class Admin'. Also removed raw_id functionality for ManyToManyFields?, as it was hackish.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/newforms-admin/django/contrib/admin/media/js/admin/RelatedObjectLookups.js

    r3517 r4430  
    1 // Handles related-objects functionality: lookup link for raw_id_admin=True 
     1// Handles related-objects functionality: lookup link for raw_id_fields 
    22// and Add Another links. 
    33 
  • django/branches/newforms-admin/django/contrib/admin/options.py

    r4427 r4430  
    109109    js = None 
    110110    fields = None 
     111    raw_id_fields = () 
    111112 
    112113    def __init__(self, model): 
     
    225226 
    226227        # For ForeignKey or ManyToManyFields, use a special widget. 
    227         if db_field.rel and isinstance(db_field.rel, (models.ManyToOneRel, models.ManyToManyRel)): 
    228             # Wrap the widget's render() method with a method that adds 
    229             # extra HTML to the end of the rendered output. 
    230             formfield = db_field.formfield(**kwargs) 
    231             formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel) 
    232             return formfield 
     228        if isinstance(db_field, (models.ForeignKey, models.ManyToManyField)): 
     229            if isinstance(db_field, models.ForeignKey) and db_field.name in self.raw_id_fields: 
     230                kwargs['widget'] = widgets.ForeignKeyRawIdWidget(db_field.rel) 
     231                return db_field.formfield(**kwargs) 
     232            else: 
     233                # Wrap the widget's render() method with a method that adds 
     234                # extra HTML to the end of the rendered output. 
     235                formfield = db_field.formfield(**kwargs) 
     236                formfield.widget.render = widgets.RelatedFieldWidgetWrapper(formfield.widget.render, db_field.rel) 
     237                return formfield 
    233238 
    234239        # For any other type of field, just call its formfield() method. 
  • django/branches/newforms-admin/django/contrib/admin/widgets.py

    r4416 r4430  
    44 
    55from django import newforms as forms 
     6from django.newforms.util import smart_unicode 
     7from django.utils.text import capfirst 
    68 
    79class FilteredSelectMultiple(forms.SelectMultiple): 
     
    4244            (_('Date:'), rendered_widgets[0], _('Time:'), rendered_widgets[1]) 
    4345 
     46class ForeignKeyRawIdWidget(forms.TextInput): 
     47    """ 
     48    A Widget for displaying ForeignKeys in the "raw_id" interface rather than 
     49    in a <select> box. 
     50    """ 
     51    def __init__(self, rel, attrs=None): 
     52        self.rel = rel 
     53        super(ForeignKeyRawIdWidget, self).__init__(attrs) 
     54 
     55    def render(self, name, value, attrs=None): 
     56        from django.conf import settings 
     57        related_url = '../../../%s/%s/' % (self.rel.to._meta.app_label, self.rel.to._meta.object_name.lower()) 
     58        if self.rel.limit_choices_to: 
     59            url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in self.rel.limit_choices_to.items()]) 
     60        else: 
     61            url = '' 
     62        attrs['class'] = 'vRawIdAdminField' # The JavaScript looks for this hook. 
     63        output = [super(ForeignKeyRawIdWidget, self).render(name, value, attrs)] 
     64        # TODO: "id_" is hard-coded here. This should instead use the correct 
     65        # API to determine the ID dynamically. 
     66        output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \ 
     67            (related_url, url, name)) 
     68        output.append('<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="Lookup"></a>' % settings.ADMIN_MEDIA_PREFIX) 
     69        return u''.join(output) 
     70        #if self.change: # TODO 
     71            #output.append('&nbsp;<strong>TODO</strong>') 
     72 
    4473class RelatedFieldWidgetWrapper(object): 
    4574    """ 
     
    5584        related_url = '../../../%s/%s/' % (rel_to._meta.app_label, rel_to._meta.object_name.lower()) 
    5685        output = [self.render_func(name, value, *args, **kwargs)] 
    57         if self.rel.raw_id_admin: 
    58             if self.rel.limit_choices_to: 
    59                 url = '?' + '&amp;'.join(['%s=%s' % (k, v) for k, v in self.rel.limit_choices_to.items()]) 
    60             else: 
    61                 url = '' 
    62             # TODO: "id_" is hard-coded here. This should instead use the correct 
    63             # API to determine the ID dynamically. 
    64             output.append('<a href="%s%s" class="related-lookup" id="lookup_id_%s" onclick="return showRelatedObjectLookupPopup(this);"> ' % \ 
    65                 (related_url, url, name)) 
    66             output.append('<img src="%simg/admin/selector-search.gif" width="16" height="16" alt="Lookup"></a>' % settings.ADMIN_MEDIA_PREFIX) 
    67             #if self.change: # TODO 
    68                 #output.append('&nbsp;<strong>TODO</strong>') 
    69         elif rel_to._meta.admin: # If the related object has an admin interface: 
     86        if rel_to._meta.admin: # If the related object has an admin interface: 
    7087            # TODO: "id_" is hard-coded here. This should instead use the correct 
    7188            # API to determine the ID dynamically. 
  • django/branches/newforms-admin/django/contrib/comments/models.py

    r4265 r4430  
    6363 
    6464class Comment(models.Model): 
    65     user = models.ForeignKey(User, raw_id_admin=True
     65    user = models.ForeignKey(User
    6666    content_type = models.ForeignKey(ContentType) 
    6767    object_id = models.IntegerField(_('object ID')) 
     
    102102        date_hierarchy = 'submit_date' 
    103103        search_fields = ('comment', 'user__username') 
     104        raw_id_fields = ('user',) 
    104105 
    105106    def __repr__(self): 
  • django/branches/newforms-admin/django/db/models/fields/generic.py

    r4265 r4430  
    1717    fields. 
    1818    """ 
    19      
     19 
    2020    def __init__(self, ct_field="content_type", fk_field="object_id"): 
    2121        self.ct_field = ct_field 
    2222        self.fk_field = fk_field 
    23          
     23 
    2424    def contribute_to_class(self, cls, name): 
    25         # Make sure the fields exist (these raise FieldDoesNotExist,  
     25        # Make sure the fields exist (these raise FieldDoesNotExist, 
    2626        # which is a fine error to raise here) 
    2727        self.name = name 
    2828        self.model = cls 
    2929        self.cache_attr = "_%s_cache" % name 
    30          
     30 
    3131        # For some reason I don't totally understand, using weakrefs here doesn't work. 
    3232        dispatcher.connect(self.instance_pre_init, signal=signals.pre_init, sender=cls, weak=False) 
     
    3636 
    3737    def instance_pre_init(self, signal, sender, args, kwargs): 
    38         # Handle initalizing an object with the generic FK instaed of  
    39         # content-type/object-id fields.         
     38        # Handle initalizing an object with the generic FK instaed of 
     39        # content-type/object-id fields. 
    4040        if kwargs.has_key(self.name): 
    4141            value = kwargs.pop(self.name) 
    4242            kwargs[self.ct_field] = self.get_content_type(value) 
    4343            kwargs[self.fk_field] = value._get_pk_val() 
    44              
     44 
    4545    def get_content_type(self, obj): 
    4646        # Convenience function using get_model avoids a circular import when using this model 
    4747        ContentType = get_model("contenttypes", "contenttype") 
    4848        return ContentType.objects.get_for_model(obj) 
    49          
     49 
    5050    def __get__(self, instance, instance_type=None): 
    5151        if instance is None: 
     
    7878        setattr(instance, self.fk_field, fk) 
    7979        setattr(instance, self.cache_attr, value) 
    80      
     80 
    8181class GenericRelation(RelatedField, Field): 
    8282    """Provides an accessor to generic related objects (i.e. comments)""" 
     
    8484    def __init__(self, to, **kwargs): 
    8585        kwargs['verbose_name'] = kwargs.get('verbose_name', None) 
    86         kwargs['rel'] = GenericRel(to,  
     86        kwargs['rel'] = GenericRel(to, 
    8787                            related_name=kwargs.pop('related_name', None), 
    8888                            limit_choices_to=kwargs.pop('limit_choices_to', None), 
    8989                            symmetrical=kwargs.pop('symmetrical', True)) 
    90                              
     90 
    9191        # Override content-type/object-id field names on the related class 
    9292        self.object_id_field_name = kwargs.pop("object_id_field", "object_id") 
    93         self.content_type_field_name = kwargs.pop("content_type_field", "content_type")                 
    94          
     93        self.content_type_field_name = kwargs.pop("content_type_field", "content_type") 
     94 
    9595        kwargs['blank'] = True 
    9696        kwargs['editable'] = False 
     
    116116    def m2m_column_name(self): 
    117117        return self.object_id_field_name 
    118          
     118 
    119119    def m2m_reverse_name(self): 
    120120        return self.object_id_field_name 
     
    131131    def contribute_to_related_class(self, cls, related): 
    132132        pass 
    133          
     133 
    134134    def set_attributes_from_rel(self): 
    135135        pass 
     
    137137    def get_internal_type(self): 
    138138        return "ManyToManyField" 
    139          
     139 
    140140class ReverseGenericRelatedObjectsDescriptor(object): 
    141141    """ 
     
    191191    Manager) and adds behavior for generic related objects. 
    192192    """ 
    193      
     193 
    194194    class GenericRelatedObjectManager(superclass): 
    195195        def __init__(self, model=None, core_filters=None, instance=None, symmetrical=None, 
    196196                     join_table=None, source_col_name=None, target_col_name=None, content_type=None, 
    197197                     content_type_field_name=None, object_id_field_name=None): 
    198              
     198 
    199199            super(GenericRelatedObjectManager, self).__init__() 
    200200            self.core_filters = core_filters or {} 
     
    210210            self.object_id_field_name = object_id_field_name 
    211211            self.pk_val = self.instance._get_pk_val() 
    212                          
     212 
    213213        def get_query_set(self): 
    214214            query = { 
    215                 '%s__pk' % self.content_type_field_name : self.content_type.id,  
     215                '%s__pk' % self.content_type_field_name : self.content_type.id, 
    216216                '%s__exact' % self.object_id_field_name : self.pk_val, 
    217217            } 
     
    253253        self.limit_choices_to = limit_choices_to or {} 
    254254        self.edit_inline = False 
    255         self.raw_id_admin = False 
    256255        self.symmetrical = symmetrical 
    257256        self.multiple = True 
    258         assert not (self.raw_id_admin and self.filter_interface), \ 
    259             "Generic relations may not use both raw_id_admin and filter_interface" 
  • django/branches/newforms-admin/django/db/models/fields/related.py

    r4390 r4430  
    484484            related_name=kwargs.pop('related_name', None), 
    485485            limit_choices_to=kwargs.pop('limit_choices_to', None), 
    486             lookup_overrides=kwargs.pop('lookup_overrides', None), 
    487             raw_id_admin=kwargs.pop('raw_id_admin', False)) 
     486            lookup_overrides=kwargs.pop('lookup_overrides', None)) 
    488487        Field.__init__(self, **kwargs) 
    489488 
     
    498497    def prepare_field_objs_and_params(self, manipulator, name_prefix): 
    499498        params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname} 
    500         if self.rel.raw_id_admin: 
    501             field_objs = self.get_manipulator_field_objs() 
    502             params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator)) 
    503         else: 
    504             if self.radio_admin: 
    505                 field_objs = [oldforms.RadioSelectField] 
    506                 params['ul_class'] = get_ul_class(self.radio_admin) 
     499        if self.radio_admin: 
     500            field_objs = [oldforms.RadioSelectField] 
     501            params['ul_class'] = get_ul_class(self.radio_admin) 
     502        else: 
     503            if self.null: 
     504                field_objs = [oldforms.NullSelectField] 
    507505            else: 
    508                 if self.null: 
    509                     field_objs = [oldforms.NullSelectField] 
    510                 else: 
    511                     field_objs = [oldforms.SelectField] 
    512             params['choices'] = self.get_choices_default() 
     506                field_objs = [oldforms.SelectField] 
     507        params['choices'] = self.get_choices_default() 
    513508        return field_objs, params 
    514509 
    515510    def get_manipulator_field_objs(self): 
    516511        rel_field = self.rel.get_related_field() 
    517         if self.rel.raw_id_admin and not isinstance(rel_field, AutoField): 
    518             return rel_field.get_manipulator_field_objs() 
    519         else: 
    520             return [oldforms.IntegerField] 
     512        return [oldforms.IntegerField] 
    521513 
    522514    def get_db_prep_save(self, value): 
     
    534526            # "blank" value. Otherwise (radio_admin=True), we check that the 
    535527            # length is 1. 
    536             if not self.blank and (not self.rel.raw_id_admin or self.choices)
     528            if not self.blank and self.choices
    537529                choice_list = self.get_choices_default() 
    538530                if self.radio_admin and len(choice_list) == 1: 
     
    574566            related_name=kwargs.pop('related_name', None), 
    575567            limit_choices_to=kwargs.pop('limit_choices_to', None), 
    576             lookup_overrides=kwargs.pop('lookup_overrides', None), 
    577             raw_id_admin=kwargs.pop('raw_id_admin', False)) 
     568            lookup_overrides=kwargs.pop('lookup_overrides', None)) 
    578569        kwargs['primary_key'] = True 
    579570        IntegerField.__init__(self, **kwargs) 
     
    591582    def prepare_field_objs_and_params(self, manipulator, name_prefix): 
    592583        params = {'validator_list': self.validator_list[:], 'member_name': name_prefix + self.attname} 
    593         if self.rel.raw_id_admin: 
    594             field_objs = self.get_manipulator_field_objs() 
    595             params['validator_list'].append(curry(manipulator_valid_rel_key, self, manipulator)) 
    596         else: 
    597             if self.radio_admin: 
    598                 field_objs = [oldforms.RadioSelectField] 
    599                 params['ul_class'] = get_ul_class(self.radio_admin) 
     584        if self.radio_admin: 
     585            field_objs = [oldforms.RadioSelectField] 
     586            params['ul_class'] = get_ul_class(self.radio_admin) 
     587        else: 
     588            if self.null: 
     589                field_objs = [oldforms.NullSelectField] 
    600590            else: 
    601                 if self.null: 
    602                     field_objs = [oldforms.NullSelectField] 
    603                 else: 
    604                     field_objs = [oldforms.SelectField] 
    605             params['choices'] = self.get_choices_default() 
     591                field_objs = [oldforms.SelectField] 
     592        params['choices'] = self.get_choices_default() 
    606593        return field_objs, params 
    607594 
     
    628615            filter_interface=kwargs.pop('filter_interface', None), 
    629616            limit_choices_to=kwargs.pop('limit_choices_to', None), 
    630             raw_id_admin=kwargs.pop('raw_id_admin', False), 
    631617            symmetrical=kwargs.pop('symmetrical', True)) 
    632         if kwargs["rel"].raw_id_admin: 
    633             kwargs.setdefault("validator_list", []).append(self.isValidIDList) 
    634618        Field.__init__(self, **kwargs) 
    635619 
    636         if self.rel.raw_id_admin: 
    637             msg = gettext_lazy('Separate multiple IDs with commas.') 
    638         else: 
    639             msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.') 
     620        msg = gettext_lazy('Hold down "Control", or "Command" on a Mac, to select more than one.') 
    640621        self.help_text = string_concat(self.help_text, ' ', msg) 
    641622 
    642623    def get_manipulator_field_objs(self): 
    643         if self.rel.raw_id_admin: 
    644             return [oldforms.RawIdAdminField] 
    645         else: 
    646             choices = self.get_choices_default() 
    647             return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)] 
     624        choices = self.get_choices_default() 
     625        return [curry(oldforms.SelectMultipleField, size=min(max(len(choices), 5), 15), choices=choices)] 
    648626 
    649627    def get_choices_default(self): 
     
    691669        if obj: 
    692670            instance_ids = [instance._get_pk_val() for instance in getattr(obj, self.name).all()] 
    693             if self.rel.raw_id_admin: 
    694                 new_data[self.name] = ",".join([str(id) for id in instance_ids]) 
    695             else: 
    696                 new_data[self.name] = instance_ids 
     671            new_data[self.name] = instance_ids 
    697672        else: 
    698673            # In required many-to-many fields with only one available choice, 
    699674            # select that one available choice. 
    700             if not self.blank and not self.rel.edit_inline and not self.rel.raw_id_admin
     675            if not self.blank and not self.rel.edit_inline
    701676                choices_list = self.get_choices_default() 
    702677                if len(choices_list) == 1: 
     
    742717    def __init__(self, to, field_name, num_in_admin=3, min_num_in_admin=None, 
    743718        max_num_in_admin=None, num_extra_on_change=1, edit_inline=False, 
    744         related_name=None, limit_choices_to=None, lookup_overrides=None, raw_id_admin=False): 
     719        related_name=None, limit_choices_to=None, lookup_overrides=None): 
    745720        try: 
    746721            to._meta 
     
    755730        self.limit_choices_to = limit_choices_to 
    756731        self.lookup_overrides = lookup_overrides or {} 
    757         self.raw_id_admin = raw_id_admin 
    758732        self.multiple = True 
    759733 
     
    764738class OneToOneRel(ManyToOneRel): 
    765739    def __init__(self, to, field_name, num_in_admin=0, edit_inline=False, 
    766         related_name=None, limit_choices_to=None, lookup_overrides=None, 
    767         raw_id_admin=False): 
     740        related_name=None, limit_choices_to=None, lookup_overrides=None): 
    768741        self.to, self.field_name = to, field_name 
    769742        self.num_in_admin, self.edit_inline = num_in_admin, edit_inline 
     
    773746        self.limit_choices_to = limit_choices_to 
    774747        self.lookup_overrides = lookup_overrides or {} 
    775         self.raw_id_admin = raw_id_admin 
    776748        self.multiple = False 
    777749 
    778750class ManyToManyRel(object): 
    779751    def __init__(self, to, num_in_admin=0, related_name=None, 
    780         filter_interface=None, limit_choices_to=None, raw_id_admin=False, symmetrical=True): 
     752        filter_interface=None, limit_choices_to=None, symmetrical=True): 
    781753        self.to = to 
    782754        self.num_in_admin = num_in_admin 
     
    787759        self.limit_choices_to = limit_choices_to 
    788760        self.edit_inline = False 
    789         self.raw_id_admin = raw_id_admin 
    790761        self.symmetrical = symmetrical 
    791762        self.multiple = True 
    792  
    793         assert not (self.raw_id_admin and self.filter_interface), "ManyToManyRels may not use both raw_id_admin and filter_interface" 
  • django/branches/newforms-admin/django/db/models/manipulators.py

    r4265 r4430  
    117117            if self.follow.get(f.name, None): 
    118118                if not f.rel.edit_inline: 
    119                     if f.rel.raw_id_admin: 
    120                         new_vals = new_data.get(f.name, ()) 
    121                     else: 
    122                         new_vals = new_data.getlist(f.name) 
     119                    new_vals = new_data.getlist(f.name) 
    123120                    # First, clear the existing values. 
    124121                    rel_manager = getattr(new_object, f.name) 
     
    217214                            if child_follow.get(f.name, None) and not f.rel.edit_inline: 
    218215                                new_value = rel_new_data[f.attname] 
    219                                 if f.rel.raw_id_admin: 
    220                                     new_value = new_value[0] 
    221216                                setattr(new_rel_obj, f.name, f.rel.to.objects.filter(pk__in=new_value)) 
    222217                                if self.change: