Abdul Rehman
Abdul Rehman

Reputation: 5674

Make a model field as required on the base of a condition in Django Models

I'm working on a project with Python(3.6) and Django(2.0) in which I need to make a field in child model required on the base of a condition for a field in parent model class.

If the service is multiple then the routing and configuration fields will be required otherwise it's not necessary to be filled.

Here's my code from models.py

From models.py:

services = (
    ('Single', 'Single'),
    ('Multiple', 'Multiple'),
)


class DeploymentOnUserModel(models.Model):
    deployment_name = models.CharField(max_length=256, )
    credentials = models.TextField(blank=False)
    project_name = models.CharField(max_length=150, blank=False)
    project_id = models.CharField(max_length=150, blank=True)
    cluster_name = models.CharField(max_length=256, blank=False)
    zone_region = models.CharField(max_length=150, blank=False)
    services = models.CharField(max_length=150, choices=services)
    configuration = models.TextField(blank=True)
    routing = models.TextField(blank=True)

    def save(self, **kwargs):
        if self.services == 'Multiple' and not self.routing and not self.configuration:
            raise ValidationError("You must have to provide routing for multiple services deployment.")
        super().save(**kwargs)

From serializers.py:

class DeploymentOnUserSerializer(serializers.ModelSerializer):
    class Meta:
        model = DeploymentOnUserModel
        fields = '__all__'

From apiview.py:

class DeploymentsList(generics.ListCreateAPIView):
    queryset = DeploymentOnUserModel.objects.all()
    serializer_class = DeploymentOnUserSerializer

    def get(self, request, *args, **kwargs):
        return self.list(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        serializer = DeploymentOnUserSerializer(data=self.request.data)
        validation = serializer.is_valid()
        if validation is True:
            perform_deployment(self.request.data)
            self.create(request=self.request)
        else:
            return Response('You haven\' passed the correct data ')
        return Response(serializer.data)

Post payload:

{
  "deployment_name": "first_deployment",
  "credentials":{
  "type": "service_account",
  "project_id": "project_id",
  "private_key_id": "private_key_id",
  "private_key": "-----BEGIN PRIVATE KEY",
  "client_email": "client_email",
  "client_id": "client_id",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://accounts.google.com/o/oauth2/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "client_x509_cert_url"
},
  "project_name": "project_name",
  "project_id": "project_id",
  "cluster_name": "numpy",
  "zone_region": "europe-west1-d",
  "services": "Single",
  "configuration": "",
  "routing": ""
}

Update: Now I have implemented apiview and serializers for these models. When I submit a post request with the services=Single without the values for configuration & routing it returns You haven't passed the correct data.

This means the save method, is not working. Help me, please!

Thanks in advance!

Upvotes: 3

Views: 3991

Answers (1)

JPG
JPG

Reputation: 88629

apart from my comment, you could override the save() method of AwdModel model.


from django.core.exceptions import ValidationError


class AwdModel(UserAccountModel):
    source_zip = models.FileField(upload_to='media/awdSource/', name='awd_source')
    routing = models.TextField(name='routing', null=True)

    def save(self, **kwargs):
        if not self.id and self.services == 'Multiple' and not self.routing:
            raise ValidationError("error message")
        super().save(**kwargs)

self.id will be null or similar if it's a new instance,hence the validation checks happens only if instance is created

Update-1 use this payload to POST

{
  "deployment_name": "first_deployment",
  "credentials":{"test_key":"test_value"},
  "project_name": "project_name",
  "project_id": "project_id",
  "cluster_name": "numpy",
  "zone_region": "europe-west1-d",
  "services": "Single",
  "configuration": "",
  "routing": ""
}

update-2 try this for your serializer,

class DeploymentOnUserSerializer(serializers.ModelSerializer):
    credentials = serializers.JSONField()
    class Meta:
        model = DeploymentOnUserModel
        fields = '__all__'

Upvotes: 2

Related Questions