J
J
Jekson2020-02-26 17:41:57
Django
Jekson, 2020-02-26 17:41:57

How to create instances of three models in one post request?

There are three interrelated models

class VendorContacts(models.Model):
    contact_id = models.AutoField(primary_key=True)
    vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE)
    contact_name = models.CharField(max_length=45, blank=True)
    phone = models.CharField(max_length=45, blank=True)
    email = models.CharField(max_length=80, blank=True, unique=True)

    class Meta:
        db_table = 'vendor_contacts'


class VendorModuleNames(models.Model):
    vendor = models.OneToOneField('Vendors', on_delete=models.CASCADE, primary_key=True)
    module = models.ForeignKey(Modules, models.DO_NOTHING)
    timestamp = models.DateTimeField(auto_now=True)

    class Meta:
        db_table = 'vendor_module_names'
        unique_together = (('vendor', 'module'),)


class Vendors(models.Model):
    COUNTRY_CHOICES = tuple(COUNTRIES)

    vendorid = models.AutoField(primary_key=True)
    vendor_name = models.CharField(max_length=45, unique=True)
    country = models.CharField(max_length=45, choices=COUNTRY_CHOICES)
    nda = models.DateField(blank=True, null=True)
    user_id = models.ForeignKey('c_users.CustomUser', on_delete=models.PROTECT)
    timestamp = models.DateTimeField(auto_now_add=True)

    class Meta:
        db_table = 'vendors'
        unique_together = (('vendorid', 'timestamp'),)


serializer.py

class VendorsSerializer(serializers.ModelSerializer):

    class Meta:
        model = Vendors
        fields = ('vendor_name',
                  'country',
                  'nda',
                  'parent_vendor',)


class VendorContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorContacts
        fields = (
                  'contact_name',
                  'phone',
                  'email',)


class VendorModulSerializer(serializers.ModelSerializer):

    class Meta:
        model = VendorModuleNames
        fields = ('module',)


views.py

class VendorsCreateView(APIView):
    """Create new vendor instances from form"""
    serializer_class = (VendorsSerializer)

    def post(self, request, *args, **kwargs):
        vendor_serializer = VendorsSerializer(data=request.data)
        vendor_contact_serializer = VendorContactSerializer(data=request.data)
        vendor_modules_serializer = VendorModulSerializer(data=request.data)
        try:
            vendor_serializer.is_valid(raise_exception=True) \
                and vendor_contact_serializer.is_valid(raise_exception=True) \
                and vendor_modules_serializer.is_valid(raise_exception=True) \
            vendor = vendor_serializer.save(user_id=CustomUser.objects.get(id=2))
            vendor_contact_serializer.save(vendor=vendor)
            vendor_modules_serializer.save( vendor=vendor)

        except ValidationError:
            return Response({"errors": (vendor_serializer.errors,
                                        vendor_contact_serializer.errors,
                                        vendor_modules_serializer.errors
                                        )},
                            status=status.HTTP_400_BAD_REQUEST)
        else:
            return Response(request.data, status=status.HTTP_200_OK)


I am sending json like this

{
        "vendor_name": "Awrddaosgsgpxsdsxjwszsslsasdjegdzasas",
        "country": "RU",
        "module": [
        	1,
        	2
        ],
        "NDA date": "",
        "contact_name": "Tim",
        "email": "[email protected]",
        "phone": "+3464784594940",
        "parent_vendor": "21"
    }


And I get an error

{
    "module": [
        "Incorrect type. Expected pk value, received list."
    ]
}


If I replace json
"module": [1, 2]with , "module":1then everything works. But I have a Foreignkey connection, so I need a multi-select option. Or maybe I'm not using the correct json and list is not appropriate in it? Basically, I can't figure out what to do.

Answer the question

In order to leave comments, you need to log in

1 answer(s)
V
Vladimir Kuts, 2020-02-26
@Lepilov

You somehow do everything crutch. You should have something like this:

from drf_writable_nested.serializers import WritableNestedModelSerializer


class VendorContactSerializer(serializers.ModelSerializer):
    class Meta:
        model = VendorContacts
        fields = (
                  'contact_name',
                  'phone',
                  'email',)

class VendorModulSerializer(serializers.ModelSerializer):

    class Meta:
        model = VendorModuleNames
        fields = ('module',)

class VendorsSerializer(WritableNestedModelSerializer):
    vendorcontact = VendorContactSerializer(source='vendor.vendorcontacts', many=True)
    vendormodulenames = VendorContactSerializer(source='vendor.vendormodulenames', many=True)

    class Meta:
        model = Vendors
        fields = ('vendor_name',
                  'country',
                  'nda',
                  'parent_vendor',)

And then most of the code that you piled up in the post view is not required. And you can create several instances
According to sources, just specify how your back relations are called

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question