{"id":77143,"date":"2019-01-21T08:00:55","date_gmt":"2019-01-21T08:00:55","guid":{"rendered":"https:\/\/fedoramagazine.org\/?p=23093"},"modified":"2019-01-21T08:00:55","modified_gmt":"2019-01-21T08:00:55","slug":"build-a-django-restful-api-on-fedora","status":"publish","type":"post","link":"https:\/\/sickgaming.net\/blog\/2019\/01\/21\/build-a-django-restful-api-on-fedora\/","title":{"rendered":"Build a Django RESTful API on Fedora."},"content":{"rendered":"<p>With the rise of kubernetes and micro-services architecture, being able to quickly write and deploy a RESTful API service is a good skill to have. In this first part of a series of articles, you&#8217;ll learn how to use Fedora to build a RESTful application and deploy it on Openshift. Together, we&#8217;re going to build the back-end for a &#8220;To Do&#8221; application.<\/p>\n<p> <span id=\"more-23093\"><\/span> <\/p>\n<p>The APIs allow you to Create, Read, Update, and Delete (<a href=\"https:\/\/en.wikipedia.org\/wiki\/Create%2C_read%2C_update_and_delete\">CRUD<\/a>) a task. The tasks are stored in a database and we&#8217;re using the Django ORM (Object Relational Mapping) to deal with the database management.<\/p>\n<h3>Django App and Rest Framework setup<\/h3>\n<p>In a new directory, create a Python 3 virtual environment so that you can install dependencies.<\/p>\n<pre class=\"wp-block-preformatted\">$ mkdir todoapp &amp;&amp; cd todoapp<br \/>$ python3 -m venv .venv<br \/>$ source .venv\/bin\/activate<\/pre>\n<p>After activating the virtual environment, install the dependencies.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv)$ pip install djangorestframework django<\/pre>\n<p><a href=\"https:\/\/www.django-rest-framework.org\/\">Django REST Framework<\/a>, or DRF, is a framework that makes it easy to create RESTful CRUD APIs. By default it gives access to useful features like browseable APIs, authentication management, serialization of data, and more.<\/p>\n<h4>Create the Django project and application<\/h4>\n<p>Create the Django project using the django-admin CLI tool provided.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv) $ django-admin startproject todo_app . # Note the trailing '.'<br \/>(.venv) $ tree .<br \/>.<br \/>\u251c\u2500\u2500 manage.py<br \/>\u2514\u2500\u2500 todo_app<br \/>&nbsp;&nbsp;&nbsp; \u251c\u2500\u2500 __init__.py<br \/>&nbsp;&nbsp;&nbsp; \u251c\u2500\u2500 settings.py<br \/>&nbsp;&nbsp;&nbsp; \u251c\u2500\u2500 urls.py<br \/>&nbsp;&nbsp;&nbsp; \u2514\u2500\u2500 wsgi.py<br \/>1 directory, 5 files<\/pre>\n<p>Next, create the application inside the project.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv) $ cd todo_app<br \/>(.venv) $ django-admin startapp todo<br \/>(.venv) $ cd ..<br \/>(.venv) $ tree .<br \/>.<br \/>\u251c\u2500\u2500 manage.py<br \/>\u2514\u2500\u2500 todo_app<br \/> \u251c\u2500\u2500 __init__.py<br \/> \u251c\u2500\u2500 settings.py<br \/> \u251c\u2500\u2500 todo<br \/> \u2502 \u251c\u2500\u2500 admin.py<br \/> \u2502 \u251c\u2500\u2500 apps.py<br \/> \u2502 \u251c\u2500\u2500 __init__.py<br \/> \u2502 \u251c\u2500\u2500 migrations<br \/> \u2502 \u2502 \u2514\u2500\u2500 __init__.py<br \/> \u2502 \u251c\u2500\u2500 models.py<br \/> \u2502 \u251c\u2500\u2500 tests.py<br \/> \u2502 \u2514\u2500\u2500 views.py<br \/> \u251c\u2500\u2500 urls.py<br \/> \u2514\u2500\u2500 wsgi.py<\/pre>\n<p>Now that the basic structure of the project is in place, you can enable the REST framework and the <em>todo<\/em> application. Let&#8217;s add <em>rest_framework<\/em> and <em>todo<\/em> to the list of <em>INSTALL_APPS<\/em> in the project&#8217;s <em>settings.py<\/em>.<\/p>\n<pre class=\"wp-block-preformatted\">todoapp\/todo_app\/settings.py<\/pre>\n<pre class=\"wp-block-preformatted\"># Application definition<br \/><br \/>INSTALLED_APPS = [<br \/> 'django.contrib.admin',<br \/> 'django.contrib.auth',<br \/> 'django.contrib.contenttypes',<br \/> 'django.contrib.sessions',<br \/> 'django.contrib.messages',<br \/> 'django.contrib.staticfiles',<br \/> 'rest_framework',<br \/> 'todo_app.todo',<br \/>]<\/pre>\n<h3>&nbsp;Application Model and Database<\/h3>\n<p>The next step of building our application is to set up the database. By default, Django uses the <span class=\"module__title__link\">SQLite database management system. S<\/span>ince <span class=\"module__title__link\">SQLite works well and is easy to use during development, let&#8217;s keep this default setting. <\/span>The second part of this series will look at how to replace SQLite with <span class=\"module__title__link\">PostgreSQL to run the application in production.<\/span><\/p>\n<h4>The Task Model<\/h4>\n<p>By adding the following code to&nbsp;<em>todo_app\/todo\/models.py<\/em>, you define which properties have a task. The application defines a task with a <em>title,&nbsp;<\/em>a&nbsp;<em>description<\/em> and a <em>status.<\/em> The status of a task can only be one of the three following states: <em>Backlog, Work in Progress<\/em> and <em>Done.<\/em><\/p>\n<pre class=\"wp-block-preformatted\">from django.db import models<br \/><br \/>class Task(models.Model):<br \/> STATES = ((\"todo\", \"Backlog\"), (\"wip\", \"Work in Progress\"), (\"done\", \"Done\"))<br \/> title = models.CharField(max_length=255, blank=False, unique=True)<br \/> description = models.TextField()<br \/> status = models.CharField(max_length=4, choices=STATES, default=\"todo\")<br \/><br \/><\/pre>\n<p>Now create the database migration script that Django uses to update the database with changes.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv) $ PYTHONPATH=. DJANGO_SETTINGS_MODULE=todo_app.settings django-admin makemigrations<\/pre>\n<p>Then you can apply the migration to the database.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv) $ PYTHONPATH=. DJANGO_SETTINGS_MODULE=todo_app.settings django-admin migrate<\/pre>\n<p>This step creates a<em>&nbsp;<\/em>file named <em>db.sqlite3<\/em> in the root directory of the application. This is where SQLite stores the data.<\/p>\n<h3>Access to the data<\/h3>\n<h4>Creating a View<\/h4>\n<p>Now that you can represent and store a task in the database, you need a way to access the data.&nbsp; This is where we start making use of Django REST Framework by using the <em><a href=\"https:\/\/www.django-rest-framework.org\/api-guide\/viewsets\/#modelviewset\">ModelViewSet<\/a>. <\/em>The <em>ModelViewSet<\/em> provides the following actions on a data model: list, retrieve, create, update, partial update, and destroy.<\/p>\n<p>Let&#8217;s add our view to <em>todo_app\/todo\/views.py<\/em>:<\/p>\n<pre class=\"wp-block-preformatted\">from rest_framework import viewsets<br \/><br \/>from todo_app.todo.models import Task<br \/>from todo_app.todo.serializers import TaskSerializer<br \/><br \/><br \/>class TaskViewSet(viewsets.ModelViewSet):<br \/> queryset = Task.objects.all()<br \/> serializer_class = TaskSerializer<\/pre>\n<h4>Creating a Serializer<\/h4>\n<p>As you can see, the <em>TaskViewSet<\/em> is using a <a href=\"https:\/\/www.django-rest-framework.org\/api-guide\/serializers\/\">Serializer<\/a>. In DRF, serializers convert the data modeled in the application models to a native Python datatype. This datatype can be later easily rendered into JSON or XML,<em> <\/em>for example. Serializers are also used to deserialize JSON or other content types into the data structure defined in the model.<\/p>\n<p>Let&#8217;s add our <em>TaskSerializer<\/em> object by creating a new file in the project <em>todo_app\/todo\/serializers.py<\/em>:<\/p>\n<pre class=\"wp-block-preformatted\">from rest_framework.serializers import ModelSerializer<br \/>from todo_app.todo.models import Task<br \/><br \/><br \/>class TaskSerializer(ModelSerializer):<br \/> class Meta:<br \/> model = Task<br \/> fields = \"__all__\"<\/pre>\n<p>We&#8217;re using the generic <em><a href=\"https:\/\/www.django-rest-framework.org\/api-guide\/serializers\/#modelserializer\">ModelSerializer<\/a><\/em> from DRF, to automatically create a serializer with the fields that correspond to our Task model.<\/p>\n<p>Now that we have a data model a view and way to serialize\/deserialize data, we need to map our view actions to URLs. That way we can use HTTP methods to manipulate our data.<\/p>\n<h4>Creating a Router<\/h4>\n<p>Here again we&#8217;re using the power of the Django REST Framework with the <em><a href=\"https:\/\/www.django-rest-framework.org\/api-guide\/routers\/#defaultrouter\">DefaultRouter<\/a><\/em>. The DRF <em>DefaultRouter<\/em> takes care of mapping actions to HTTP Method and URLs. <\/p>\n<p>Before we see a better example of what the <em>DefaultRouter<\/em> does for us, let&#8217;s add a new URL to access the view we have created earlier. Add the following to <em>todo_app\/urls.py<\/em>:<\/p>\n<pre class=\"wp-block-preformatted\">from django.contrib import admin<br \/>from django.conf.urls import url, include<br \/><br \/>from rest_framework.routers import DefaultRouter<br \/><br \/>from todo_app.todo.views import TaskViewSet<br \/><br \/>router = DefaultRouter()<br \/>router.register(r\"todo\", TaskViewSet)<br \/><br \/>urlpatterns = [<br \/> url(r\"admin\/\", admin.site.urls),<br \/> url(r\"^api\/\", include((router.urls, \"todo\"))),<br \/>]<\/pre>\n<p>As you can see, we&#8217;re registering our <em>TaskViewSet<\/em> to the <em>DefaultRouter<\/em>. Then later, we&#8217;re mapping all the router URLs to the <em>\/api<\/em> endpoint. This way, DRF takes care of mapping the URLs and HTTP method to our view actions (list, retrieve, create, update, destroy).<\/p>\n<p>For example, accessing the <em>api\/todo<\/em> endpoint with a GET HTTP request calls the list action of our view. Doing the same but using a POST HTTP request calls the create action.<\/p>\n<p>To get a better grasp of this, let&#8217;s run the application and start using our API.<\/p>\n<h3>Running the application<\/h3>\n<p>We can run the application using the development server provided by Django. This server should only be used during development. We&#8217;ll see in the second part of this tutorial how to use a web server better suited for production.<\/p>\n<pre class=\"wp-block-preformatted\">(.venv)$ PYTHONPATH=. DJANGO_SETTINGS_MODULE=todo_app.settings django-admin runserver<br \/>Django version 2.1.5, using settings 'todo_app.settings'<br \/>Starting development server at http:\/\/127.0.0.1:8000\/<br \/>Quit the server with CONTROL-C.<\/pre>\n<p>Now we can access the application at the following URL: <em>http:\/\/127.0.0.1:8000\/api\/<\/em><\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/01\/build-a-django-restful-api-on-fedora.png\" alt=\"\" class=\"wp-image-24543\" \/><\/figure>\n<p>DRF provides an interface to the view actions, for example listing or creating tasks, using the following URL: <em>http:\/\/127.0.0.1:8000\/api\/todo<\/em><\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/01\/build-a-django-restful-api-on-fedora-1.png\" alt=\"\" class=\"wp-image-24544\" \/><\/figure>\n<p>Or updating\/deleting an existing tasks with this URL: <em>http:\/\/127.0.0.1:8000\/api\/todo\/1<\/em><\/p>\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/www.sickgaming.net\/blog\/wp-content\/uploads\/2019\/01\/build-a-django-restful-api-on-fedora-2.png\" alt=\"\" class=\"wp-image-24545\" \/><\/figure>\n<h3>Conclusion<\/h3>\n<p>In this article you&#8217;ve learned how to create a basic RESTful API using the Django REST Framework. In the second part of this series, we&#8217;ll update this application to use the PostgreSQL database management system, and deploy it in OpenShift.<\/p>\n<p>The source code of the application is available on <a href=\"https:\/\/github.com\/cverna\/django-rest-framework-todo\">GitHub<\/a>. <\/p>\n<p><\/p>\n","protected":false},"excerpt":{"rendered":"<p>With the rise of kubernetes and micro-services architecture, being able to quickly write and deploy a RESTful API service is a good skill to have. In this first part of a series of articles, you&#8217;ll learn how to use Fedora to build a RESTful application and deploy it on Openshift. Together, we&#8217;re going to build [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":77144,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[48],"tags":[45,61,46,47],"class_list":["post-77143","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-fedora-os","tag-fedora","tag-fedora-project-community","tag-magazine","tag-news"],"_links":{"self":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/77143","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/comments?post=77143"}],"version-history":[{"count":0,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/posts\/77143\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media\/77144"}],"wp:attachment":[{"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/media?parent=77143"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/categories?post=77143"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sickgaming.net\/blog\/wp-json\/wp\/v2\/tags?post=77143"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}