I am new to Django. Reading a lot of ways to do the same thing--but not finding the proverbial needle in a haystack. One such needle is a simple "Find or Create" pattern for Django Rest.
I am trying to find a simple example of how to go about implementing a find or create pattern for one of my model data using Django Rest ModelSerializer and CreateAPIView methods. Let say that I have a model Location with a unique field 'address'. I want to return an existing instance when the address already exists on my database. If the address does not exist, I want to create an entry in the database and populate other computed values for the object.
address = models.CharField(max_length=100, unique=True,)
thing1 = models.CharField(max_length=100, blank=True, null=True, )
thing2 = models.CharField(max_length=100, blank=True, null=True, )
def compute_things(self, address):
somevalue1 = ...
somevalue2 = ....
return somevalue1, somevalue2
model = Location
serializer_class = LocationCreateSerializer
queryset = Location.objects.all()
Ok, I figured out the answer to my own question. I am not sure this is the best solution; however, for anyone that needs a solution, here is what I ended up doing:
class LocationCreateAPIView(CreateAPIView): serializer_class = LocationCreateSerializer queryset = Location.objects.all() def post(self, request, format=None): address = None if 'address' in self.request.data: address = self.request.data['address'] else: return Response(status=HTTP_400_BAD_REQUEST) try: location = Location.objects.get(address=address) serializer = self.get_serializer(location) return Response(serializer.data, status=HTTP_200_OK) except Location.DoesNotExist: pass serializer = LocationCreateSerializer(data=self.request.data) if serializer.is_valid(): somevalue1, somevalue2 = Location.compute_things(self, address=address) if (not somevalue1) | (not somevalue2): return Response(status=HTTP_400_BAD_REQUEST) serializer.save(address=address, thing1=somevalue1, thing2=somevalue2) return Response(serializer.data, status=HTTP_201_CREATED) return Response(status=HTTP_400_BAD_REQUEST)
If you have a better solution, please post it. I'd like to continue learning.