2013-12-14 3 views
1

Предположим, у меня есть модель, как это:Настройка Джанго администратора сайта - в кнопках строк

class Foo(models.Model): 
    name = models.CharField(max_length=50) 
    year = models.IntegerField(max_length=4) 
    some_value = models.IntegerField(default=0) 

и

class Bar(models.Model) 
    name = models.CharField(max_length=50) 
    foo = models.ForeignKey(Foo) 

Тогда я зарегистрировать свои модели в Django AdminSite с помощью FooAdmin класса:

class FooAdmin(admin.ModelAdmin): 
    list_display = ['name', 'year', 'some_value'] 

Он отлично работает, но по какой-то причине мне нужно добавить две кнопки для каждой строки Foo на моем сайте администратора. Скажем, я бы назвал их «Related_button» и «Action_button»

Мне нужны эти кнопки, чтобы быть в каждой строке и вести себя следующим образом:
-Когда пользователь нажимает на «Related_button», он перенаправляется на Джанго администратора где все бары, связанные с объектом Foo объекта, перечислены
- Когда пользователь нажимает на «Action_button», поле some_value в объекте класса Foo устанавливается на пользовательское значение, скажем 15. Но до этого подтвердите всплывающее окно (вы обязательно? y/n).

Как это сделать? Я понял, что я мог бы сделать что-то вроде:

def button(self, obj): 
    return '''<input type="button" value="button" />''' 
button.short_description = 'Action' 
button.allow_tags = True 
list_display = ['name', 'year', 'some_value', 'action'] 

в моей FooAdmin, который вызывает кнопку, чтобы появиться в каждой строке. Но как я могу настроить действие для этой кнопки?

ответ

5

страница Список форма.

<form id="changelist-form" action="" method="post"> 

Добавление пуговиц к нему подает форму. Чтобы что-то сделать с помощью formdata, вы должны создать пользовательскую форму. Он будет грязным, потому что он содержит все отображаемые строки, а не только одну строку. Я думаю, это можно сделать, но есть и другие способы:

В большинстве случаев Admin Actions будет делать все как надо. Действия администратора выглядеть следующим образом:

Admin actions

def rename_action(modeladmin, request, queryset): 
    queryset.update(name='Ni') 
make_published.short_description = "Rename selected objects to 'Ni'" 

class FooAdmin(admin.ModelAdmin): 
    actions = [rename_action, ...] 

Но если вы хотите больше гибкости, чем админ действия, не стесняйтесь писать пользовательские представления для администратора. Администратор работает от самого Django, и вы можете писать пользовательские представления, которые подключаются к системе аутентификации, проверять разрешения и делать все, что им нужно. Это выглядит следующим образом:

class Foo(models.Model): 
    ... 

    def my_action_link(self, obj): 
     return '<a href="/admin/app/foo/my_custom_action/%d/" class="link">Action name</a>' %obj.id 
    my_action_link.short_description = 'My action' 
    my_action_link.allow_tags = True 

Теперь мое действие ссылку, которая указывает на какой-то custom url and custom admin view. Создать пользовательский вид администратора:

class FooAdmin(admin.ModelAdmin): 
    ... 

    list_display = ['name', 'my_action_link', ...] 

    def get_urls(self): 
     urls = super(FooAdmin, self).get_urls() 
     my_urls = patterns('', 
      (r'^my_custom_action/(?P<pk>\d+)/$', self.my_view) 
     ) 
     return my_urls + urls 

    @permission_required('foo.can_change') 
    def my_view(self, request): 
     obj = get_object_or_404(Foo, pk=pk) 
     obj.do_something() 
     # Redirect back to the change list. Or something else? 
     # You could add some modelform to this view. :) 

Я не тестировал этот код. Но я надеюсь, что вы поняли эту идею. Счастливый взлом!

[EDITED]: Ссылка Ссылка URL-адреса Django 1.6 больше не работают. Добавлены URL-адреса Django 1.11

+0

Спасибо, что хорошо! Но я беспокоюсь об одном: я также изменил queryset mehtod в своем FooAdmin следующим образом: return Foo.objects.filter (created_by = request.user). Является ли my_view объектом Foo в моем фильтрованном наборе или он извлекает его непосредственно из базы данных? Я не хочу, чтобы мой пользователь видел то, что ему не позволили. – slnowak

+0

Я предполагаю, что ваш пользователь может возиться с URL-адресом. Но вы могли бы сделать: 'obj = get_object_or_404 (Foo, pk = pk, created_by = request.user)', если obj не создан этим пользователем, он поднимет значение 404. – allcaps

+0

Или, конечно, есть другие способы. Проверьте и верните полезное сообщение: 'if request.user! = Obj.created_by: return" Этот инцидент будет сообщен. "' – allcaps

0

Добавление пользовательских JS в класс администратора:

class FooAdmin(admin.ModelAdmin): 
    list_display = ['name', 'year', 'some_value'] 

    class Media: 
     js = ("/media/javascript/yourjs.js",) 
+0

Не могли бы вы написать что-нибудь еще? К сожалению, я не знаю java-скрипта. И какая из моих проблем должна решить? – slnowak

Смежные вопросы