В программе всегда используйте параметризированный запрос. Это избегает Атак с использованием кода на SQL, а также любых других символов, которые являются особенными для синтаксического анализатора SQL.
Не уверен, что этот вид обезьяньего исправления - хорошая идея, но вставка этого в один из моих admin.py
у меня работает:
from django.contrib.admin.actions import delete_selected
delete_selected.short_description = u'How\'s this for a name?'
Это изменится подробное имя для всех ваших административных сайтов. Если вы хотите изменить его только для администратора одной конкретной модели, я думаю, вам нужно написать настраиваемое действие администратора .
Протестировано с Django версии 1.1:
>>> import django
>>> django.VERSION
(1, 1, 0, 'beta', 1)
Вы можете отключить отображение действия с помощью этого кода.
from django.contrib import admin
admin.site.disable_action('delete_selected')
При желании вы можете восстановить его на отдельных моделях следующим образом:
class FooAdmin(admin.ModelAdmin):
actions = ['my_action', 'my_other_action', admin.actions.delete_selected]
Чтобы заменить delete_selected, я делаю следующее:
Скопируйте функцию delete_selected
из contrib / admin / actions.py
в ваш admin.py
и переименуйте его. Также скопируйте шаблон contrib / admin / templates / delete_selected_confirmation.html
в свой каталог шаблонов и переименуйте его. Мой выглядит так:
def reservation_bulk_delete(modeladmin, request, queryset):
"""
Default action which deletes the selected objects.
This action first displays a confirmation page whichs shows all the
deleteable objects, or, if the user has no permission one of the related
childs (foreignkeys), a "permission denied" message.
Next, it delets all selected objects and redirects back to the change list.
"""
opts = modeladmin.model._meta
app_label = opts.app_label
# Check that the user has delete permission for the actual model
if not modeladmin.has_delete_permission(request):
raise PermissionDenied
# Populate deletable_objects, a data structure of all related objects that
# will also be deleted.
# deletable_objects must be a list if we want to use '|unordered_list' in the template
deletable_objects = []
perms_needed = set()
i = 0
for obj in queryset:
deletable_objects.append([mark_safe(u'%s: <a href="%s/">%s</a>' % (escape(force_unicode(capfirst(opts.verbose_name))), obj.pk, escape(obj))), []])
get_deleted_objects(deletable_objects[i], perms_needed, request.user, obj, opts, 1, modeladmin.admin_site, levels_to_root=2)
i=i+1
# The user has already confirmed the deletion.
# Do the deletion and return a None to display the change list view again.
if request.POST.get('post'):
if perms_needed:
raise PermissionDenied
n = queryset.count()
if n:
for obj in queryset:
obj_display = force_unicode(obj)
obj.delete()
modeladmin.log_deletion(request, obj, obj_display)
#queryset.delete()
modeladmin.message_user(request, _("Successfully deleted %(count)d %(items)s.") % {
"count": n, "items": model_ngettext(modeladmin.opts, n)
})
# Return None to display the change list page again.
return None
context = {
"title": _("Are you sure?"),
"object_name": force_unicode(opts.verbose_name),
"deletable_objects": deletable_objects,
'queryset': queryset,
"perms_lacking": perms_needed,
"opts": opts,
"root_path": modeladmin.admin_site.root_path,
"app_label": app_label,
'action_checkbox_name': helpers.ACTION_CHECKBOX_NAME,
}
# Display the confirmation page
return render_to_response(modeladmin.delete_confirmation_template or [
"admin/%s/%s/reservation_bulk_delete_confirmation.html" % (app_label, opts.object_name.lower()),
"admin/%s/reservation_bulk_delete_confirmation.html" % app_label,
"admin/reservation_bulk_delete_confirmation.html"
], context, context_instance=template.RequestContext(request))
Как видите, я закомментировал
queryset.delete()
и предпочитаю использовать:
obj.delete()
Это еще не оптимально - вы должны применить что-то ко всему набору запросов для повышения производительности.
В admin.py я отключаю действие по умолчанию delete_selected для всего сайта администратора:
admin.site.disable_action('delete_selected')
Вместо этого я использую свою собственную функцию там, где это необходимо:
class ReservationAdmin(admin.ModelAdmin):
actions = [reservation_bulk_delete, ]
В моей модели я определяю функцию delete ()
:
class Reservation(models.Model):
def delete(self):
self.status_server = RESERVATION_STATUS_DELETED
self.save()