📜  Django REST API – 带有 DRF 的 CRUD

📅  最后修改于: 2022-05-13 01:54:20.768000             🧑  作者: Mango

Django REST API – 带有 DRF 的 CRUD

Django REST Framework 用于非常轻松高效地创建 Web API。这是 Django 框架的一个包装器。在通过 REST 框架创建 API 之前有三个阶段,将模型的数据转换为 JSON/XML 格式(序列化),将此数据渲染到视图,创建用于映射到视图集的 URL。

在本教程中,我们将讨论使用 Django REST API 的 CRUD 操作。它假设您熟悉 Django 基础知识 – Django 教程。

我们要建造什么?

在本教程中,我们将为超市应用程序构建简单的 REST API。这家商店包含各种食品、饮料和家居用品,分为不同的类别。这些类别有子类别,子类别下有项目。每个项目都有一个可以出售的价格。现在我们应该能够使用 DRF API 从我们的数据库中添加、更新、查看和删除此类记录。

假设您在系统中设置并安装了 Django。如果您根本没有任何设置,请参阅以下文章 -

  • Django 介绍与安装
  • 如何在 Django 中使用 MVT 创建基本项目?
  • 如何在 Django 中创建应用程序?

如何安装 Django REST 框架?

要在 Windows、Linux 或任何操作系统上安装 Django REST Framework,需要 pip 包。要检查如何在您的操作系统上安装 pip,请查看 – PIP 安装 – Windows || Linux。

现在,运行一个简单的命令,

pip install djangorestframework

安装 Django REST 框架

安装 REST 框架后,转到 settings.py,并在 INSTALLED_APPS 的底部添加“ rest_framework ”。

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


Python3
INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'rest_framework',
    'api.apps.ApiConfig',
  
]


Python3
from django.contrib import admin
from django.urls import path, include
  
urlpatterns = [
    path('admin/', admin.site.urls),
    path('api/', include('api.urls')),
]


Python3
from django.urls import path
  
urlpatterns = [
      
]


Python3
from django.db import models
  
class Item(models.Model):
    category = models.CharField(max_length=255)
    subcatgeory = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    amount = models.PositiveIntegerField()
  
    def __str__(self) -> str:
        return self.name


Python3
from django.db.models import fields
from rest_framework import serializers
from .models import Item
  
class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('category', 'subcatgeory', 'name', 'amount')


Python3
from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Item
from .serializers import ItemSerializer
  
@api_view(['GET'])
def ApiOverview(request):
    api_urls = {
        'all_items': '/',
        'Search by Category': '/?category=category_name',
        'Search by Subcategory': '/?subcategory=category_name',
        'Add': '/create',
        'Update': '/update/pk',
        'Delete': '/item/pk/delete'
    }
  
    return Response(api_urls)


Python3
from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home')
]


Python3
from rest_framework import serializers
from rest_framework import status
  
@api_view(['POST'])
def add_items(request):
    item = ItemSerializer(data=request.data)
  
    # validating for already existing data
    if Item.objects.filter(**request.data).exists():
        raise serializers.ValidationError('This data already exists')
  
    if item.is_valid():
        item.save()
        return Response(item.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)


Python3
from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
]


Python3
@api_view(['GET'])
def view_items(request):
    
    # checking for the parameters from the URL
    if request.query_params:
        items = Item.objects.filter(**request.query_param.dict())
    else:
        items = Item.objects.all()
  
    # if there is something in items else raise error
    if items:
        data = ItemSerializer(items)
        return Response(data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)


Python3
from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
  
]


Python3
@api_view(['POST'])
def update_items(request, pk):
    item = Item.objects.get(pk=pk)
    data = ItemSerializer(instance=item, data=request.data)
  
    if data.is_valid():
        data.save()
        return Response(data.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)


Python3
from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update//', views.update_items, name='update-items'),
  
]


Python3
@api_view(['DELETE'])
def delete_items(request, pk):
    item = get_object_or_404(Item, pk=pk)
    item.delete()
    return Response(status=status.HTTP_202_ACCEPTED)


Python3
from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update//', views.update_items, name='update-items'),
    path('item//delete/', views.delete_items, name='delete-items'),
      
]


有关更多信息,请参阅我们的文章 Django REST 框架安装。

创建应用

安装 DRF 并将其添加到 settings.py 后,让我们使用以下命令创建一个应用程序 -

python manage.py startapp api

现在已经注册了一个名为 api 的文件夹。

django api 创建应用程序文件夹

让我们将此应用程序添加到 INSTALLED_APPS 和 urls.py 中。

在settings.py中,

Python3

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

现在,在 urls.py 中添加 api url。在GFG_REST.urls.py 中,

Python3

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

现在让我们在我们的 api 文件夹中创建 urls.py -

在 api/urls.py

Python3

from django.urls import path
  
urlpatterns = [
      
]

创建模型

现在让我们创建我们的模型。我们将创建一个项目模型。 API 将使用此模型来执行 CRUD 操作。

Python3

from django.db import models
  
class Item(models.Model):
    category = models.CharField(max_length=255)
    subcatgeory = models.CharField(max_length=255)
    name = models.CharField(max_length=255)
    amount = models.PositiveIntegerField()
  
    def __str__(self) -> str:
        return self.name

现在,在我们的应用程序准备好之后,让我们为 Item 类创建序列化程序。

序列化

Django REST Framework 中的序列化器将对象转换为 javascript 和前端框架可以理解的数据类型。序列化器还提供反序列化,允许在首先验证传入数据后将解析的数据转换回复杂类型。最常用的两个主要序列化器是 ModelSerializer 和 HyperLinkedModelSerialzer。

