CRUD: Create & Delete
Intro
So far our application has READ and UPDATE capabilities for both Moves and Pokemon. Lets go into the last two methods and complete our CRUD capabilities in our API by adding a CREATE and DELETE capability to our API.
Create
When we create something we are technically POSTING something new onto our database and therefore built a relationship where CREATE = POST and POST = CREATE. Always correlate POST to CREATE with the exception of handling user Authentication. The question then comes where do we want this
POSTmethod to live. Lets say I want to create a new Pokemon, since I'm creating a new entry onto the list of Pokemon I would want this method to exist at theAll_pokemonCBV.
# pokemon_app/views.py
class All_pokemon(APIview):
authentication_classes = []
permission_classes = []
# specify the request method that should trigger this behavior
def post(self, request):
# We could create a pokemon by specifying each individual field but that's obviously not optimal
# new_pokemon = Pokemon(name = request.data['name'], level = request.data['level'], description = request.data['description'])
# instead we can use the PokemonSerializers kwargs method and pass in request.data (a dict) into the create argument
new_pokemon = PokemonSerializer(data=request.data)
if new_pokemon.is_valid():
new_pokemon.save()
return Response(new_pokemon.data, status=HTTP_201_CREATED)
else:
return Response(new_pokemon.errors, status=HTTP_400_BAD_REQUEST)
Now that we have a flexible and well constructed API view to create a Pokemon, we can test it with
Thunder Clientby sending aPOSTrequest tohttp://127.0.0.1:8000/api/v1/pokemon/with all of the following data.Our API is working correctly and it is able to validate data and create a new entry onto our database utilizing the
POSTmethod.
Delete
Deleting an item from a database is surprisingly simple. We could utilize the already established
A_pokemonCBV to get a pokemon instance and then call the .delete() method to delete an item from our database.
# pokemon_app/views.py
class A_pokemon(APIView):
authentication_classes = []
permission_classes = []
def delete(self, request, id):
# get a pokemon from our database
pokemon = self.get_a_pokemon(id)
# delete instance and database entry
pokemon.delete()
# return the name of the pokemon deleted
return Response(status=HTTP_204_NO_CONTENT)
Finally we can test it by sending a DELETE request to
http://127.0.0.1:8000/api/v1/pokemon/geodude/. This will cause Geodude to be deleted from out database and this should reflect on our user interface.
Testing API Endpoints
We have successfully created our MVC's and given them CRUD capabilities to allow users to interact with our data. Although this works on our local machine we need to create tests for this functionality to help us identify bugs or issues that we can raise in the development cycle.
# tests/test_views.py
def test_004_create_a_pokemon(self):
# First lets send a post request with the corresponding data
response = self.client.post(reverse('all_pokemon'), data={
"name":"Geodude",
"level": 22,
"description": "Geodude is a rock type pokemon that will eventually evolve into graveler",
"captured": True
}, content_type="application/json")
with self.subTest():
# The date encountered is default to .now() so
# we can't create an answer for this code instead
# we can ensure the request was successful
self.assertEquals(response.status_code, 201)
# We know the request was successful so now lets grab the pokemon
# we created and ensure it exists within the database
response = self.client.get(reverse('a_pokemon', args=['geodude']))
self.assertTrue('Geodude' == response.data['name'])
def test_005_deleting_a_pokemon(self):
# after every test the Database resets back to only having fixture data
# we can call test_007 where the test creates Geodude and then
# delete it
self.test_004_create_a_pokemon()
response = self.client.delete(reverse('a_pokemon', args=['geodude']))
self.assertEquals(response.status_code, 204)