django嵌套了具有中间表的多对多关系的序列化

时间:2015-11-16 17:36:03

标签: django serialization django-rest-framework django-serializer

我已经看过很多关于如何反序列化和序列化具有多对多关系的表的嵌套关系的帖子,但是当在多对多关系中使用中间表时,我无法实现反序列化。

这是因为中间表需要两个外键,每个外键来自参与该关系的两个表。

我有订单模型和服务模型,它们通过 OrderItem 中间表处于多对多关系中。

我需要传递一个像这样的JSON请求:

{"service_time":"2015-11-14 10:00:51+0530",
  "address":"xyz",
   "items":[{"order": "1", "service_id":"4"},
               {"order":"1", "service_id":"5"}]
}

" service_time"和"地址"元素保存在订单表中。现在问题出现在"项目" JSON数组。我通过" service_id" (服务表的外键)我需要通过" order" (Order表的外键),因为它是必填字段。问题是发送请求时不知道 Order 表的主键(因为Order也是作为同一请求的一部分创建的)。如何在这种情况下实现反序列化?

我尝试过这样的事情,但它没有成功。

class OrderSerializer(serializers.ModelSerializer):
    items = ItemSerializer(many=True)

    class Meta:
        model = Order

    def create(self, validated_data):
        items_data = validated_data.pop('items')
        orders = Order.objects.create(**validated_data)
        for item in items_data:
            #order = item['order']
            service = item['service']
            //Passing the Order object just created as the foreign key of OrderItem
            orderItem = OrderItem.objects.create(order=orders, service=service)
            orderItem.save()
        return orders

class ServiceSerializer(serializers.ModelSerializer):
    group = serializers.CharField(source="group.group_name")
    category = serializers.IntegerField(source="group.category_id")

    class Meta:
        model = Service
        fields = ['id', 'service_name', 'price', 'special_price', 'service_time', 'group', 'category']

class ItemSerializer(serializers.ModelSerializer):
    service_detail = ServiceSerializer(source="service", read_only=True)

    class Meta:
        model = OrderItem

我收到错误消息' Service'对象没有属性' order'

我知道服务模型没有"订单"属性,但我正在创建 OrderItem 对象,而不是服务对象。

任何建议都会有所帮助!

编辑:添加使用的模型

class Order(models.Model):
    STATUSES = [('PENDING', 'Pending'), ('PROCESSING', 'Processing'), ('COMPLETE', 'Complete'), ('CANCELED', 'Canceled')]
    PAYMENT_STATUSES = [('PENDING', 'Pending'), ('PAID', 'Paid'),]
    CANCEL_REASON = [('NO_SERVICE', 'No Service In Area'), ('NO_STYLIST', 'Stylist Not Available'), ('STYLIST_REFUSED', 'Stylist Refused After Accepting',), 
            ('CUSTOMER_UNREACHABLE', 'Customer Not Reachable'), ('CUSTOMER_CANCELED', 'Customer Canceled at Fisrt Call'), ('CUSTOMER_REFUSED', 'Customer Refused at Last Moment'), 
            ('DUPLICATE_ORDER', 'Duplicate Order'), ('MALE_CLIENT', 'Male Client'), ('CALLCENTER_DELAY', 'Delay/Error at Frontdesk')]
    serial = models.CharField(max_length=10, null=True, blank=True,)
    customer = models.ForeignKey(Customer, verbose_name="customer", related_name="ordersbycustomer")
    stylist = models.ForeignKey(Stylist, null=True, blank=True, verbose_name="stylist", related_name="ordersbystylist")
    # TODO, Use timezone.now
    service_time = models.DateTimeField(default=timezone.now, blank=True)
    started_moving = models.DateTimeField(null=True, blank=True)
    service_start_at = models.DateTimeField(null=True, blank=True)
    service_end_at = models.DateTimeField(null=True, blank=True)
    reached_safely = models.DateTimeField(null=True, blank=True)
    sub_total = models.FloatField(default=0)
    discounts = models.FloatField(default=0)
    grand_total = models.FloatField(default=0)
    total_time = models.IntegerField(default=0)
    status = models.CharField(max_length=32, choices=STATUSES, default='PENDING')
    payment_status = models.CharField(max_length=32, choices=PAYMENT_STATUSES, default='PENDING')
    items = models.ManyToManyField(Service, through='OrderItem')
    address = models.ForeignKey(Address, null=True,  blank=True, related_name='+',  on_delete=models.SET_NULL)
    amount_received = models.FloatField(default=0)
    send_sms = models.BooleanField(default=True)
    thru_app = models.BooleanField(default=True)
    referral_discount = models.FloatField(default=0)
    cancellation_reason = models.CharField(max_length=64, choices=CANCEL_REASON, null=True, blank=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.serial

    def _get_service_list(self):
        return ','.join(str(p.description) for p in self.items.all())

    service_list = property(_get_service_list)


class Service(models.Model):
    group = models.ForeignKey(Group, related_name="services")
    service_name = models.CharField(max_length=128)
    price = models.FloatField(default=0)
    special_price = models.FloatField(default=0)
    service_time = models.IntegerField()
    description = models.CharField(max_length=123)
    is_active = models.BooleanField(default=True)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return '{} ({})'.format(self.service_name, self.group)


class OrderItem(models.Model):
    order = models.ForeignKey(Order)
    service = models.ForeignKey(Service)
    price = models.FloatField(default=0)
    special_price = models.FloatField(default=0)
    qty = models.IntegerField(default=1)
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def __unicode__(self):
        return self.service.service_name

Edit2:添加了其他相关的序列化程序。

我忘记提到的一件重要事情是,数据会保存在数据库中,但仍会引发异常。

0 个答案:

没有答案