از فهرست ساده تا ابزار کار روزانه
کارمند فروش باید اقلام سفارش را همانجا ببیند، ده سفارش را با یک کلیک «ارسالشده» کند و بین دو هزار طرح فرش با تایپ چند حرف انتخاب کند. سه ابزار اینها را ممکن میکنند: inline، action و autocomplete.
from django.contrib import admin, messages
from django.db import transaction
from apps.catalog.models import Carpet
from .models import Order, OrderItem
@admin.register(Carpet)
class CarpetAdmin(admin.ModelAdmin):
search_fields = ("code", "name") # برای autocomplete الزامی است
list_display = ("code", "name", "density", "price", "stock")
class OrderItemInline(admin.TabularInline):
model = OrderItem
extra = 0
autocomplete_fields = ("carpet",)
readonly_fields = ("unit_price",)
@admin.action(description="علامتگذاری بهعنوان ارسالشده", permissions=["change"])
def mark_shipped(modeladmin, request, queryset):
with transaction.atomic():
n = queryset.filter(status="paid").update(status="shipped")
skipped = queryset.count() - n
modeladmin.message_user(request, f"{n} سفارش ارسالشده شد.", messages.SUCCESS)
if skipped:
modeladmin.message_user(request, f"{skipped} سفارش پرداختنشده نادیده گرفته شد.", messages.WARNING)
@admin.register(Order)
class OrderAdmin(admin.ModelAdmin):
inlines = [OrderItemInline]
actions = [mark_shipped]
autocomplete_fields = ("customer",)
def get_readonly_fields(self, request, obj=None):
if obj and obj.status in ("shipped", "cancelled"):
return [f.name for f in self.model._meta.fields] # سفارش بسته قفل است
return ("tracking_code", "total")
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
def save_related(self, request, form, formsets, change):
super().save_related(request, form, formsets, change)
form.instance.recalculate_total() # بعد از ذخیرهی اقلام
ادمین فارسی و راستبهچپ
با LANGUAGE_CODE = "fa" ادمین خودکار راستبهچپ و فارسی میشود؛ جنگو ترجمهی فارسی رسمی دارد. دو چیز باقی میماند: فونت (با override کردن قالب admin/base_site.html و افزودن یک فایل CSS محلی با فونت Vazirmatn) و تاریخ شمسی (با ستونهای نمایشی مثل درس قبل یا بستههایی مثل django-jalali). اگر ظاهر مدرنتر میخواهید، تمهایی مثل django-unfold ادمین را بازطراحی میکنند و از RTL پشتیبانی دارند؛ همین سایت آموزشی هم با آن ساخته شده است.
{# templates/admin/base_site.html #}
{% extends "admin/base_site.html" %}
{% load static %}
{% block extrastyle %}{{ block.super }}
<link rel="stylesheet" href="{% static 'admin/fa.css' %}">
{% endblock %}
نکتههایی که کمتر کسی میداند
- autocomplete_fields فقط وقتی کار میکند که ModelAdmin مدل مقصد
search_fieldsداشته باشد؛ وگرنه درcheckخطای admin.E040 میگیرید. - action با
queryset.update()نهsave()مدل را صدا میزند نه سیگنالها را؛ اگر ارسال به پیامک یا لاگ تغییرات لازم است، روی اشیا حلقه بزنید یا کار را صریحاً انجام دهید. admin.site.disable_action("delete_selected")حذف گروهی را در کل ادمین غیرفعال میکند؛ یکی از رایجترین منشأهای فاجعهی «همهی سفارشها پاک شد».- ادمین با
extends "admin/base_site.html"در قالبی با همان نام کار میکند چون جنگو قالبهای پروژه را قبل از قالبهای اپ admin پیدا میکند؛ اپهای شما باید درDIRSیا قبل از admin در INSTALLED_APPS باشند. formfield_for_foreignkeyاجازه میدهد گزینههای یک ForeignKey را بر اساس کاربر محدود کنید؛ مثلاً هر نمایندهی فروش فقط مشتریان شهر خودش را ببیند.