Movatterモバイル変換


[0]ホーム

URL:


How to Build a News Site API with Django Rest Framework in Python

Learn how to create a news site API from scratch using the Django and Django Rest Framework libraries in Python.
  · 13 min read · Updated feb 2023 ·Web Programming

Struggling with multiple programming languages? No worries. OurCode Converter has got you covered. Give it a go!

In this tutorial, we will create an internal news app consisting of journalists writing articles. Creating an internal news site with an API allows organizations to share news content and internal communication more effectively, improving collaboration and knowledge sharing among employees.

What is an API

An API stands for Application Programming Interface. It is a software that allows two applications to talk to each other. Think of how when you initiate a withdrawal in PayPal for example, PayPal API will send your data to the bank for verification first. If the data is correct, then it initiates your withdrawal.

Getting started

We will create a new directory. In the terminal:

$ mkdir news_app$ cd news_app

We have created a new directory to store our app. We will call itnews_app. We have then changed the directory tonews_app.

Let's make and activate our virtual environment:

$ python -m venv venv
# on Linux/macOS$ source venv/bin/activate# on Windows$ \venv\Scripts\activate

Now that we have a virtual environment, we can install Django by using thepip installer:

$ pip install django

We will then create a Django project.

Starting a Django Project

A Django project is a Python package that represents the entire web application. A Django project essentially contains the configuration and settings for the entire website. A single project may also contain multiple apps that can be used to implement functionality.

We will use thedjango-admin executable that comes with Django to start a Django project.

We have called our projectnews_project:

$ django-admin startproject news_project

The project structure is as follows:

.├── manage.py└── news_project   ├── asgi.py   ├── __init__.py   ├── settings.py   ├── urls.py   └── wsgi.py

A Django project can contain several Django apps. Anapp is a small library representing a larger project subset. We will create a new app,news_app:

$ python manage.py startapp news_app

The app structure is:

├── db.sqlite3├── manage.py├── news_project└── news_app   ├── admin.py   ├── apps.py   ├── __init__.py   ├── migrations   │   └── __init__.py   ├── models.py   ├── tests.py   └── views.py

Running Migrations

Migrations are Django's way of propagating model changes (adding a field, deleting a model, etc.) into your database schema. First, navigate to the project's directory. Make sure it contains amanage.py file.

Themakemigrations command examines all of your available models and generates migrations for any tables that do not yet exist. Themigrate command runs all unapplied migrations against your database, essentially synchronizing the changes you made to your models with the database schema. To run migrations:

$ cd news_project

$ python manage.py makemigrations$ python manage.py migrate

We will then run the server:

The server is live:

Configuring the App

We will then include our app in theINSTALLED_APPS list insettings.py:

