我有按名称和位置定义的产品。每个产品都有一对唯一的名称/位置。
我正在编写一个能够创建产品的视图,我想首先检查它是否存在于DB中。 如果是,那么将ID保留在某处以将其返回到我的前端应用程序。 如果否,则创建它并获取ID。
根据我的研究,覆盖perform_create方法应该是解决方案,但我无法弄清楚如何。
任何帮助都将不胜感激。
urls.py
from django.conf.urls import url
from main.views import product_view
urlpatterns = [
url(r'^products/$', product_view.ProductCreate.as_view()),
url(r'^products/(?P<pk>[0-9]+)/$', product_view.ProductDetail.as_view()),
]
product_view.py
from rest_framework import generics
from rest_framework import permissions
from main.models import Product
from main.serializers import ProductSerializer
class ProductCreate(generics.CreateAPIView):
"""
Create a new product.
"""
permission_classes = (permissions.IsAuthenticated,)
serializer_class = ProductSerializer
queryset = Product.objects.all()
def perform_create(self, serializer):
if serializer.is_valid():
product_name = serializer.validated_data['product_name']
product_location = serializer.validated_data['product_location']
if product_name != '':
product_list = Product.objects.filter(
product_name=product_name, product_location=product_location)
if not product_list:
product = create_product(product_name, product_location)
else:
product = product_list[0]
serializer = ProductSerializer(product)
return Response(serializer.data)
else:
return Response(data={'message': 'Empty product_name'}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
class ProductDetail(generics.RetrieveUpdateAPIView):
"""
Retrieve, update or delete a product.
"""
permission_classes = (permissions.IsAuthenticated,)
serializer_class = ProductSerializer
queryset = Product.objects.all()
serializer.py
from django.contrib.auth.models import User
from rest_framework import serializers
from main.models import Product
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ('id',
'product_name',
'product_shop',
'product_url',
'product_img',
'product_location')
修改
产品型号:
class Product(models.Model):
product_name = models.CharField(max_length=200, blank=True)
product_shop = models.CharField(max_length=200, blank=True)
product_url = models.CharField(max_length=400, blank=False)
product_img = models.CharField(max_length=400, blank=True)
product_location = models.CharField(max_length=200, blank=False)
product_creation_date = models.DateTimeField(default=datetime.now, blank=True)
productgroup = models.ForeignKey(ProductGroup, blank=True, null=True, on_delete=models.CASCADE)
def __str__(self):
return '#' + str(self.pk) + ' ' + self.product_name + ' (' + self.product_shop + ')'
根据产品名称和位置自动创建产品。一个特定的功能是处理创建和履行数据。
我在前端应用中获得的结果是使用此代码丢失了一些数据。 以下是使用httpie:
的示例请求:http POST http://127.0.0.1:8000/products/ product_name =&#34;产品测试&#34; product_location =&#34; LOC1&#34; product_img =&#34; www.myimg.com&#34;
结果: HTTP / 1.0 201已创建 允许:POST,OPTIONS 内容长度:247 Content-Type:application / json 日期:2018年3月8日星期四,格林威治标准时间13:58:18 服务器:WSGIServer / 0.2 CPython / 3.5.3 变化:接受 X-Frame-Options:SAMEORIGIN
{ &#34; product_location&#34;:&#34; Loc1&#34;, &#34; product_name&#34;:&#34;产品测试&#34;, &#34; product_img&#34;:&#34; www.myimg.com&#34; }
在DB中,产品存在且具有product_shop和product_url的值,当然还有ID。
编辑2
我做了一些测试并记录了尽可能多的东西。
这是我的perform_create函数和记录器的结果:
def perform_create(self, serializer):
if serializer.is_valid():
product_name = serializer.validated_data['product_name']
product_location = serializer.validated_data['product_location']
if product_name != '':
product_list = Product.objects.filter(
product_name=product_name, product_location=product_location)
if not product_list:
product = create_product(product_name, product_location)
else:
product = product_list[0]
logger.info('product id : ' + str(product.id)) # Generated automatically
logger.info('product name : ' + product.product_name) # From the request
logger.info('product url : ' + product.product_url) # Generated by my create_product function
serializer = ProductSerializer(product)
logger.info('serializer.data['id'] : ' + str(serializer.data['id']))
return Response(serializer.data)
else:
return Response(data={'message': 'Empty product_name'}, status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
以下是结果,它们很好:
产品编号:3713
产品名称:产品1
产品网址:/ products / Product1 /...
serializer.data [&#39; id&#39;]:3713
在请求的结果中,我现在只有product_url和product_location ....
还有其他方法可以实现我的目标吗?
答案 0 :(得分:2)
首先需要检查序列化程序是否有效。然后你可以调用serializer.save()来创建新对象,或者只是创建新的序列化器对象并传递给它已经存在的产品:
def perform_create(self, serializer):
if serializer.is_valid():
product_name = serializer.validated_data['product_name']
product_location = serializer.validated_data['product_location']
if product_name != '':
product_list = Product.objects.filter(
product_name=product_name, product_location=product_location)
if not product_list:
product = serializer.save()
else:
product = product_list[0]
serializer = ProductSerializer(product)
return Response(serializer.data)
else:
return Response(data={'message': 'Empty product_name'},
status=status.HTTP_400_BAD_REQUEST)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
如果序列化程序的数据无效,则必须返回serializer.errors
。
答案 1 :(得分:0)
好的,所以我解决了我的问题,不使用perform_create。我回到了一个简单的APIView,并根据需要定义了POST方法。现在工作得很好。
class ProductCreate(APIView):
"""
Create a new product.
"""
permission_classes = (permissions.IsAuthenticated,)
def post(cls, request, format=None):
serializer = ProductSerializer(data=request.data)
if serializer.is_valid():
............