هدف از ایجاد List Action در ادمین جنگو انجام عملیات روی آبجکت های یک مدل به صورت انبوه است. تمامی مدل ها در محیط ادمین جنگو با یک Action پیشفرض “حذف <نام مدل> انتخاب شده” همراه هستند. در این آموزش من شما را در مراحل ساخت List Action راهنمایی می کنم.
هر Action در لیست آبجکت ها یک تابع معمولی پایتون است که 3 پارامتر را به عنوان ورودی دریافت می کند:
این تابع های Action در داخل فایل admin.py اپ جنگو ما قرار میگیرند ولی اگر واقعا در حال زیاد شدن بودند، میتوانید اونها را خارج از admin.py هم تعریف کنید.
در ادامه نمونه کد پایه یک تابع Action را مشاهده می کنید:
def my_admin_action(modeladmin, request, queryset): # do something with the queryset my_admin_action.short_description = 'My admin action'
به عنوان یک نمونه ساده این مدل را در نظر بگیرید:
models.py
from django.db import models class Book(models.Model): HARDCOVER = 1 PAPERBACK = 2 EBOOK = 3 BOOK_TYPES = ( (HARDCOVER, 'Hardcover'), (PAPERBACK, 'Paperback'), (EBOOK, 'E-book'), ) title = models.CharField(max_length=50) publication_date = models.DateField(null=True) author = models.CharField(max_length=30, blank=True) price = models.DecimalField(max_digits=5, decimal_places=2) pages = models.IntegerField(blank=True, null=True) book_type = models.PositiveSmallIntegerField(choices=BOOK_TYPES) class Meta: verbose_name = 'book' verbose_name_plural = 'books'
admin.py
from django.contrib import admin from .models import Book class BookAdmin(admin.ModelAdmin): list_display = ['title', 'publication_date', 'author', 'price', 'book_type'] admin.site.register(Book, BookAdmin)
حالا می خواهیم یک List Action بسازیم تا 10 درصد تخفیف روی کتاب های انتخاب شده اعمال کند. این کار به همین سادگی خواهد بود:
admin.py
import decimal from django.contrib import admin from .models import Book def apply_discount(modeladmin, request, queryset): for book in queryset: book.price = book.price * decimal.Decimal('0.9') book.save() apply_discount.short_description = 'Apply 10%% discount' class BookAdmin(admin.ModelAdmin): list_display = ['title', 'publication_date', 'author', 'price', 'book_type'] actions = [apply_discount, ] # <-- Add the list action function here admin.site.register(Book, BookAdmin)
فراموش نکنید که نام تابعی را که ساختید، در لیست actions اضافه کنید. نتیجه چنین چیزی خواهد بود:
نکته: شما می توانید تابع apply_discount را با استفاده از اصطلاح ()F در جنگو بهینه تر کنید:
from django.db.models import F def apply_discount(modeladmin, request, queryset): queryset.update(price=F('price') * decimal.Decimal('0.9'))
همچنین شما می توانید از List Action استفاده کنید تا به شما یک HttpResponse برگشت دهد. یک نمونه ساده خروجی به CSV:
import decimal, csv from django.contrib import admin from django.http import HttpResponse from django.db.models import F from .models import Book def apply_discount(modeladmin, request, queryset): queryset.update(price=F('price') * decimal.Decimal('0.9')) apply_discount.short_description = 'Apply 10%% discount' def export_books(modeladmin, request, queryset): response = HttpResponse(content_type='text/csv') response['Content-Disposition'] = 'attachment; filename="books.csv"' writer = csv.writer(response) writer.writerow(['Title', 'Publication Date', 'Author', 'Price', 'Pages', 'Book Type']) books = queryset.values_list('title', 'publication_date', 'author', 'price', 'pages', 'book_type') for book in books: writer.writerow(book) return response export_books.short_description = 'Export to csv' class BookAdmin(admin.ModelAdmin): list_display = ['title', 'publication_date', 'author', 'price', 'book_type'] actions = [apply_discount, export_books, ] admin.site.register(Book, BookAdmin)
یک روش جایگزین برای انجام این کار، ایجاد تابع List Action به عنوان یک متد از کلاس ادمین است:
class BookAdmin(admin.ModelAdmin): list_display = ['title', 'publication_date', 'author', 'price', 'book_type'] actions = ['apply_discount', export_books] def apply_discount(self, request, queryset): queryset.update(price=F('price') * decimal.Decimal('0.9')) apply_discount.short_description = 'Apply 10%% discount'
نام متدی را که ساختید، در قالب یک رشته به لیست actions ارسال کنید و اولین آرگومان (کلمه کلیدی modeladmin) را به self تغییر نام دهید.