Как добавить несколько товаров в корзину?
Django Admin — довольно мощный инструмент при работе с данными в стиле CRUD (создание, чтение, модификация, удаление). Одна из особенностей, о которой многие (даже опытные) разработчики не подозревают, — это наличие нескольких строк «many-one» или «many-to-many» на одной странице, как показано на этом рисунке:
Потрясно, правда? А рецепт простой, давайте посмотрим.
Data (Models)
from django.db import models
class Item(models.Model):
name = models.CharField(max_length=100)
price = models.DecimalField(default=0, decimal_places=2, max_digits=10)
def __str__(self):
return f"{self.name}: ${self.price}"
class Cart(models.Model):
created = models.DateTimeField(auto_now_add=True)
paid = models.BooleanField(default=False)
def total_price(self):
return sum([
cart_item.total()
for cart_item in CartItem.objects.filter(cart=self)
])
def __str__(self):
return f"{self.created}, ${self.total_price()}: {self.paid}"
class CartItem(models.Model):
cart = models.ForeignKey(Cart, on_delete=models.CASCADE)
item = models.ForeignKey(Item, on_delete=models.CASCADE)
count = models.IntegerField(default=1)
def total(self):
return self.count * self.item.price
def __str__(self):
return f"{self.item.name}, " \
f"${self.item.price} * {self.count} = ${self.total()}"
Модели просты: у нас есть Items, Carts и таблица CartItem для отношения многие-ко-многим между Items и Carts. Мы не могли использовать здесь models.ManyToManyField
, так как нам нужно дополнительное поле “count” внутри отношений. Когда я сам создаю отношения, это кажется более прозрачным.
Admin
Внутри Admin мы не просто регистрируем модели напрямую, нам нужно создать классы ModelAdmin
и StackedInline
.
Идея заключается в следующем. Сначала мы создаем многострочное представление (multiline view) для поддержки CRUD в таблице CartItem. А затем мы добавляем это представление к представлению корзины.
Это делается следующим образом:
from django.contrib import admin
from shop.models import Cart, Item, CartItem
class ItemInline(admin.StackedInline):
model = CartItem
extra = 5
class CartAdmin(admin.ModelAdmin):
inlines = [ItemInline]
list_display = ["created", "total_price", "paid"]
admin.site.register(Cart, CartAdmin)
admin.site.register(Item)
Вот и все. Полезная вещь и не занимает много времени.
Скоро состоится открытое занятие «О "регулярках" и не только», на котором:
- Поговорим о роли регулярных выражений в разработке.
- Оценим эффект от re.compile.
- Попробуем переписать код без использования регулярок и посмотрим, стоит ли тратить время на изучение этой непростой темы.Регистрируйтесь по ссылке.
danilovmy
Я бы не рискнул StackedInline называть Multiline-View. Стакед Инлайн это менеджер для организации работы формсета внутри Model admin form со своим косячным способом этот формсет отрендерить. Multiline-View это например List View - отношения к инлайнам не имеет. Тимуру спасибо за копи паст документации отсюда https://docs.djangoproject.com/en/4.1/ref/contrib/admin/#inlinemodeladmin-objects