Есть модель Product.
Как сделать так, чтобы при сохранении модели автоматически присваивалось значение полю type_of_product с параметром ManyToManyField. Через save() у меня выдает ошибку.
Код:
from django.db import models
from django.template.defaultfilters import slugify as django_slugify
alphabet = {'а': 'a', 'б': 'b', 'в': 'v', 'г': 'g', 'д': 'd', 'е': 'e', 'ё': 'yo', 'ж': 'zh', 'з': 'z', 'и': 'i',
'й': 'j', 'к': 'k', 'л': 'l', 'м': 'm', 'н': 'n', 'о': 'o', 'п': 'p', 'р': 'r', 'с': 's', 'т': 't',
'у': 'u', 'ф': 'f', 'х': 'kh', 'ц': 'ts', 'ч': 'ch', 'ш': 'sh', 'щ': 'shch', 'ы': 'i', 'э': 'e', 'ю': 'yu',
'я': 'ya'}
def slugify(s):
"""Транскрипция slug с кириллицы на англ алфавит"""
return django_slugify(''.join(alphabet.get(w, w) for w in s.lower()))
class ProductRubric(models.Model):
"""Модель рубрики"""
name = models.CharField(max_length=255, verbose_name='Название рубрики')
slug = models.SlugField(unique=True, db_index=True)
class Meta:
db_table = 'ProductRubric'
def __str__(self):
return self.name
def save(self, *args, **kwargs):
# Автоматическая генерация слага
self.slug = slugify(self.name)
super().save(*args, **kwargs)
class ProductType(models.Model):
"""Модель типа товара"""
name = models.CharField(max_length=255, verbose_name='Название типа товара')
slug = models.SlugField(unique=True, db_index=True)
class Meta:
db_table = 'ProductType'
def __str__(self):
return self.name
class Product(models.Model):
"""Модель товара"""
name = models.CharField(max_length=255, verbose_name='Название товара', db_index=True)
slug = models.SlugField(unique=True, db_index=True, blank=True, null=True, default=None)
author = models.CharField(max_length=255, verbose_name='ФИО автора')
description = models.TextField(verbose_name='Описание товара')
image = models.ImageField(upload_to='product_img/', verbose_name='Картинка товара')
price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name='Цена товара')
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
is_available = models.BooleanField()
rubric = models.ManyToManyField('ProductRubric', related_name='product')
# Тип товара (Цифровой, или материальный). При создании автоматически будет присвоено значение. Может быть одновременно два типа
type_of_product = models.ManyToManyField('ProductType', related_name='product', blank=True)
# Файл продукции присваевается только цифровому типу товара
file = models.FileField(upload_to='product_files/', verbose_name='Файл товара', blank=True, null=True)
# Вес и кол-во товара на складе присваевается только материальному товару
weight = models.PositiveIntegerField(verbose_name='Вес товара', blank=True, null=True)
count_of_product = models.PositiveIntegerField(verbose_name='Кол-во товара на складе', blank=True, null=True)
class Meta:
db_table = 'Product'
def save(self, *args, **kwargs):
# Проверка типа товара и генерация slug
self.is_available = True
digital = ProductType.objects.get(slug='digital')
material = ProductType.objects.get(slug='material')
if self.file and self.weight and self.count_of_product:
# Создание одновременно цифрового и материального товара
self.slug = 'material-and-digital-' + slugify(self.name)
self.type_of_product.add(material, digital)
elif self.file:
# Создание цифрового товара
self.slug = 'digital-' + slugify(self.name)
self.type_of_product.add(digital)
elif self.weight and self.count_of_product:
# Создание материального товара
self.slug = 'material-' + slugify(self.name)
self.type_of_product.add(material)
return super(Product, self).save(*args, **kwargs)
def __str__(self):
return f'{self.name}.'