Django

Code

Show
Ignore:
Timestamp:
08/05/08 12:15:33 (4 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7981-8001,8003-8011,8013-8033,8035-8036,8038-8039,8041-8063,8065-8076,8078-8139,8141-8154,8156-8214 via svnmerge from trunk.

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • django/branches/gis

    • Property svnmerge-integrated changed from /django/trunk:1-7978 to /django/trunk:1-8214
  • django/branches/gis/django/contrib/admin/__init__.py

    r7979 r8215  
    99    may want. 
    1010    """ 
     11    import imp 
    1112    from django.conf import settings 
    1213    for app in settings.INSTALLED_APPS: 
    1314        try: 
    14             __import__("%s.admin" % app
     15            imp.find_module("admin", __import__(app, {}, {}, [app.split(".")[-1]]).__path__
    1516        except ImportError: 
    16             pass 
     17            # there is no app admin.py, skip it 
     18            continue 
     19        __import__("%s.admin" % app) 
  • django/branches/gis/django/contrib/admin/media/css/rtl.css

    r3415 r8215  
    4545.selector { float: right;} 
    4646.selector .selector-filter { text-align: right;} 
     47 
     48/* x unsorted */ 
     49.inline-related h2 { text-align:right } 
  • django/branches/gis/django/contrib/admin/options.py

    r7979 r8215  
    1 from django import oldforms, template 
    2 from django import forms 
     1from django import forms, template 
    32from django.forms.formsets import all_valid 
    43from django.forms.models import modelform_factory, inlineformset_factory 
     
    1615from django.utils.translation import ugettext as _ 
    1716from django.utils.encoding import force_unicode 
    18 import sets 
     17try: 
     18    set 
     19except NameError: 
     20    from sets import Set as set     # Python 2.3 fallback 
    1921 
    2022HORIZONTAL, VERTICAL = 1, 2 
     
    9193 
    9294    def errors(self): 
    93         return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields])
     95        return mark_safe(u'\n'.join([self.form[f].errors.as_ul() for f in self.fields]).strip('\n')
    9496 
    9597class AdminField(object): 
     
    131133        If kwargs are given, they're passed to the form Field's constructor. 
    132134        """ 
     135 
     136        # If the field specifies choices, we don't need to look for special 
     137        # admin widgets - we just need to use a select widget of some kind. 
     138        if db_field.choices: 
     139            if db_field.name in self.radio_fields: 
     140                # If the field is named as a radio_field, use a RadioSelect 
     141                kwargs['widget'] = widgets.AdminRadioSelect( 
     142                    choices=db_field.get_choices(include_blank=db_field.blank, 
     143                        blank_choice=[('', _('None'))]), 
     144                    attrs={ 
     145                        'class': get_ul_class(self.radio_fields[db_field.name]), 
     146                    } 
     147                ) 
     148            else: 
     149                # Otherwise, use the default select widget. 
     150                return db_field.formfield(**kwargs) 
     151 
    133152        # For DateTimeFields, use a special field and widget. 
    134153        if isinstance(db_field, models.DateTimeField): 
     
    163182            else: 
    164183                if isinstance(db_field, models.ManyToManyField): 
    165                     if db_field.name in self.raw_id_fields: 
     184                    # If it uses an intermediary model, don't show field in admin. 
     185                    if db_field.rel.through is not None: 
     186                        return None 
     187                    elif db_field.name in self.raw_id_fields: 
    166188                        kwargs['widget'] = widgets.ManyToManyRawIdWidget(db_field.rel) 
    167189                        kwargs['help_text'] = '' 
    168                     elif db_field.name in (self.filter_vertical + self.filter_horizontal): 
     190                    elif db_field.name in (list(self.filter_vertical) + list(self.filter_horizontal)): 
    169191                        kwargs['widget'] = widgets.FilteredSelectMultiple(db_field.verbose_name, (db_field.name in self.filter_vertical)) 
    170192            # Wrap the widget's render() method with a method that adds 
     
    175197                formfield.widget = widgets.RelatedFieldWidgetWrapper(formfield.widget, db_field.rel, self.admin_site) 
    176198            return formfield 
    177          
    178         if db_field.choices and db_field.name in self.radio_fields: 
    179             kwargs['widget'] = widgets.AdminRadioSelect( 
    180                 choices=db_field.get_choices(include_blank=db_field.blank, 
    181                     blank_choice=[('', _('None'))]), 
    182                 attrs={ 
    183                     'class': get_ul_class(self.radio_fields[db_field.name]), 
    184                 } 
    185             ) 
    186199 
    187200        # For any other type of field, just call its formfield() method. 
     
    211224    ordering = None 
    212225    inlines = [] 
    213      
     226 
    214227    # Custom templates (designed to be over-ridden in subclasses) 
    215228    change_form_template = None 
     
    262275        if self.filter_vertical or self.filter_horizontal: 
    263276            js.extend(['js/SelectBox.js' , 'js/SelectFilter2.js']) 
    264          
     277 
    265278        return forms.Media(js=['%s%s' % (settings.ADMIN_MEDIA_PREFIX, url) for url in js]) 
    266279    media = property(_media) 
     
    346359        pk_value = new_object._get_pk_val() 
    347360        LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(self.model).id, pk_value, force_unicode(new_object), ADDITION) 
    348         msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': opts.verbose_name, 'obj': new_object} 
     361        msg = _('The %(name)s "%(obj)s" was added successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': new_object} 
    349362        # Here, we distinguish between different save types by checking for 
    350363        # the presence of keys in request.POST. 
     
    360373                (escape(pk_value), escape(new_object))) 
    361374        elif request.POST.has_key("_addanother"): 
    362             request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) 
     375            request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name))) 
    363376            return HttpResponseRedirect(request.path) 
    364377        else: 
     
    379392 
    380393        `form` is a bound Form instance that's verified to be valid. 
    381          
     394 
    382395        `formsets` is a sequence of InlineFormSet instances that are verified to be valid. 
    383396        """ 
     
    395408        if form.changed_data: 
    396409            change_message.append(_('Changed %s.') % get_text_list(form.changed_data, _('and'))) 
    397              
     410 
    398411        if formsets: 
    399412            for formset in formsets: 
    400413                for added_object in formset.new_objects: 
    401                     change_message.append(_('Added %(name)s "%(object)s".')  
     414                    change_message.append(_('Added %(name)s "%(object)s".') 
    402415                                          % {'name': added_object._meta.verbose_name, 
    403416                                             'object': added_object}) 
    404417                for changed_object, changed_fields in formset.changed_objects: 
    405                     change_message.append(_('Changed %(list)s for %(name)s "%(object)s".')  
    406                                           % {'list': get_text_list(changed_fields, _('and')),  
    407                                              'name': changed_object._meta.verbose_name,  
     418                    change_message.append(_('Changed %(list)s for %(name)s "%(object)s".') 
     419                                          % {'list': get_text_list(changed_fields, _('and')), 
     420                                             'name': changed_object._meta.verbose_name, 
    408421                                             'object': changed_object}) 
    409422                for deleted_object in formset.deleted_objects: 
    410                     change_message.append(_('Deleted %(name)s "%(object)s".')  
     423                    change_message.append(_('Deleted %(name)s "%(object)s".') 
    411424                                          % {'name': deleted_object._meta.verbose_name, 
    412425                                             'object': deleted_object}) 
     
    416429        LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(self.model).id, pk_value, force_unicode(new_object), CHANGE, change_message) 
    417430 
    418         msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': opts.verbose_name, 'obj': new_object} 
     431        msg = _('The %(name)s "%(obj)s" was changed successfully.') % {'name': force_unicode(opts.verbose_name), 'obj': new_object} 
    419432        if request.POST.has_key("_continue"): 
    420433            request.user.message_set.create(message=msg + ' ' + _("You may edit it again below.")) 
     
    424437                return HttpResponseRedirect(request.path) 
    425438        elif request.POST.has_key("_saveasnew"): 
    426             request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': opts.verbose_name, 'obj': new_object}) 
     439            request.user.message_set.create(message=_('The %(name)s "%(obj)s" was added successfully. You may edit it again below.') % {'name': force_unicode(opts.verbose_name), 'obj': new_object}) 
    427440            return HttpResponseRedirect("../%s/" % pk_value) 
    428441        elif request.POST.has_key("_addanother"): 
    429             request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % opts.verbose_name)) 
     442            request.user.message_set.create(message=msg + ' ' + (_("You may add another %s below.") % force_unicode(opts.verbose_name))) 
    430443            return HttpResponseRedirect("../add/") 
    431444        else: 
     
    505518 
    506519        context = { 
    507             'title': _('Add %s') % opts.verbose_name
     520            'title': _('Add %s') % force_unicode(opts.verbose_name)
    508521            'adminform': adminForm, 
    509522            'is_popup': request.REQUEST.has_key('_popup'), 
     
    535548 
    536549        if obj is None: 
    537             raise Http404('%s object with primary key %r does not exist.' % (opts.verbose_name, escape(object_id))) 
     550            raise Http404('%s object with primary key %r does not exist.' % (force_unicode(opts.verbose_name), escape(object_id))) 
    538551 
    539552        if request.POST and request.POST.has_key("_saveasnew"): 
     
    558571        adminForm = AdminForm(form, self.get_fieldsets(request, obj), self.prepopulated_fields) 
    559572        media = self.media + adminForm.media 
    560         for fs in inline_formsets: 
    561             media = media + fs.media 
    562573 
    563574        inline_admin_formsets = [] 
     
    566577            inline_admin_formset = InlineAdminFormSet(inline, formset, fieldsets) 
    567578            inline_admin_formsets.append(inline_admin_formset) 
     579            media = media + inline_admin_formset.media 
    568580 
    569581        context = { 
    570             'title': _('Change %s') % opts.verbose_name
     582            'title': _('Change %s') % force_unicode(opts.verbose_name)
    571583            'adminform': adminForm, 
    572584            'object_id': object_id, 
     
    600612                return render_to_response('admin/invalid_setup.html', {'title': _('Database error')}) 
    601613            return HttpResponseRedirect(request.path + '?' + ERROR_FLAG + '=1') 
    602          
     614 
    603615        context = { 
    604616            'title': cl.title, 
     
    633645 
    634646        if obj is None: 
    635             raise Http404('%s object with primary key %r does not exist.' % (opts.verbose_name, escape(object_id))) 
     647            raise Http404('%s object with primary key %r does not exist.' % (force_unicode(opts.verbose_name), escape(object_id))) 
    636648 
    637649        # Populate deleted_objects, a data structure of all related objects that 
    638650        # will also be deleted. 
    639651        deleted_objects = [mark_safe(u'%s: <a href="../../%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), quote(object_id), escape(obj))), []] 
    640         perms_needed = sets.Set() 
     652        perms_needed = set() 
    641653        get_deleted_objects(deleted_objects, perms_needed, request.user, obj, opts, 1, self.admin_site) 
    642654 
     
    651663                return HttpResponseRedirect("../../../../") 
    652664            return HttpResponseRedirect("../../") 
    653          
     665 
    654666        context = { 
    655667            "title": _("Are you sure?"), 
    656             "object_name": opts.verbose_name
     668            "object_name": force_unicode(opts.verbose_name)
    657669            "object": obj, 
    658670            "deleted_objects": deleted_objects, 
     
    682694            'title': _('Change history: %s') % force_unicode(obj), 
    683695            'action_list': action_list, 
    684             'module_name': capfirst(opts.verbose_name_plural), 
     696            'module_name': capfirst(force_unicode(opts.verbose_name_plural)), 
    685697            'object': obj, 
    686698            'root_path': self.admin_site.root_path, 
     
    762774            yield self.formset.form.base_fields[field_name] 
    763775 
     776    def _media(self): 
     777        media = self.formset.media 
     778        for fs in self: 
     779            media = media + fs.media 
     780        return media 
     781    media = property(_media) 
     782 
    764783class InlineAdminForm(AdminForm): 
    765784    """ 
  • django/branches/gis/django/contrib/admin/sites.py

    r7979 r8215  
     1import base64 
     2import cPickle as pickle 
     3import re 
     4 
    15from django import http, template 
    26from django.contrib.admin import ModelAdmin 
     
    913from django.views.decorators.cache import never_cache 
    1014from django.conf import settings 
    11 import base64 
    12 import cPickle as pickle 
    13 import datetime 
    14 import md5 
    15 import re 
     15from django.utils.hashcompat import md5_constructor 
    1616 
    1717ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") 
     
    2727 
    2828def _encode_post_data(post_data): 
    29     from django.conf import settings 
    3029    pickled = pickle.dumps(post_data) 
    31     pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() 
     30    pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() 
    3231    return base64.encodestring(pickled + pickled_md5) 
    3332 
    3433def _decode_post_data(encoded_data): 
    35     from django.conf import settings 
    3634    encoded_data = base64.decodestring(encoded_data) 
    3735    pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] 
    38     if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: 
     36    if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: 
    3937        from django.core.exceptions import SuspiciousOperation 
    4038        raise SuspiciousOperation, "User may have tampered with session cookie." 
     
    4846    that presents a full admin interface for the collection of registered models. 
    4947    """ 
    50      
     48 
    5149    index_template = None 
    5250    login_template = None 
    53      
     51 
    5452    def __init__(self): 
    5553        self._registry = {} # model_class class -> admin_class instance 
     
    6765        If a model is already registered, this will raise AlreadyRegistered. 
    6866        """ 
    69         do_validate = admin_class and settings.DEBUG 
    70         if do_validate: 
    71             # don't import the humongous validation code unless required 
     67        # Don't import the humongous validation code unless required 
     68        if admin_class and settings.DEBUG: 
    7269            from django.contrib.admin.validation import validate 
    73         admin_class = admin_class or ModelAdmin 
    74         # TODO: Handle options 
     70        else: 
     71            validate = lambda model, adminclass: None 
     72 
     73        if not admin_class: 
     74            admin_class = ModelAdmin 
    7575        if isinstance(model_or_iterable, ModelBase): 
    7676            model_or_iterable = [model_or_iterable] 
     
    7878            if model in self._registry: 
    7979                raise AlreadyRegistered('The model %s is already registered' % model.__name__) 
    80             if do_validate: 
    81                 validate(admin_class, model) 
     80 
     81            # If we got **options then dynamically construct a subclass of 
     82            # admin_class with those **options. 
     83            if options: 
     84                # For reasons I don't quite understand, without a __module__ 
     85                # the created class appears to "live" in the wrong place, 
     86                # which causes issues later on. 
     87                options['__module__'] = __name__ 
     88                admin_class = type("%sAdmin" % model.__name__, (admin_class,), options) 
     89 
     90            # Validate (which might be a no-op) 
     91            validate(admin_class, model) 
     92 
     93            # Instantiate the admin class to save in the registry 
    8294            self._registry[model] = admin_class(model, self) 
    8395 
     
    103115 
    104116    def root(self, request, url): 
    105         """  
     117        """ 
    106118        Handles main URL routing for the admin app. 
    107119 
     
    110122        if request.method == 'GET' and not request.path.endswith('/'): 
    111123            return http.HttpResponseRedirect(request.path + '/') 
    112          
     124 
    113125        # Figure out the admin base URL path and stash it for later use 
    114126        self.root_path = re.sub(re.escape(url) + '$', '', request.path) 
    115          
     127 
    116128        url = url.rstrip('/') # Trim trailing slash, if it exists. 
    117129 
     
    119131        if url == 'logout': 
    120132            return self.logout(request) 
    121          
     133 
    122134        # Check permission to continue or display login form. 
    123135        if not self.has_permission(request): 
     
    140152            if match: 
    141153                return self.user_change_password(request, match.group(1)) 
    142                  
     154 
    143155            if '/' in url: 
    144156                return self.model_page(request, *url.split('/', 2)) 
     
    190202        generated JavaScript will be leaner and faster. 
    191203        """ 
    192         from django.conf import settings 
    193204        if settings.USE_I18N: 
    194205            from django.views.i18n import javascript_catalog 
     
    250261            if user.is_active and user.is_staff: 
    251262                login(request, user) 
    252                 # TODO: set last_login with an event. 
    253                 user.last_login = datetime.datetime.now() 
    254                 user.save() 
    255263                if request.POST.has_key('post_data'): 
    256264                    post_data = _decode_post_data(request.POST['post_data']) 
     
    309317        for app in app_list: 
    310318            app['models'].sort(lambda x, y: cmp(x['name'], y['name'])) 
    311          
     319 
    312320        context = { 
    313321            'title': _('Site administration'), 
     
    316324        } 
    317325        context.update(extra_context or {}) 
    318         return render_to_response(self.index_template or 'admin/index.html', context,  
     326        return render_to_response(self.index_template or 'admin/index.html', context, 
    319327            context_instance=template.RequestContext(request) 
    320328        ) 
     
    331339        else: 
    332340            post_data = _encode_post_data({}) 
    333          
     341 
    334342        context = { 
    335343            'title': _('Log in'), 
  • django/branches/gis/django/contrib/admin/templates/admin_doc/model_detail.html

    r7354 r8215  
    3535    <td>{{ field.name }}</td> 
    3636    <td>{{ field.data_type }}</td> 
    37     <td>{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text }}{% endif %}</td> 
     37    <td>{% if field.verbose %}{{ field.verbose }}{% endif %}{% if field.help_text %} - {{ field.help_text|safe }}{% endif %}</td> 
    3838</tr> 
    3939{% endfor %} 
  • django/branches/gis/django/contrib/admin/templates/admin/includes/fieldset.html

    r7979 r8215  
    11<fieldset class="module aligned {{ fieldset.classes }}"> 
    22  {% if fieldset.name %}<h2>{{ fieldset.name }}</h2>{% endif %} 
    3   {% if fieldset.description %}<div class="description">{{ fieldset.description }}</div>{% endif %} 
     3  {% if fieldset.description %}<div class="description">{{ fieldset.description|safe }}</div>{% endif %} 
    44  {% for line in fieldset %} 
    55      <div class="form-row{% if line.errors %} errors{% endif %} {% for field in line %}{{ field.field.name }} {% endfor %} "> 
  • django/branches/gis/django/contrib/admin/templates/registration/password_reset_done.html

    r7354 r8215  
    1010<h1>{% trans 'Password reset successful' %}</h1> 
    1111 
    12 <p>{% trans "We've e-mailed a new password to the e-mail address you submitted. You should be receiving it shortly." %}</p> 
     12<p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p> 
    1313 
    1414{% endblock %} 
  • django/branches/gis/django/contrib/admin/templates/registration/password_reset_email.html

    r7354 r8215  
    1 {% load i18n %} 
     1{% load i18n %}{% autoescape off %} 
    22{% trans "You're receiving this e-mail because you requested a password reset" %} 
    33{% blocktrans %}for your user account at {{ site_name }}{% endblocktrans %}. 
    44 
    5 {% blocktrans %}Your new password is: {{ new_password }}{% endblocktrans %} 
    6  
    7 {% trans "Feel free to change this password by going to this page:" %} 
    8  
    9 http://{{ domain }}/password_change/ 
    10  
     5{% trans "Please go to the following page and choose a new password:" %} 
     6{% block reset_link %} 
     7{{ protocol }}://{{ domain }}/reset/{{ uid }}-{{ token }}/ 
     8{% endblock %} 
    119{% trans "Your username, in case you've forgotten:" %} {{ user.username }} 
    1210 
     
    1412 
    1513{% blocktrans %}The {{ site_name }} team{% endblocktrans %} 
     14 
     15{% endautoescape %} 
  • django/branches/gis/django/contrib/admin/templates/registration/password_reset_form.html

    r7979 r8215  
    1010<h1>{% trans "Password reset" %}</h1> 
    1111 
    12 <p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll reset your password and e-mail the new one to you." %}</p> 
     12<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p> 
    1313 
    1414<form action="" method="post"> 
  • django/branches/gis/django/contrib/admin/validation.py

    r7979 r8215  
     1try: 
     2    set 
     3except NameError: 
     4    from sets import Set as set   # Python 2.3 fallback 
    15 
    26from django.core.exceptions import ImproperlyConfigured 
     
    166170        if cls.fieldsets: 
    167171            raise ImproperlyConfigured('Both fieldsets and fields are specified in %s.' % cls.__name__) 
     172        if len(cls.fields) > len(set(cls.fields)): 
     173            raise ImproperlyConfigured('There are duplicate field(s) in %s.fields' % cls.__name__) 
    168174 
    169175    # fieldsets 
     
    180186                        "%s.fieldsets[%d][1] field options dict." 
    181187                        % (cls.__name__, idx)) 
    182         for field in flatten_fieldsets(cls.fieldsets): 
     188        flattened_fieldsets = flatten_fieldsets(cls.fieldsets) 
     189        if len(flattened_fieldsets) > len(set(flattened_fieldsets)): 
     190            raise ImproperlyConfigured('There are duplicate field(s) in %s.fieldsets' % cls.__name__) 
     191        for field in flattened_fieldsets: 
    183192            _check_form_field_existsw("fieldsets[%d][1]['fields']" % idx, field) 
    184193 
  • django/branches/gis/django/contrib/admin/views/decorators.py

    r7979 r8215  
    11import base64 
    2 import md5 
    32import cPickle as pickle 
    43try: 
     
    1312from django.shortcuts import render_to_response 
    1413from django.utils.translation import ugettext_lazy, ugettext as _ 
     14from django.utils.hashcompat import md5_constructor 
    1515 
    1616ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") 
     
    3636def _encode_post_data(post_data): 
    3737    pickled = pickle.dumps(post_data) 
    38     pickled_md5 = md5.new(pickled + settings.SECRET_KEY).hexdigest() 
     38    pickled_md5 = md5_constructor(pickled + settings.SECRET_KEY).hexdigest() 
    3939    return base64.encodestring(pickled + pickled_md5) 
    4040 
     
    4242    encoded_data = base64.decodestring(encoded_data) 
    4343    pickled, tamper_check = encoded_data[:-32], encoded_data[-32:] 
    44     if md5.new(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: 
     44    if md5_constructor(pickled + settings.SECRET_KEY).hexdigest() != tamper_check: 
    4545        from django.core.exceptions import SuspiciousOperation 
    4646        raise SuspiciousOperation, "User may have tampered with session cookie." 
     
    8888                    message = _("Your e-mail address is not your username. Try '%s' instead.") % users[0].username 
    8989                else: 
    90                     # Either we cannot find the user, or if more than 1  
     90                    # Either we cannot find the user, or if more than 1 
    9191                    # we cannot guess which user is the correct one. 
    9292                    message = _("Usernames cannot contain the '@' character.") 
  • django/branches/gis/django/contrib/admin/views/main.py

    r7979 r8215  
    77from django.utils.encoding import force_unicode, smart_str 
    88from django.utils.translation import ugettext 
    9 from django.utils.safestring import mark_safe 
    109from django.utils.http import urlencode 
    1110import operator 
  • django/branches/gis/django/contrib/admin/widgets.py

    r7979 r8215  
    88from django.forms.widgets import RadioFieldRenderer 
    99from django.forms.util import flatatt 
    10 from django.utils.datastructures import MultiValueDict 
    11 from django.utils.text import capfirst, truncate_words 
     10from django.utils.text import truncate_words 
    1211from django.utils.translation import ugettext as _ 
    1312from django.utils.safestring import mark_safe