对于本教程,我们将使用 ModelSerializer。如果您想了解有关手动创建序列化程序的更多信息,请参阅以下文章 -

  • 序列化器——Django REST 框架
  • 序列化程序中的 HyperlinkedModelSerializer – Django REST 框架

模型序列化器

ModelSerializer 是默认序列化器的抽象层,允许快速为 Django 中的模型创建序列化器。它提供了一个快捷方式,让您可以自动创建一个带有对应于模型字段的字段的序列化程序类。 ModelSerializer 类与常规 Serializer 类相同,除了:

  • 它将根据模型自动为您生成一组字段。
  • 它将自动为序列化程序生成验证器,例如 unique_together 验证器。
  • 它包括 .create() 和 .update() 的简单默认实现。

现在让我们在 api 文件夹中创建我们的 serlializers.py 文件并添加以下代码 -

Python3

from django.db.models import fields
from rest_framework import serializers
from .models import Item
  
class ItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = Item
        fields = ('category', 'subcatgeory', 'name', 'amount')

创建视图

要将数据呈现到前端并处理来自用户的请求,我们需要创建一个视图。在 Django REST Framework 中,我们调用这些视图集,所以让我们在 apis/views.py 中创建一个视图,

Python3

from rest_framework.decorators import api_view
from rest_framework.response import Response
from .models import Item
from .serializers import ItemSerializer
  
@api_view(['GET'])
def ApiOverview(request):
    api_urls = {
        'all_items': '/',
        'Search by Category': '/?category=category_name',
        'Search by Subcategory': '/?subcategory=category_name',
        'Add': '/create',
        'Update': '/update/pk',
        'Delete': '/item/pk/delete'
    }
  
    return Response(api_urls)

在上面的代码中, api_view 装饰器获取一个视图应该响应的 HTTP 方法列表。其他方法将响应Method Not Allowed。

现在让我们更新我们的 api/urls.py 文件——

Python3

from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home')
]

现在让我们取消我们的服务器。运行以下命令 -

python manage.py makemigrations
python manage.py migrate
python manage.py runserver

现在前往 http://127.0.0.1:8000/api/

django rest api 视图

现在让我们通过我们的 API 来实现我们的 CRUD 操作。

Django Rest 框架 – 创建视图

现在我们的创建视图将使用 POST 方法将数据插入到我们的数据库中。让我们在 views.py 文件中创建我们的 add_items函数。

Python3

from rest_framework import serializers
from rest_framework import status
  
@api_view(['POST'])
def add_items(request):
    item = ItemSerializer(data=request.data)
  
    # validating for already existing data
    if Item.objects.filter(**request.data).exists():
        raise serializers.ValidationError('This data already exists')
  
    if item.is_valid():
        item.save()
        return Response(item.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

现在让我们更新我们的 urls.py 文件并为我们刚刚创建的创建视图函数添加端点。

Python3

from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
]

访问http://127.0.0.1:8000/api/create/

Django Rest 框架 - 创建视图

Django Rest 框架 – 列表视图

现在我们的列表视图将使用 GET 方法从我们的数据库中检索数据。让我们在 views.py 文件中创建我们的 view_items函数。这个 view_items函数将显示用户根据类别、子类别或名称查询的所有数据或过滤数据。

在views.py

Python3

@api_view(['GET'])
def view_items(request):
    
    # checking for the parameters from the URL
    if request.query_params:
        items = Item.objects.filter(**request.query_param.dict())
    else:
        items = Item.objects.all()
  
    # if there is something in items else raise error
    if items:
        data = ItemSerializer(items)
        return Response(data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

在 urls.py

Python3

from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
  
]

现在访问 http://127.0.0.1:8000/api/all/

Django Rest 框架 - 列表视图

此视图函数还允许我们按类别或子类别进行过滤。您可以使用以下任一 URL 即 http://127.0.0.1:8000/api/?category=category_name 或 http://127.0.0.1:8000/api/?subcategory=category_name 分别过滤类别和子类别.您还可以使用 http://127.0.0.1:8000/api/all/?name=item_name 搜索特定项目。

如果我们访问 http://127.0.0.1:8000/api/all/?category=food 我们的搜索结果将缩小到 -

Django Rest Framework - 列表视图过滤器搜索结果

Django Rest 框架 – 更新视图

现在对于我们的更新视图函数,我们将使用 POST 方法。让我们在 views.py 文件中创建我们的 update_items函数。此视图函数将更新数据库中的特定项目。它将在主键的帮助下过滤项目。

在views.py

Python3

@api_view(['POST'])
def update_items(request, pk):
    item = Item.objects.get(pk=pk)
    data = ItemSerializer(instance=item, data=request.data)
  
    if data.is_valid():
        data.save()
        return Response(data.data)
    else:
        return Response(status=status.HTTP_404_NOT_FOUND)

在 urls.py

Python3

from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update//', views.update_items, name='update-items'),
  
]

现在前往 http://127.0.0.1:8000/api/all/?name=potato

Django rest框架更新视图

Django Rest Framework – 删除视图

对于我们的删除视图函数,我们将使用 DELETE 方法。让我们在 views.py 文件中创建我们的 delete_items函数。此视图函数将从数据库中删除特定项目。

在views.py

Python3

@api_view(['DELETE'])
def delete_items(request, pk):
    item = get_object_or_404(Item, pk=pk)
    item.delete()
    return Response(status=status.HTTP_202_ACCEPTED)

在 urls.py

Python3

from django.urls import path
from . import views
  
urlpatterns = [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update//', views.update_items, name='update-items'),
    path('item//delete/', views.delete_items, name='delete-items'),
      
]

现在访问 http://127.0.0.1:8000/api/item/pk/delete/。请参阅下面的 GIF 以获得更好的理解。

Django Rest Framework - 删除视图