我有一个商业模型和订单模型。企业可以在我们的网站上订购家具。用户创建帐户并下订单。由于他是新用户,因此与任何企业没有关联。在订单中,他会提供有关他的业务的信息以及与当前订单相关的一些信息。将使用给定信息创建新的业务记录和订单记录。订单表中的业务有一个外键。
如果他想创建第二个订单,因为他已经有一家企业,他将在表格中预先填写企业信息。当他给出订单数据并提交时,后端不会创建新的业务记录。它仅创建订单记录并存储业务参考。
如何在单个端点中实现此目的以创建更新和检索?
# models.py
class Order(models.Model):
applicant = models.ForeignKey(User, on_delete=models.DO_NOTHING, related_name='Applicant', blank=True, null=True)
business = models.ForeignKey(Business, on_delete=models.DO_NOTHING, related_name='Business', blank=True, null=True)
code = models.CharField(verbose_name='Order Code', max_length=100, blank=True, null=True)
chairs = models.IntegerField(verbose_name='Chairs', blank=True, null=True)
tables = models.IntegerField(verbose_name='Tables', blank=True, null=True)
delivery_type = models.CharField(verbose_name='Delivery Type', max_length=100, blank=True, null=True)
payment_type = models.CharField(verbose_name='Payment Type', max_length=100, blank=True, null=True)
STATUS_CHOICES = (
('CREATED', 'Created'),
('IN_PROGRESS', 'In Progress'),
('CANCELLED', 'Cancelled'),
('SHIPPED', 'Shipped'),
)
status = models.CharField(max_length=20, choices=STATUS_CHOICES, blank=True, null=True, default='CREATED')
class Business(models.Model):
name = models.CharField(verbose_name='Legal Name', max_length=100, blank=True, null=True)
code = models.CharField(verbose_name='Business Code', max_length=100, blank=True, null=True)
website = models.CharField(verbose_name='Website URL', max_length=100, blank=True, null=True)
address = models.TextField(verbose_name="Street Address 1", blank=True, null=True)
city = models.CharField(verbose_name='City', max_length=250, blank=True, null=True)
state = models.CharField(verbose_name='State', max_length=200, blank=True, null=True)
country = models.CharField(verbose_name='Country', max_length=200, blank=True, null=True)
# serializers.py
import time
class BusinessSerializer(serializers.ModelSerializer):
class Meta:
model = Business
fields = '__all__'
def create(self, validated_data):
timestamp = int(time.time())
random_number = random.randint(100,999)
validated_data['code'] = f'BUSINESS-{timestamp}'
validated_data['status'] = 'CREATED'
return super().create(validated_data)
class OrderSerializer(serializers.ModelSerializer):
class Meta:
model = Order
fields = '__all__'
def create(self, validated_data):
timestamp = int(time.time())
random_number = random.randint(100,999)
validated_data['code'] = f'ORDER-{timestamp}'
validated_data['status'] = 'CREATED'
return super().create(validated_data)
# views.py
class BusinessOrderAPIView(generics.CreateAPIView):
permission_classes = [IsAuthenticated]
queryset = Order.objects.all()
serializer_class = OrderSerializer
def perform_create(self, serializer):
business_data = self.request.data.get('business', {})
business_id = business.get('id')
if business_id:
try:
business = Business.objects.get(pk=business_id)
except Business.DoesNotExist:
business = Business.objects.create()
business.name = business_data.get('name')
business.website = business_data.get('website')
business.address = business_data.get('address')
business.city = business_data.get('city')
business.state = business_data.get('state')
business.country = business_data.get('country')
business.save()
order = serializer.save(business=business.pk)
这就是我的请求的样子
{
"chairs": 3,
"tables": 1,
"delivery_type": "ONE_DAY",
"payment_type": "CASH_ON_DELIVERY",
"business": {
"name": "Vin.AI",
"website": "https://lol.com",
"address": "My street",
"city": "Gotham City",
"state": "New York",
"country": "USA",
}
}
这是我收到的回复
{
"business": [
"Incorrect type. Expected pk value, received dict."
]
}
问题很简单。您的序列化程序期望
business
字段作为 PK,而不是您在有效负载中发送的字典。然而,为了执行所需的操作,一些工作是必要的。另外,模型也有点奇怪,但我不会深入讨论。
目前,
Business
模型没有可以将 User
与其关联的字段。这意味着,您会知道谁制造了 Order
,但不知道是谁创造了 Business
。
根据你所说的,我认为一个
Business
属于一个User
并且只有一个。 (当然,您可以通过一对多关系轻松修改它)。
因此,从对模型进行小修改开始,从
applicant
中删除 Order
并添加到 Business
(我猜是所有者):
class Business(models.Model):
applicant = models.OneToOneField(
User,
on_delete=models.DO_NOTHING,
primary_key=True
)
...
另外,
BusinessSerializer
上有一个小错误,没有名为 status
的字段,删除该行:
class BusinessSerializer(serializers.ModelSerializer):
class Meta:
...
def create(self, validated_data):
...
# validated_data["status"] = "CREATED"
return super().create(validated_data)
解决这个问题的方法不止一种。但为了简单起见:
User
是否有Business
class BusinessOrderAPIView(generics.CreateAPIView):
permission_classes = [permissions.IsAuthenticated]
queryset = Order.objects.all()
serializer_class = OrderSerializer
business_serializer = BusinessSerializer
def create(self, request, *args, **kwargs):
user_business = None
try:
user_business = request.user.business
except ObjectDoesNotExist:
business = request.data.pop("business")
business["applicant"] = request.user.pk
business_serializer = self.business_serializer(data=business)
business_serializer.is_valid(raise_exception=True)
user_business = business_serializer.save()
request.data["business"] = user_business.pk
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
self.perform_create(serializer)
headers = self.get_success_headers(serializer.data)
return Response(
serializer.data, status=status.HTTP_201_CREATED, headers=headers
)
您可以通过多种形式修改此代码。如果您想保留原始格式,只需使用
try/except
来查询给定一些唯一标识符(例如 Business
或 name
)的 website
。