Django Rest框架入门
#python #django #djangorestframework
通过cOultostic保留闪光灯:emo yo> om> om> om> om> om> om >> id)

在本文中,我们将创建一个项目,该项目发布有关使用Django和Django Rest框架的咆哮的项目。我们将使用Django的内置slugify方法并覆盖其save()方法,以自动为每个咆哮创建 slug 。我们还将使用称为drf-writable-nested的第三方软件包来处理模型中ManyToManyField的序列化。

我们将首先创建虚拟环境,安装初始软件包,创建Django项目,创建Django应用程序,最后进行初始迁移

python -m venv venv
. venv/bin/activate
python -m pip install django djangorestframework
django-admin startproject myproject
cd myproject
python -m manage startapp rants
python -m manage migrate

我们列出了项目的安装_Apps设置中的rest_framework和我们的rants应用程序,并将它们包含在项目urls.py

# settings.py
INSTALLED_APPS = [
    ...
    'rest_framework',
    'rants',
]

# myproject/urls.py
from django.urls import path, include

urlpatterns = [
    path('', include('rants.urls', namespace='main')),
    path('api-auth/', include('rest_framework.urls', namespace='rest_framework')),
]

接下来,我们在rants应用程序中创建模型:

# models.py
from django.db import models


class Category(models.Model):
    title = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50)

    def __str__(self):
        return self.title


class Rant(models.Model):
    title = models.CharField(max_length=150)
    slug = models.SlugField(max_length=150)
    categories = models.ManyToManyField(
        Category, related_name='rants_categories')

    class Meta:
        verbose_name = "rant"
        verbose_name_plural = 'rants'

    def __str__(self):
        return self.title

我们有一个带有标题的咆哮模型,带有CharField的slug和一个类别属性,该类别属性具有ManyToManyField连接到具有标题和slug属性的类别模型。

然后我们迁移数据库python -m manage makemigrations && python -m manage migrate。接下来,我们为这两个模型创建一个序列化器:

# serializers.py
from rest_framework import serializers
from .models import Rant, Category


class CategorySerializer(serializers.ModelSerializer):
    slug = serializers.SlugField(read_only=True)

    class Meta:
        model = Category
        fields = "__all__"


class RantSerializer(serializers.ModelSerializer):
    categories = CategorySerializer(many=True)
    slug = serializers.SlugField(read_only=True)


    class Meta:
        model = Rant
        fields = ('id', 'title', 'slug', 'categories')
        many = True

最后,我们创建了视图并将其映射到我们的URL,以便我们可以看到应用程序的API端点。

# views.py
from rest_framework.response import Response
from rest_framework.generics import ListCreateAPIView, UpdateAPIView, DestroyAPIView

from .models import Rant
from .serializers import RantSerializer

class RantList(ListCreateAPIView):
    queryset = Rant.objects.all()
    serializer_class = RantSerializer

    def list(self, request):
        queryset = self.get_queryset()
        serializer = RantSerializer(queryset, many=True)
        return Response(serializer.data)


class RantUpdate(UpdateAPIView):
    queryset = Rant.objects.all()
    serializer_class = RantSerializer


class RantDelete(DestroyAPIView):
    queryset = Rant.objects.all()
    serializer_class = RantSerializer

我们将ListCreateAPIView用于读取端点来表示模型实例集合,该集合提供了getpost方法处理程序,UpdateAPIView,用于单个模型实例的更新端点,该实例提供了putpatch Methoder,patch Method Handler,DestroyAPIView单个模型实例的删除端点,该实例提供了delete方法处理程序。让我们将这些视图映射到urls.py

# urls.py
from django.urls import path

from .views import RantList, RantUpdate, RantDelete
from .models import Rant
from .serializers import RantSerializer

app_name = 'rants'


urlpatterns = [
    path('api/rants/', RantList.as_view(queryset=Rant.objects.all(), serializer_class=RantSerializer)),
    path('api/rants/update/<int:pk>/', RantUpdate.as_view(queryset=Rant.objects.all(), serializer_class=RantSerializer)),
    path('api/rants/delete/<int:pk>/', RantDelete.as_view(queryset=Rant.objects.all(), serializer_class=RantSerializer)),
]

现在,我们可以使用DRF软件包在浏览器中查看API端点,但我个人更喜欢使用另一个是drf-yasg软件包的软件包查看API端点。让我们安装和配置软件包:

python -m pip install drf-yasg

# settings.py
INSTALLED_APPS = [
    ....
    'rest_framework',
    'drf_yasg',
]
# urls.py
from django.urls import path, include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi

schema_view = get_schema_view(
   openapi.Info(
      title="Rants API",
      default_version='v1',
      description="Rants",
      terms_of_service="https://www.google.com/policies/terms/",
      contact=openapi.Contact(email="contact@snippets.local"),
      license=openapi.License(name="BSD License"),
   ),
   public=True,
   permission_classes=[permissions.AllowAny],
)
urlpatterns = [path('api/', schema_view.with_ui('swagger', cache_timeout=0), name='schema-swagger-ui'),]

现在我们运行python -m manage runserver,然后前往http://localhost:8000/api/,看看我们创建了什么

Rants API screenshot

但是我们有问题,尽管在该领域输入了str,但类别字段仍有错误。

{
  "categories": [
    "Expected a list of items but got type \"str\"."
  ]
}

要解决此问题,我们将在应用程序中安装drf-nested-writable以序列化类别字段,然后更新serializers.py文件以在我们的RantSerializer中包含WritableNestedModelSerializer

python -m pip install drf-nested-writable

# serializers.py
from drf_writable_nested.serializers import WritableNestedModelSerializer


class RantSerializer(WritableNestedModelSerializer):
    categories = CategorySerializer(many=True)
    slug = serializers.SlugField(read_only=True)

    class Meta:
        model = Rant
        fields = ('id', 'title', 'slug', 'categories')
        many = True

现在,当我们使用rants_create端点为应用程序添加新数据时,我们将不再收到超过的错误,而是。我们还覆盖了slug字段的模型中的save()方法,以自动填充数据库

Rants API

在我们的模型中覆盖save()方法的代码

# models.py
...
from django.utils.text import slugify

...
    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Category, self).save(*args, **kwargs)
        return self.slug

...
    def save(self, *args, **kwargs):
        self.slug = slugify(self.title)
        super(Rant, self).save(*args, **kwargs)
        return self.slug
...

结论:
这花了我一段时间来解决,因为我在GMT+8,但是嘿,至少它已经解决了,我学会了如何覆盖模型中的保存方法,并了解了DRF-wardible-Nest-Nest-Nest-Nest-Nest-Nest-Nest-Nest-Nest-Nest-Nest-nest套件以解决我的问题。