In the previous part we implemented authentication, permissions and the possibility to POST new products for admins. In this new episode we will see how to implement details management, relations between models, nested APIs and a different level of permissions.
Our current API methods allow us to list all the products we have in our catalog and to create a new one (if we have admin permissions), but what if we wanted to delete or update a single one? What if we wanted to get only a specific product? We need to handle details.
That's it! With just three lines of code we have now implemented the same feature of the previous class, plus we have set the correct permissions.
Note: in ReviewSerializer when we serialise the user contained in created_by field, return the username instead of the id (to make it more human readable). Another important thing to notice is that the value of the related_name we have set in the Review model must match with the field name we have added in ProductSerializer fields property. In this case we have set it to reviews.
...
What are we doing here? You may have noticed that we set a new property called lookup_url_kwarg. That property is being used to determine the keyword in urls.py to be used for the primary key lookup.
In this third part of the tutorial you learned how to handle model details in the API and how relations between different model work. In the next part of the tutorial we will do something we should have done since the beginning: adding tests to our code and learn how to properly test the API.
If you enjoyed this tutorial, please leave me some feedback! I really want to improve my work, based on the users feedback so any little advice will be appreciated, thanks!
If we try to use the API again (from the browser of from the http client), it will still work in the same way. The difference here is that we are using the very basic APIView class and we have explicitly defined the GET method for it.
We just POSTed some data on the API! How can it work? Well, we have changed the base class from ListAPIView to ListCreateAPIView. This particular class implements a generic POST method that will accept and validate all the fields through the specified serializer.
Now our API let us add products to the catalog, amazing! But... is it exactly what we want? In a real scenario we don't want any random user to be able to add products in our database, so we are going to protect the POST method allowing only Admin users.
...
We will need to pass this token in every API call we want to be authenticated. The token is being passed through the "Authentication" header parameter.
Authentication is something that identify the user with a particular system. Permissions instead are the level of things that are allowed or not allowed for a particular user. In our case we said we want to let Admin users to be able to POST new products and we want to let even anonymous users to GET the product list.
Django Rest Framework has some built-in classes that we can apply to our views to define the level of permissions. We could have used the IsAdminUser class, but it would not allow anonymous users to perform the GET request. Or we could have used IsAuthenticatedOrReadOnly class, but this would allow any registered user to add products (and we want to let only admins).
...
We have now implemented the POST method to add new products to our catalog. In the next episode we will see how to implement endpoints to get a single product, to update or delete products and finally we will allow registered users to send a review for a specific product.
I know, this blog doesn't have any "comment" feature (I was tired of dealing with spam), but if you want to provide some feedback you can still do it by email. Just visit my About page, you will find my email there.
For this tutorial I will assume you have correctly installed at least Python (I will use Python 2.7.x), virtualenv and virtualenvwrapper on your system and I will explain how to create everything else step by step.
django-admin.py startproject drftutorial .
In this case we are using a ModelSerializer. We need to create a new class from it, and specify the model attribute, that's it. In this case we also specify the fields we want to return.
An HttpResponse that renders its content into JSON.
An API that doesn't return any data is not very useful, right? Also, at the moment we haven't implemented yet any feature that let us insert any data. That's why I've created a data migration for you that will insert some data for you. You may notice that the example data contains some Italian products... out of the scope of this tutorial, I strongly advise you to google this products and if you ever happen to visit Italy, try them. You won't regret!
One more thing...
That's very nice, isn't it? You can have browsable APIs at no cost.
Some parts of this tutorial and a few examples have been taken directly from the original Django Rest Framework tutorial.
14 # You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/.
71         # the instance method will create a new one without loading the config.
72         # i.e: if we are in an embed instance we do not want to load the config.
MultipleInstanceError: Multiple incompatible subclass instances of TerminalIPythonApp are being created.
