Lập trình web Python Django RESTful API Framework
Lập trình Python

Lập trình web Python Django RESTful API Framework

Hướng dẫn lập trình CRUD Restful API với Django Python dễ dàng.

Ứng dụng các công nghệ để lập trình web với python:

  • Python
  • Django REST Framework
  • SQL lite
  • Visual Studio Code
  • Python extension by Microsoft

Tại sao dùng Django REST Framework?

Django REST Framework (REST Framework) cung cấp 4 tính năng:

  1. Browsable API
  2. Auth Support
  3. Throttling: giới hạn quyền truy cập của người dùng.
  4. Serializers: chuyển đổi model thành json object.

Nếu bạn là người bắt đầu với lập trình web python thì đừng bỏ lỡ bài viết:

Django Project Setup

Xem thêm:

Tạo thư mục django-employee và kích hoạt virtualenv:

$ mkdir django-employee 
$ cd django-employee 
$ python -m venv env

Nhấn Ctrl + Shift + P chọn Python: Selection interpreter và chọn bản python bạn muốn dùng. Chi tiết hơn bạn tham khảo bài viết này

Lúc này sẽ xuất hiện (env) ở command line.

django_helloworld (5)

(env)$ pip install django  
(env)$ django-admin startproject myemployee

Cấu trúc dự án lúc này:

└── myemployee
    ├── manage.py
    └── myemployee
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

Cấu hình cho Django REST Framework

Chúng ta sẽ tạo app employee.

(env)$ cd myemployee 
(env)$ python manage.py startapp employee 
(env)$ pip install djangorestframework

Bây giờ chúng ta cấu hình cho Django project dùng REST Framework.

Đầu tiên, bạn thêm employeerest_framework vào mục INSTALLED_APPS trong myemployee/myemployee/settings.py:

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'employee',
    'rest_framework'
]

Tiếp theo, định nghĩa settings cho REST Framework, thêm code bên dưới vào file settings.py :

REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [],
    'TEST_REQUEST_DEFAULT_FORMAT': 'json'
}

Điều này sẽ không giới hạn việc truy cập tới API và thiết lập mặc định trả về JSON cho tất cả các request.

Do mình develop ở localhost nên không cần đòi hỏi giới hạn truy cập. Nhưng nếu ở production thì phải giới hạn việc truy cập tới endpoints. Xem thêm ở đây.

Cấu trúc project hiện tại thế này:

└── myemployee
    ├── manage.py
    ├── employee
    │   ├── __init__.py
    │   ├── admin.py
    │   ├── apps.py
    │   ├── migrations
    │   │   └── __init__.py
    │   ├── models.py
    │   ├── tests.py
    │   └── views.py
    └── myemployee
        ├── __init__.py
        ├── settings.py
        ├── urls.py
        └── wsgi.py

Database mình sẽ dùng mặc định là SQLite của Django đã hỗ trợ nên không cấu hình phần này.

Tiếp theo, chúng ta sẽ định nghĩa model Employee trong file django-employee/myemployee/employee/models.py:

from django.db import models

class Employee(models.Model):
    name = models.CharField(max_length=255)
    age = models.IntegerField()
    created_at = models.DateTimeField(auto_now_add=True)
    updated_at = models.DateTimeField(auto_now=True)

    def get_info(self):
        return 'Name: ' + self.name + ' age: ' + self.age

    def __repr__(self):
        return self.name + ' is added.'

Thực thi  migration cho database:

(env)$ python manage.py makemigrations 
(env)$ python manage.py migrate

Bạn hãy check database db.sqlite3 sẽ thấy thay đổi.

Serializers

Trước khi tạo API, chúng ta sẽ định nghĩa serializer cho model Employee. Hiểu đơn giản serializers là cách chúng ánh xạ các field trong class model (chuyển từ class model sang json và ngược lại).

Thêm code django-employee/myemployee/employee/serializers.py:

from rest_framework import serializers
from .models import Employee


class EmployeeSerializer(serializers.ModelSerializer):
    class Meta:
        model = Employee
        fields = ('name', 'age', 'created_at', 'updated_at')

ModelSerializer sẽ ánh xạ tương ứng các field cho model Employee.

Bây giờ là phần quan trọng, tiến hành làm RESTful API nào !

Cấu trúc restful (xem thêm)

EndpointHTTP MethodCRUD MethodResult
employeesGETREADGet all employee
employees/:idGETREADGet a single employee
employeesPOSTCREATEAdd a single employee
employees/:idPUTUPDATEUpdate a single employee
employees/:idDELETEDELETEDelete a single employee

Trước khi implement API routes chúng ta sẽ định nghĩa skeleton để return empty và map chúng với URL tương thích trong file django-employee/myemployee/employee/views.py:

from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework import status
from .models import Employee
from .serializers import EmployeeSerializer


@api_view(['GET', 'DELETE', 'PUT'])
def get_delete_update_employee(request, pk):
    try:
        employee = Employee.objects.get(pk=pk)
    except Employee.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    # get details of a single employee
    if request.method == 'GET':
        return Response({})
    # delete a single employee
    elif request.method == 'DELETE':
        return Response({})
    # update details of a single employee
    elif request.method == 'PUT':
        return Response({})


@api_view(['GET', 'POST'])
def get_post_employee(request):
    # get all employee
    if request.method == 'GET':
        return Response({})
    # insert a new record for a employee
    elif request.method == 'POST':
        return Response({})

