Django REST - creating an object with a foreign key using serializers

I am a little new to Django and Django-REST, so please bear with me. Perhaps the answer is in the documentation, so if I missed this, I apologize in advance.

Purpose:. I would like to create a EquipmentInfo object whose attributes include pre-existing foreign keys (EquipmentType and 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 

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 

Assuming I already have the corresponding EquipmentType and EquipmentManufacturer objects, I would like to add another EquipmentInfo object. What is a suitable way to configure my EquipmentInfo serializer so that I can pass information such as

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

or even better:

 { "equipment_type":"already_created", "part_identifier":"something_new", "manufacturer_name":"already_created", "serial_number":"WBA1", "date_of_manufacture": "1900-01-01", "is_active":true } 

Any help is appreciated.

+6
source share
2 answers

Using nested serializers makes it very difficult for messages (if it even works because it didn't work), and given your simple models, I would recommend just deleting them.

I recommend that you add an API for

 /api/v1/type /api/v1/manufacturer /api/v1/info 

(or any names you want to use). type and manufacturer should look like vanilla and use existing serializers.

For info remove two nested serializers:

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

After that, you can make messages using:

 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 } 

In my case, I like to make this GET more convenient, so I add read-only fields to return the name (or even the entire serialized record):

 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 

Hope this helps.

+1
source

I also ran into a problem and solved it, my next step, I hope that it will be useful 1. Model model and contact model as follows:

 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.I create a new serializer called CompanyReferenceSerializer , and company_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 as follows, in the backend I get a Named company_instance object according to 'company_id'

 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) 

and I manage to insert one record in company_contact, I hope this can help you!

0
source

All Articles