Как сохранить несколько объектов в базу данных в представлениях django rest framework
Итак, я пытаюсь добавить новый продукт в мою базу данных, используя django's restapi. но продукт может содержать несколько категорий, которые связаны через третью много-ко-многим модель и дополнительные изображения, которые являются внешними ключами к продукту
вот мой models.py
class Products(models.Model):
product_id = models.AutoField(primary_key=True)
name = models.CharField(max_length=35, null=False, unique=True)
description = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.)
main_image = models.FileField(upload_to='shop/images')
created_on = models.DateTimeField(blank=True, default=datetime.now)
class Category(models.Model):
category_id = models.AutoField(primary_key=True)
category = models.CharField(max_length=20, null=True, blank=True)
created_on = models.DateTimeField(blank=True, default=datetime.now)
class Meta:
db_table = 'Category'
class ProductsCategory(models.Model):
productscategory_id = models.AutoField(primary_key=True)
category = models.ForeignKey(to=Category, on_delete=models.CASCADE)
product = models.ForeignKey(to=Products, on_delete=models.CASCADE)
created_on = models.DateTimeField(blank=True, default=datetime.now)
class Meta:
db_table = 'ProductsCategory'
class Pictures(models.Model):
picture_id = models.AutoField(primary_key=True)
image = models.FileField(upload_to='shop/images')
product = models.ForeignKey(to=Products, on_delete=models.CASCADE)
created_on = models.DateTimeField(blank=True, default=datetime.now)
class Meta:
db_table = 'Pictures'
и вот что я попробовал:
@api_view(['POST'])
@permission_classes([IsModerator])
def create_product(request):
product_details = ProductsSerializer(request.POST, request.FILES)
pictures = PicturesSerializer(request.POST, request.FILES, many=True)
category_list = request.POST.getlist("category")
if product_details.is_valid() and validate_file_extension(request.FILES.get("main_image")):
try:
product = product_details.save()
if len(category_list) > 0:
for i in category_list:
if check_category(i):
category = Category.objects.get(category=i)
ProductsCategory.objects.create(category=category, product=product)
else:
category = Category.objects.create(category=i)
ProductsCategory.objects.create(category=category, product=product)
if pictures:
for image in request.FILES.getlist("image"):
if validate_file_extension(image):
Pictures.objects.create(image=image, product=product)
else:
error = {"error": "invalid extra pictures extension"}
return Response(error)
return Response((product_details.data, pictures.data, category_list), status=status.HTTP_201_CREATED)
except Exception as e:
return Response(e)
else:
return Response((product_details._errors, pictures._errors), status=status.HTTP_400_BAD_REQUEST)
и вывод: введите здесь описание изображения
как я должен использовать этот ввод содержимого? или если вы знаете лучший ответ на мой главный вопрос о сохранении нескольких моделей в базе данных и их взаимосвязей, пожалуйста, оставьте ответ, заранее спасибо
Я предлагаю вам изменить структуру models.py
на следующую:
from django.db import models
class Category(models.Model):
category = models.CharField(max_length=20, null=True, blank=True)
created_on = models.DateTimeField(auto_now=True)
class Meta:
verbose_name_plural = "Categories"
class Picture(models.Model):
image = models.FileField(upload_to='shop/images')
product = models.ForeignKey(to=Products, on_delete=models.CASCADE)
created_on = models.DateTimeField(blank=True, default=datetime.now)
class Product(models.Model):
name = models.CharField(max_length=35, null=False, unique=True)
description = models.CharField(max_length=255)
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.)
main_image = models.FileField(upload_to='shop/images')
more_images = models.ManyToManyField(Pictures, on_delete=models.CASCADE)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
created_on = models.DateTimeField(auto_now=True)
Затем в своем serializer.py
добавьте:
from rest_framework import serializers
from .models import Category, Picture, Product
class CategorySerializer(serializers.ModelSerializer):
class Meta:
model = Category
fields = "__all__"
class PictureSerializer(serializers.ModelSerializer):
class Meta:
model = Picture
fields = "__all__"
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = "__all__"
В вашем views
я предлагаю использовать ViewSets
:
views.py
from .models import Category, Picture, Product
from .serializer import CategorySerializer, PictureSerializer, ProductSerializer
from rest_framework import viewsets
# import custom permissions if any
class CategoryViewSet(viewsets.ModelViewSet):
serializer_class = CategorySerializer
queryset = Category.objects.all()
class PictureViewSet(viewsets.ModelViewSet):
serializer_class = PictureSerializer
queryset = Picture.objects.all()
class ProductViewSet(viewsets.ModelViewSet):
serializer_class = ProductSerializer
queryset = Product.objects.all()
permission_classes = [IsModerator]
В вашем приложении urls.py
добавьте маршрутизатор для ваших наборов представлений, и он автоматически создаст пути для ваших представлений:
from django.urls import path
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
router.register(r'category', views.CategoryViewSet, basename='category')
router.register(r'picture', views.PictureViewSet, basename='picture')
router.register(r'product', views.ProductViewSet, basename='product')
urlpatterns = [
path('', include(router.urls)),
]
Журнал изменений:
- Вам не нужно добавлять поле ID в каждую модель, Django делает это за вас. Если только это не особый случай.
- Ваши таблицы базы данных по умолчанию называются по имени вашей модели. Так что нет необходимости указывать и это.
- Я упростил структуру ваших моделей, чтобы сделать ее более чистой. Но она по-прежнему делает то, что вы хотите.
- Django добавляет
s
для создания множественного имени для каждой модели. Поэтому вы можете называть ее в единственном числе, если не нужно уточнять. Например,categories
. .
- Наборы представлений сократят вашу работу, предоставляя вам действия по составлению списков и извлечению информации.
Для доступа к конкретному экземпляру, например, продукта, достаточно добавить /<product id>
после конечной точки листинга и создания продукта.
Примечание: Вы должны добавить id без скобок.
Я также предлагаю вам пройти это руководство DRF. Это улучшит ваше понимание Django REST framework.