Ticket #2383: deletelist_with_templates_updated.diff

File deletelist_with_templates_updated.diff, 10.9 KB (added by deryck <deryck@…>, 17 years ago)

New patch, fixing "has_delete_permissions" and doing a proper form POST submit (sans JavaScript)

  • django/contrib/admin/media/css/global.css

     
    135135.object-tools a.viewsitelink:hover, .object-tools a.golink:hover { background:#5b80b2 url(../img/admin/tooltag-arrowright_over.gif) top right no-repeat; }
    136136.object-tools a.addlink { background:#999 url(../img/admin/tooltag-add.gif) top right no-repeat; padding-right:28px; }
    137137.object-tools a.addlink:hover { background:#5b80b2 url(../img/admin/tooltag-add_over.gif) top right no-repeat; }
     138#delete_checked_submit { background:#999 url(../img/admin/tool-left.gif) top left no-repeat; float:right; }
     139#delete_checked_submit:hover { background:#5b80b2 url(../img/admin/tool-left_over.gif) top left no-repeat; }
     140#delete_checked_submit input { background:#999 url(../img/admin/tooltag-delete.gif) top right no-repeat; border:0; padding:1px 28px 0 0; font-size:11px; font-weight:bold; font-family:Arial,Helvetica,sans-serif; color:#FFF; margin:0 0 0 10px; }
     141#delete_checked_submit input:hover { background:#5b80b2 url(../img/admin/tooltag-delete_over.gif) top right no-repeat; }
    138142
    139143/* OBJECT HISTORY */
    140144table#change-history { width:100%; }
  • django/contrib/admin/templatetags/admin_list.py

     
    6666    }
    6767pagination = register.inclusion_tag('admin/pagination.html')(pagination)
    6868
    69 def result_headers(cl):
     69def result_headers(cl, user):
    7070    lookup_opts = cl.lookup_opts
    7171
    7272    for i, field_name in enumerate(lookup_opts.admin.list_display):
     
    100100                       "sortable": True,
    101101                       "url": cl.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
    102102                       "class_attrib": (th_classes and ' class="%s"' % ' '.join(th_classes) or '')}
     103    if user.has_perm(lookup_opts.app_label + '.' + lookup_opts.get_delete_permission()):
     104        yield{"text":"Delete?"}
    103105
    104 def items_for_result(cl, result):
     106def items_for_result(cl, result, user):
    105107    first = True
    106108    pk = cl.lookup_opts.pk.attname
    107109    for field_name in cl.lookup_opts.admin.list_display:
     
    173175                (table_tag, row_class, url, (cl.is_popup and ' onclick="opener.dismissRelatedLookupPopup(window, %r); return false;"' % result_id or ''), result_repr, table_tag))
    174176        else:
    175177            yield ('<td%s>%s</td>' % (row_class, result_repr))
     178    if user.has_perm(cl.lookup_opts.app_label + '.' + cl.lookup_opts.get_delete_permission()):
     179        yield('<td><input type="checkbox" name="%s" /></td>' % result_id)
    176180
    177 def results(cl):
     181def results(cl, user):
    178182    for res in cl.result_list:
    179         yield list(items_for_result(cl,res))
     183        yield list(items_for_result(cl, res, user))
    180184
    181 def result_list(cl):
     185def result_list(cl, user):
     186    lookup_opts = cl.lookup_opts
    182187    return {'cl': cl,
    183             'result_headers': list(result_headers(cl)),
    184             'results': list(results(cl))}
     188            'has_delete_permission' : user.has_perm(lookup_opts.app_label + '.' + lookup_opts.get_delete_permission()),
     189            'result_headers': list(result_headers(cl, user)),
     190            'results': list(results(cl, user))}
    185191result_list = register.inclusion_tag("admin/change_list_results.html")(result_list)
    186192
    187193def date_hierarchy(cl):
  • django/contrib/admin/urls.py

     
    3333    # Add/change/delete/history
    3434    ('^([^/]+)/([^/]+)/$', 'django.contrib.admin.views.main.change_list'),
    3535    ('^([^/]+)/([^/]+)/add/$', 'django.contrib.admin.views.main.add_stage'),
     36    ('^([^/]+)/([^/]+)/delete/$', 'django.contrib.admin.views.main.delete_checked'),
    3637    ('^([^/]+)/([^/]+)/(.+)/history/$', 'django.contrib.admin.views.main.history'),
    3738    ('^([^/]+)/([^/]+)/(.+)/delete/$', 'django.contrib.admin.views.main.delete_stage'),
    3839    ('^([^/]+)/([^/]+)/(.+)/$', 'django.contrib.admin.views.main.change_stage'),
  • django/contrib/admin/views/main.py

     
    742742
    743743def change_list(request, app_label, model_name):
    744744    model = models.get_model(app_label, model_name)
     745    opts = model._meta
     746    auto_populated_fields = [f for f in opts.fields if f.prepopulate_from]
     747    field_sets = opts.admin.get_field_sets(opts)
    745748    if model is None:
    746749        raise Http404, "App %r, model %r, not found" % (app_label, model_name)
    747750    if not request.user.has_perm(app_label + '.' + model._meta.get_change_permission()):
     
    763766        'cl': cl,
    764767    })
    765768    c.update({'has_add_permission': c['perms'][app_label][cl.opts.get_add_permission()]}),
     769    c.update({'has_delete_permission': c['perms'][app_label][cl.opts.get_delete_permission()]}),
     770    c.update({'javascript_imports': get_javascript_imports(opts, auto_populated_fields, field_sets)}),
    766771    return render_to_response(['admin/%s/%s/change_list.html' % (app_label, cl.opts.object_name.lower()),
    767772                               'admin/%s/change_list.html' % app_label,
    768773                               'admin/change_list.html'], context_instance=c)
    769774change_list = staff_member_required(never_cache(change_list))
     775
     776def delete_checked (request,app_label, model_name):
     777    "Essentially the same as delete stage only for a list of objects in post parameters"
     778    import sets
     779    model = models.get_model(app_label, model_name)
     780    if model is None:
     781        raise Http404, "App %r, model %r, not found" % (app_label, model_name)
     782    opts = model._meta
     783    if not request.user.has_perm(app_label + '.' + opts.get_delete_permission()):
     784        raise PermissionDenied
     785    perms_needed = sets.Set()
     786    #Fetch all the objects
     787    objects = [get_object_or_404(model, pk = unquote(o)) for o in request.POST if o != "doit"]
     788
     789    perms_needed = sets.Set()
     790    for obj in objects:
     791        obj.deleted_objects = ['%s: <a href="../../%s/">%s</a>' % (capfirst(opts.verbose_name), getattr(obj,opts.pk.attname), escape(str(obj))), []]
     792        obj.deleteid = getattr(obj,opts.pk.attname)
     793        _get_deleted_objects(obj.deleted_objects, perms_needed, request.user, obj, opts, 1)
     794
     795    if request.POST.get('doit', 0): # The user has already confirmed the deletion.
     796        if perms_needed:
     797            raise PermissionDenied
     798        obj_display = []
     799        for obj in objects:
     800            obj_display.append(str(obj))
     801            obj.delete()
     802            LogEntry.objects.log_action(request.user.id, ContentType.objects.get_for_model(model).id, obj.deleteid, str(obj), DELETION)
     803        request.user.message_set.create(message=_('The %(name)s objects: "%(obj)s" were deleted successfully.') % {'name': opts.verbose_name, 'obj': ",".join(obj_display)})
     804        return HttpResponseRedirect("../")     
     805
     806    extra_context = {
     807        "title": _("Are you sure?"),
     808        "object_name": opts.verbose_name,
     809        "daobjects": objects,
     810        "perms_lacking": perms_needed,
     811        "opts": model._meta,
     812    }
     813    return render_to_response(["admin/%s/%s/deletelist_confirmation.html" % (app_label, opts.object_name.lower() ),
     814                               "admin/%s/deletelist_confirmation.html" % app_label ,
     815                               "admin/deletelist_confirmation.html"], extra_context, context_instance=template.RequestContext(request))
     816delete_checked = staff_member_required(delete_checked)
  • django/contrib/admin/templates/admin/change_list.html

     
    1414{% block search %}{% search_form cl %}{% endblock %}
    1515{% block date_hierarchy %}{% date_hierarchy cl %}{% endblock %}
    1616{% block filters %}{% filters cl %}{% endblock %}
    17 {% block result_list %}{% result_list cl %}{% endblock %}
     17{% block result_list %}{% result_list cl user %}{% endblock %}
    1818{% block pagination %}{% pagination cl %}{% endblock %}
    1919</div>
    2020</div>
     21{% if has_delete_permission %}
     22<div id="delete_checked_submit"><input type="submit" value="{% trans 'Delete checked' %}" /></div>
     23</form>
     24{% endif %}
    2125{% endblock %}
  • django/contrib/admin/templates/admin/change_list_results.html

     
    11{% if results %}
     2{% if has_delete_permission %}
     3<form name="delete_checked_form" id="delete_checked_form" method="post" action="delete/">
     4{% endif %}
    25<table cellspacing="0">
    36<thead>
    47<tr>
  • django/contrib/admin/templates/admin/deletelist_confirmation.html

     
     1{% extends "admin/base_site.html" %}
     2{% load i18n %}
     3{% block userlinks %}<a href="../../../../doc/">{% trans 'Documentation' %}</a> / <a href="../../../../password_change/">{% trans 'Change password' %}</a> / <a href="../../../../logout/">{% trans 'Log out' %}</a>{% endblock %}
     4{% block breadcrumbs %}
     5<div class="breadcrumbs">
     6     <a href="../../../">{% trans "Home" %}</a> &rsaquo;
     7     <a href="../">{{ opts.verbose_name_plural|capfirst|escape }}</a> &rsaquo;
     8     {% trans 'Delete' %}
     9</div>
     10{% endblock %}
     11{% block content %}
     12{% if perms_lacking %}
     13    <p>{% blocktrans with object|escape as escaped_object %}Deleting the {{ object_name }} '{{ escaped_object }}' would result in deleting related objects, but your account doesn't have permission to delete the following types of objects:{% endblocktrans %}</p>
     14    <ul>
     15    {% for obj in perms_lacking %}
     16        <li>{{ obj|escape }}</li>
     17    {% endfor %}
     18    </ul>
     19{% else %}
     20        <form action="" method="post">
     21    <p>{% blocktrans with object|escape as escaped_object %}Are you sure you want to delete the following {{ object_name }} objects? All of the following related items will be deleted:{% endblocktrans %}</p>
     22    {% for object in daobjects%}
     23    <ul>{{ object.deleted_objects|unordered_list }}</ul>
     24    <div>
     25        <input type="hidden" name="{{object.deleteid}}" value="on">
     26        {%endfor%}
     27    <input type="hidden" name="doit" value="yes" />
     28    <input type="submit" value="{% trans "Yes, I'm sure" %}" />
     29    </div>
     30    </form>
     31{% endif %}
     32{% endblock %}
Back to Top