[Fixed]-Get params validation on viewsets.ModelViewSet

8👍

You can make serializers, they have a very easy way to validate your data. As in your case all the fields seem to be required it becomes even easier.

Create a file on you api app like:

serializers.py

#Import Serializers lib
from rest_framework import serializers

#Import your models here (You can put more than one serializer in one file)
from assets.model import Assets

#Now make you serializer class
class AssetsSerializer(serializers.ModelSerializer):
    class Meta:
        model = Profile
        fields = '__all__' 
        #This last line will put all the fields on you serializer
        #but you can also especify only some fields like:
        #fields = ('assetid', 'assetname')

On you view you can use your serializer(s) class to validate you data.

views.py

#Serializers
from assets.serializers import AssetsSerializer

#Libraries you can use
from django.http import Http404
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status

class AssetsViewSet(viewsets.ModelViewSet):
    queryset = Assets.objects.using("gpr").all()

    def create(self, request):
        assets = []
        farming_details = {}
        #Set your serializer
        serializer = AssetsSerializer(data=request.data)
        if serializer.is_valid(): #MAGIC HAPPENS HERE
            #... Here you do the routine you do when the data is valid
            #You can use the serializer as an object of you Assets Model
            #Save it
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

i took this all from the documentation. You can learn a lot doing the tutorial from the official site. I hope it helps.

4👍

You can do something like:

for param in ['bluenumberid', 'actorid', 'asset_details']:
    if param not in request.data.keys():
        raise Response({'error': '%s is required.' % param}) 

...

for asset_detail in asset_details:
    for param in ['location', ..., 'longitude']:
        if param not in asset_detail.keys():
            raise Response({'error': '%s is required.' % param}) 

3👍

This is just a guide that you can follow for refactoring, of course many other things can be improved while performing this:

  • make a ModelSerializer for model Assets
  • AssetsModelSerializer should handle validation
  • within AssettsModelSerializer add any related ModelSerializer (like Locations) that has specific validation and representation
  • move the create method to AssetsModelSerializer and just handle there the model creation
  • AssetModelSerializer should provide a specific to_representation (if needed)
  • The AssetsViewSet is doing more then one thing as I see (especially the last part with FarmingAssets objects) can you split that logic in another view? or route?

Leave a comment