Tạo URLs đúng với views trong file django-employee/myemployee/employee/urls.py:

from django.conf.urls import url
from . import views

urlpatterns = [
    url(
        r'^api/employee/(?P<pk>[0-9]+)$',
        views.get_delete_update_employee,
        name='get_delete_update_employee'
    ),
    url(
        r'^api/employee/$',
        views.get_post_employee,
        name='get_post_employee'
    )
]

Đồng thời update file django-employee/myemployee/myemployee/urls.py:

from django.conf.urls import include, url
from django.contrib import admin

urlpatterns = [
    url(r'^', include('employee.urls')),
    url(
        r'^api-auth/',
        include('rest_framework.urls', namespace='rest_framework')
    ),
    url(r'^admin/', admin.site.urls),
]

Browsable API

Tất cả các route đã map với function, chúng ta sẽ test thử REST Framework’s Browsable API và xem chúng làm việc thế nào nha.

Tại Command line gõ:

(env)$ python manage.py runserver

Truy cập: http://localhost:8000/api/employee

Bạn sẽ thấy giao diện HTML với API response.

pythonrestfull

Bây giờ chúng ta sẽ bổ sung cho đủ các hàm trong file views.

Routes

GET ALL

Update code ở file employee/views.

@api_view(['GET', 'POST'])
def get_post_employee(request):
    # get all employee
    if request.method == 'GET':
        employees = Employee.objects.all()
        serializer = EmployeeSerializer(employees, many=True)
        return Response(serializer.data)
    # insert a new record for a employee
    elif request.method == 'POST':
        return Response({})

POST

Inserting employee cũng có 2 trường hợp: hợp lệ và không hợp lệ.

@api_view(['GET', 'POST'])
def get_post_employee(request):
    # get all employee
    if request.method == 'GET':
        employees = Employee.objects.all()
        serializer = EmployeeSerializer(employees, many=True)
        return Response(serializer.data)
    # insert a new record for a employee
    if request.method == 'POST':
        data = {
            'name': request.data.get('name'),
            'age': int(request.data.get('age'))
        }
        serializer = EmployeeSerializer(data=data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_201_CREATED)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

Tại đây, chúng sẽ chèn dòng mới bởi serializing và xác nhận field hợp lệ trước khi chèn vào database.

Truy cập: http://localhost:8000/api/employee/ và thêm data mẫu bên dưới.

{
    "name": "Lam",
    "age": 4
}

GET Single

Get employee có 2 trường hợp:

  1. Hợp lệ: employee tồn tại
  2. Không hợp lệ: employee không tồn tại
@api_view(['GET', 'UPDATE', 'DELETE'])
def get_delete_update_employee(request, pk):
    try:
        employee = Employee.objects.get(pk=pk)
    except Employee.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    # get details of a single employee
    if request.method == 'GET':
        serializer = EmployeeSerializer(employee)
        return Response(serializer.data)

 

PUT

Method PUT để cập nhật 1 employee

@api_view(['GET', 'DELETE', 'PUT'])
def get_delete_update_employee(request, pk):
    try:
        employee = Employee.objects.get(pk=pk)
    except Employee.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    # get details of a single employee
    if request.method == 'GET':
        serializer = EmployeeSerializer(employee)
        return Response(serializer.data)

    # update details of a single employee
    if request.method == 'PUT':
        serializer = EmployeeSerializer(employee, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # delete a single employee
    elif request.method == 'DELETE':
        return Response({})

DELETE

To delete a single record, an ID is required:

@api_view(['GET', 'DELETE', 'PUT'])
def get_delete_update_employee(request, pk):
    try:
        employee = Employee.objects.get(pk=pk)
    except Employee.DoesNotExist:
        return Response(status=status.HTTP_404_NOT_FOUND)

    # get details of a single employee
    if request.method == 'GET':
        serializer = EmployeeSerializer(employee)
        return Response(serializer.data)

    # update details of a single employee
    if request.method == 'PUT':
        serializer = EmployeeSerializer(employee, data=request.data)
        if serializer.is_valid():
            serializer.save()
            return Response(serializer.data, status=status.HTTP_204_NO_CONTENT)
        return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)

    # delete a single employee
    if request.method == 'DELETE':
        employee.delete()
        return Response(status=status.HTTP_204_NO_CONTENT)

Xong! Bạn có thể thử với các Restful API như mục trên, danh sách employee api click đây.

Mình đã Hướng dẫn lập trình web Python CRUD Restful API với Django Python qua dự án Employee dễ dàng. Các bạn có thắc gì cứ bình luận bên dưới nhé!

Download source code Python web:

Employee project

AboutQLâm Xmaster

Share Everything !

2 Comments

  1. Page not found (404)
    Request Method: GET
    Request URL: http://127.0.0.1:8000/employees
    Using the URLconf defined in myemployee.urls, Django tried these URL patterns, in this order:

    ^ ^api/employee/(?P[0-9]+)$ [name=’get_delete_update_employee’]
    ^ ^api/employee/$ [name=’get_post_employee’]
    ^api-auth/
    admin/
    The current path, employees, didn’t match any of these.

    You’re seeing this error because you have DEBUG = True in your Django settings file. Change that to False, and Django will display a standard 404 page.

    em nhận được lỗi này là sao ạ, mong ad giải thích giúp ạ

Leave a Reply

Your email address will not be published. Required fields are marked *

Nhận bài viết mới nhất qua email của bạn

Get notified when we publish new articles for free! (Fill in email and Confirm verification link)