INSTALLED_APPS = [   'django.contrib.admin',   'django.contrib.auth',   'django.contrib.contenttypes',   'django.contrib.sessions',   'django.contrib.messages',   'django.contrib.staticfiles',   'news_app' #new app   ]

We will then create models inmodels.py:

from django.db import modelsclass Journalist(models.Model):   first_name = models.CharField(max_length=60)   last_name = models.CharField(max_length=60)   def __str__(self):       return f"{ self.first_name } - { self.last_name }"class Article(models.Model):   author = models.ForeignKey(Journalist,                           on_delete=models.CASCADE,                           related_name='articles')   title = models.CharField(max_length=120)   description = models.CharField(max_length=200)   body = models.TextField()   location = models.CharField(max_length=120)   publication_date = models.DateField()   def __str__(self):       return f"{ self.author } - { self.title }"

We will need to register the models inadmin.py, so that we can access the admin panel:

from django.contrib import adminfrom .models import *admin.site.register(Article)admin.site.register(Journalist)

We will then run migrations:

$ python manage.py makemigrations$ python manage.py migrate

Let's create a superuser to access the admin page:

$ python manage.py createsuperuser

To access the admin panel, we enterhttp://127.0.0.1:8000/admin in the browser. After logging in, we can add the data for articles and journalists:

Let's install the Django Rest Framework:

$ pip install djangorestframework

We will then include it in theINSTALLED_APPS list insettings.py.We will need to create endpoints. The first endpoint will enable us to view all the journalists.Inviews.py:

from rest_framework.response import Responsefrom rest_framework.views import APIViewfrom .models import *class JournalistView(APIView):   def get (self, request):       journalists = Journalist.objects.all()       return Response({"journalists":journalists})

We will then need to link it with its URL. In thenews_app folder, create a new file, and name iturls.py:

from django.urls import pathfrom .views import JournalistViewapp_name="news_app"urlpatterns=[   path('journalist/', JournalistView.as_view() ),]

The originalurls.py file needs to know that this file exists.

Innews_project/urls.py:

from django.contrib import adminfrom django.urls import path,includeurlpatterns = [   path('admin/', admin.site.urls),   path('api/',include('news_app.urls')),]

When we runhttp://127.0.0.1:8000/api/journalist/ in the browser, however, we get an error:

This is because we did not provide a class to serialize theJournalist object. That is where serializers come in.

Serializers in the Django REST Framework are in charge of converting objects into data types that Javascript and front-end frameworks can understand. Deserialization is also provided by serializers, which allows parsed data to be converted back into complex types after validating the incoming data.

We will create a new file inside theapps folder, calledserializes.py:

from rest_framework import serializersclass JournalistSerializer(serializers.Serializer):   first_name = serializers.CharField(max_length=60)   last_name = serializers.CharField(max_length=60)   bio = serializers.CharField()

The next thing will be to insert the serializers into our views:

from django.shortcuts import renderfrom rest_framework.response import Responsefrom rest_framework.views import APIViewfrom .models import *from .serializers import JournalistSerializer# Create your views here.class JournalistView(APIView):   def get (self, request):       journalists = Journalist.objects.all()       serializer = JournalistSerializer(journalists, many=True)       return Response({"journalists":serializer.data})

TheJournalistView class inherits from theAPIViewclass provided by the Django REST Framework.

Theget() method is used to handleGET requests to this view. Inside it, allJournalist objects are retrieved from the database usingJournalist.objects.all().The retrievedJournalist objects are then serialized into JSON format using theJournalistSerializer class.

The serialized data is returned as a response using theResponse class provided by the Django REST Framework.

The returned response will have a JSON object with a key of "journalists", and the value will be an array of serializedJournalist objects, where each object corresponds to an individual journalist. Themany=True argument passed to the serializer indicates that we are serializing multiple objects, rather than a single object.

Run the server again:

We now have the contents of theJournalist model. We have successfully created an endpoint where we can view the Journalists details.

We will use thePostman app to visualize it better:

We will then create another endpoint to view all the articles. We will start with updating theserializers.py file to include the articles serializers:

class ArticleSerializer(serializers.Serializer):   title = serializers.CharField(max_length=120)   description = serializers.CharField(max_length=200)   body = serializers.CharField()   location = serializers.CharField(max_length=120)   publication_date = serializers.DateField()

We will then create its views inviews.py:

from .serializers import JournalistSerializer, ArticleSerializerclass ArticleView(APIView):   def get (self, request):       articles = Article.objects.all()       serializer = ArticleSerializer(articles, many=True)       return Response({"articles":serializer.data})

We will then link it to theurls.py file:

from django.urls import pathfrom .views import JournalistView, ArticleViewapp_name="news_app"urlpatterns=[   path('journalist/', JournalistView.as_view() ),   path('article/', ArticleView.as_view() ),]

Input the URLhttp://127.0.0.1:8000/api/article/ in the Postman:

This allows one to create the authors and journalist data through the admin site. However, not everyone can access the admin site. We will create a new endpoint for users to create new articles usingAPIViews.

APIView is a class provided by DRF used to define class-based views for handling HTTP requests. It is a base class that can be extended to create views that handle different types of requests such asGET,POST,PUT,DELETE, etc.

We will add a new post method within ourArticleView:

This defines a view function that handlesHTTP POST requests. The view function expects a JSON payload with an"article" field that contains the data for the new article to be created:

   def post(self, request):       article = request.data.get('article')       serializer = ArticleSerializer(data=article)       if serializer.is_valid(raise_exception=True):           saved_article = serializer.save()       return Response({"success": "Article '{}' created successfully".format(saved_article.title)})

The view function then creates an instance of theArticleSerializer class and passes the"article" data to it. Theis_valid() method is called on the serializer to validate the data against the serializer's validation rules. If the data is not valid, a validation error is raised and a 400 Bad Request response is returned.

If the data is valid, theserializer.save() method is called to create a newArticle object and save it to the database. The saved article object is returned in the HTTP response along with a success message.

However, we have not mentioned the journalist in our response. We should create anauthor_id and implement a create method so that serializers can create articles when the save method is input.

Inserializers.py:

class ArticleSerializer(serializers.Serializer):   title = serializers.CharField(max_length=120)   description = serializers.CharField(max_length=200)   body = serializers.CharField()   location = serializers.CharField(max_length=120)   publication_date = serializers.DateField()   author_id = serializers.IntegerField()   def create(self, validated_data):       return Article.objects.create(**validated_data)

This would be how to create a new article.

Now that we can create new articles, we should be able to edit them.We will create aPUT request for the article to update the articles' endpoint.

Now we should add anupdate() to our serializer so that the update is done for us.Inserializers.py file:

class ArticleSerializer(serializers.Serializer):   title = serializers.CharField(max_length=120)   description = serializers.CharField(max_length=200)   body = serializers.CharField()   location = serializers.CharField(max_length=120)   publication_date = serializers.DateField()   author_id = serializers.IntegerField()   def create(self, validated_data):       return Article.objects.create(**validated_data)   def update(self, instance, validated_data):       instance.title = validated_data.get('title', instance.title)       instance.description = validated_data.get('description', instance.description)       instance.body = validated_data.get('body', instance.body)       instance.author_id = validated_data.get('author_id', instance.author_id)       instance.location = validated_data.get('location', instance.location)       instance.publication_date = validated_data.get('publication_date', instance.publication_date)       instance.save()       return instance

Theupdate() method takes two arguments:instance, which is the existing article instance to be updated, andvalidated_data, which is a dictionary of the new data to be updated. The method then updates the fields of theinstance with the corresponding values from thevalidated_data dictionary using the get method.

If a new value is not provided for a particular field invalidated_data, the existing value of that field ininstance is used. After updating the fields, theinstance is saved and returned as the response.

We will then write a code for obtaining the update request by the user followed by updating the article.

We will create a new classArticleDetailView and define aput() function:

class ArticleDetailView(APIView):      def put(self, request, pk):       saved_article = get_object_or_404(Article.objects.all(), pk=pk)       serializer = ArticleSerializer(instance=saved_article, data=request.data, partial=True)       if serializer.is_valid(raise_exception=True):           article_saved = serializer.save()       return Response({"success": "Article '{}' updated successfully".format(article_saved.title)})

The view function first retrieves the existing article object from the database usingget_object_or_404(), then creates an instance of theArticleSerializer class to validate and update the object with new data. If the data is valid, the updated object is returned in the HTTP response with a success message.

We will then add a new path to the article URL inurls.py:

from django.urls import pathfrom .views import JournalistView, ArticleView, ArticleDetailViewapp_name="news_app"urlpatterns=[   path('journalist/', JournalistView.as_view() ),   path('article/', ArticleView.as_view() ),   path('article/<int:pk>/', ArticleDetailView.as_view()),]

Suppose we want to update the body of one of the articles, whose primary key is 1. We will input the URLhttp://127.0.0.1:8000/api/article/1/ in Postman. We will input the data we want to update inside the body, then chose thePUT method and hitSEND.

Now that we are able to update, we should be able to delete the articles in case we don't want them anymore.We add adelete() method to theAPIDetailView.Inviews.py:

   def delete(self, request, pk):       # Get object with this pk       article = get_object_or_404(Article.objects.all(), pk=pk)       article.delete()       return Response({"message": "Article with id `{}` has been deleted.".format(pk)},status=204)

This retrieves thearticle object with the specified ID usingget_object_or_404(), deletes it from the database using thedelete() method, and returns a JSON response indicating that the object has been deleted, along with a204 No Content status code.

To delete the fourth article in our app, we will input URLhttp://127.0.0.1:8000/api/article/4/ in Postman, selectDELETE method and hitSEND. We will get a message that our article has been deleted successfully.

Conclusion

In this article, you have learned to successfully create APIs for a simple CRUD application, that's a news site. You should also be able to understand the use of serializers in the Django Rest Framework.

Learn also:How to Make an Accounting App with Django in Python.

Get the complete codehere.

Happy coding ♥

Why juggle between languages when you can convert? Check out ourCode Converter. Try it out today!

View Full Code Explain My Code
Sharing is caring!



Read Also


How to Make an Accounting App with Django in Python
How to Build a Web Assistant Using Django and ChatGPT API in Python
How to Make a Blog using Django in Python

Comment panel

    Got a coding query or need some guidance before you comment? Check out thisPython Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!





    Ethical Hacking with Python EBook - Topic - Top


    Join 50,000+ Python Programmers & Enthusiasts like you!



    Tags


    New Tutorials

    Popular Tutorials


    Ethical Hacking with Python EBook - Topic - Bottom

    CodingFleet - Topic - Bottom






    Claim your Free Chapter!

    Download a Completely Free Ethical hacking with Python from Scratch Chapter.

    See how the book can help you build awesome hacking tools with Python!



    [8]ページ先頭

    ©2009-2025 Movatter.jp