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

时间:2016-02-22 00:04:53

标签: python django django-rest-framework

我对Django和Django-REST有点新鲜,所以请耐心等待。也许答案在文档中,所以如果我错过了,请提前道歉。

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

models.py

$(".image").on('click', function(){
    $('.image').removeClass('selected');
  $(this).addClass('selected');
  sendToDatabase($(this).attr('id'));
});

function sendToDatabase(data) {
    //$.post(saveToDatabase.php,{id: data}, function(){
    //    post request to your controler in php 
    //});
}

serializers.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

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

之类的信息
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

甚至更好:

{
 "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
}

感谢任何帮助。

2 个答案:

答案 0 :(得分:2)

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

我建议您添加

的API
/api/v1/type
/api/v1/manufacturer
/api/v1/info

(或您想要使用的任何名称)。 typemanufacturer应该是vanilla视图并使用现有的序列化程序。

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

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

之后,您应该可以使用以下方式进行发布:

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
}

在我的情况下,我喜欢使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

希望这有帮助。

答案 1 :(得分:0)

我也遇到了问题,并且已经解决了,以下是我的步骤,希望它会有所帮助  1.company模型和联系模型如下:

class Company(models.Model):
    Company_Name = models.CharField(u'Company Name',max_length=255, default="")
    Modified_By = models.CharField(u'Modified By',max_length=255, default="")



class Company_Contact(models.Model):
     Company = models.ForeignKey(Company)
     Last_Name = models.CharField(u'Last Name',max_length=255, default="")
     First_Name = models.CharField(u'First Name',max_length=255, default="")

2.我创建一个名为CompanyReferenceSerializercompany_contact

的新序列化程序
class CompanyReferenceSerializer(serializers.ModelSerializer):
class Meta:
    model = Company
    fields = ['id', 'Company_Name', 'Company_Name_SC']





class CompanyContactSerializer(serializers.ModelSerializer):
   Company =  CompanyReferenceSerializer()
class Meta:
    model = Company_Contact
    fields = ['Company', 'Last_Name','First_Name']
    extra_kwargs = {
        'Company': {'allow_null': True, 'required': False},
        'Last_Name': {'allow_null': True, 'allow_blank': True, 'required': False}, 
        'First_Name': {'allow_null': True, 'required': False, 'allow_blank': True},     
    }

3.Viewset如下,在后端,我根据'company_id'得到名为company_instance的对象

class CompanyContactViewSet(viewsets.ModelViewSet):
     serializer_class = CompanyContactSerializer
def create(self, validated_data):
    serializer = self.get_serializer(data=self.request.data)
    company_id_for_contact =  self.request.data.pop('Company_id')
    company_instance = Company.objects.filter(id=company_id_for_contact).first()
    if not serializer.is_valid():
        print serializer.errors
    data = serializer.validated_data
    serializer.save(Company=company_instance)
    headers = self.get_success_headers(serializer.data)
    return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers) 

我成功在company_contact中插入一条记录,希望它可以帮到你!