Django REST - 使用序列化器创建具有外键的对象

mca*_*aro 6 python django django-rest-framework

我是Django和Django-REST的新手,所以请耐心等待.也许答案在文档中,所以如果我错过了,请提前道歉.

目标:我想创建一个EquipmentInfo对象,其属性包括预先存在的外键(EquipmentType和EquipmentManufacturer).

models.py

class EquipmentType(models.Model):
    equipment_type = models.CharField(verbose_name="Equipment Type", max_length=50, unique=True)

    def __unicode__(self):
        return self.equipment_type


class EquipmentManufacturer(models.Model):

    manufacturer_name = models.CharField(verbose_name="Manufacturer Name", max_length=50, unique=True)

    def __unicode__(self):
        return self.manufacturer_name


class EquipmentInfo(models.Model):

    equipment_type = models.ForeignKey(EquipmentType, verbose_name="Equipment Type")
    part_identifier = models.CharField(verbose_name="Machine ID (alias)", max_length=25)
    manufacturer_name = models.ForeignKey(EquipmentManufacturer, verbose_name="Manufacturer Name")
    serial_number = models.CharField(verbose_name="Serial Number", max_length=25)
    date_of_manufacture = models.DateField(verbose_name="Date of Manufacture", default=date.today)
    is_active = models.BooleanField(verbose_name="Is Active", default=True)

    def __unicode__(self):
        return self.part_identifier
Run Code Online (Sandbox Code Playgroud)

serializers.py

class EquipmentTypeSerializer(serializers.ModelSerializer):
    class Meta:
        model = EquipmentType
        fields = ('id', 'equipment_type',)

class EquipmentManufacturerSerializer(serializers.ModelSerializer):
    class Meta:
        model = EquipmentManufacturer
        fields = ('id', 'manufacturer_name',)

class EquipmentInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = EquipmentInfo
        fields = ('id', 'equipment_type', 'part_identifier', 'manufacturer_name','serial_number', 'date_of_manufacture', 'is_active')

    equipment_type = EquipmentTypeSerializer(many=False)
    manufacturer_name = EquipmentManufacturerSerializer(many=False)

    def create(self, validated_data):
        equipment_type = validated_data.pop('equipment_type')
        manufacturer_name = validated_data.pop('manufacturer_name')
        equipment_info = EquipmentInfo.objects.create(**validated_data)
        return equipment_info
Run Code Online (Sandbox Code Playgroud)

假设我已经创建了相关的EquipmentType和EquipmentManufacturer对象,我想添加另一个EquipmentInfo对象.设置我的EquipmentInfo序列化程序的适当方法是什么,以便我可以传递诸如的信息

{
 "equipment_type":{
  "equipment_type":"already_created",
 },
 "part_identifier":"something_new",
 "manufacturer_name":{
  "manufacturer_name":"already_created"
 },
 "serial_number":"WBA1",
 "date_of_manufacture": "1900-01-01",
 "is_active":true
}
Run Code Online (Sandbox Code Playgroud)

甚至更好:

{
 "equipment_type":"already_created",
 "part_identifier":"something_new",
 "manufacturer_name":"already_created",
 "serial_number":"WBA1",
 "date_of_manufacture": "1900-01-01",
 "is_active":true
}
Run Code Online (Sandbox Code Playgroud)

任何帮助表示赞赏.

dka*_*mer 4

使用嵌套序列化器会使帖子变得非常困难(如果它甚至可以工作,因为它以前不起作用),并且考虑到您的简单模型,我建议删除它们。

我建议您添加 API

/api/v1/type
/api/v1/manufacturer
/api/v1/info
Run Code Online (Sandbox Code Playgroud)

(或任何您想使用的名称)。和应该是普通视图并使用现有的序列化器typemanufacturer

对于info,删除两个嵌套序列化器:

class EquipmentInfoSerializer(serializers.ModelSerializer):
    class Meta:
        model = EquipmentInfo
        fields = ('id', 'equipment_type', 'part_identifier', 'manufacturer_name','serial_number', 'date_of_manufacture', 'is_active')
Run Code Online (Sandbox Code Playgroud)

之后,您应该能够使用以下方式发帖:

data = {
  "equipment_type": 5,  # The ID of the equipment type record
  "part_identifier":"something_new",
  "manufacturer_name": 10 # The ID of the manufacturer record
  "serial_number":"WBA1",
  "date_of_manufacture": "1900-01-01",
  "is_active":true
}
Run Code Online (Sandbox Code Playgroud)

就我而言,我确实喜欢使其 GET 更方便,因此我添加只读字段来返回名称(甚至整个序列化记录):

class EquipmentInfoSerializer(serializers.ModelSerializer):
    type_name = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = EquipmentInfo
        fields = ('id', 'equipment_type', 'part_identifier', 'manufacturer_name','serial_number', 'date_of_manufacture', 'is_active')

    def get_type_name(self, obj):
       return obj.equipment_type.equipment_type
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助。