美文网首页
教程:Django REST With Reaction(Dja

教程:Django REST With Reaction(Dja

作者: Mead170810 | 来源:发表于2019-11-04 09:17 被阅读0次

    教程:Django REST With Reaction(Django 2.0和少量测试)

    <header style="box-sizing: border-box; display: block; color: rgb(0, 0, 0); height: 89px;">

    教程:Django REST With Reaction(Django 2.0和少量测试)

    </header>

    一个实用的(固执己见)介绍使用Django REST与Reaction。以Django 2.0为特色!

    [图片上传中...(image-1637b4-1572572590957-2)]

    我做了个报告Django与Django休息和反应的解耦在佛罗伦萨的意大利派康X。下面的幻灯片!

    如今,Web框架并不短缺。

    想要构建一个API吗?这里是:Laravel,Rails,Node.js和Koa 2,凤凰,你可以给它命名。

    但事实是:客户想要原型快速...我该怎么办?

    我选择一个网络框架:

    • 让我少写些代码
    • 让我尽可能快地运送一艘MVP。
    • 为扩展项目提供了坚实的基础。

    相信我,姜戈在发展速度方面是很棒的。但是如何创建一个简单的Django RESTAPI呢?如何用Reaction构造Django项目?

    不用担心,我们会一起发现的!

    Django休息与反应:您将学到什么

    在下面的教程中,您将学习:

    • 如何构建一个简单的Django RESTAPI
    • 如何用Reaction构造Django项目

    我们要建什么?在这个项目中,我们将构建一个用于列出和存储引线的简单API.

    Django休息与反应:需求

    要遵循本教程,您应该拥有:

    • 对…的基本理解Python姜戈.
    • 对…的基本理解JavaScript ES6反应.
    • 在您的系统上安装了较新版本的Node.js

    准备好的?我们开始吧!

    Django REST With Reaction:设置Python虚拟环境和项目

    首先要确保您可以使用虚拟Python环境。您可以在Python 3中使用pipenv、pyenv或venv模块。

    对于这个项目,我想使用一个本机虚拟环境:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">python 3-m venv venvDjango</pre>

    1. python 3-m venv venvDjango

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">python 3-m venv venvDjango</pre>

    创建后,在新文件夹中移动并激活环境:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD VenvDjango/&源bin/激活</pre>

    1. CD VenvDjango/&源bin/激活

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD VenvDjango/&源bin/激活</pre>

    现在让我们通过创建一个新目录来开始这个项目:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir Django-drf反应-快速启动&&cd$_</pre>

    1. mkdir Django-drf反应-快速启动&&cd$_

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir Django-drf反应-快速启动&&cd$_</pre>

    并引入依赖项:通过运行以下命令安装Django和Django REST框架:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PIP安装Django djangorestframework</pre>

    1. PIP安装Django djangorestframework

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PIP安装Django djangorestframework</pre>

    安装结束后,就可以创建一个新的Django项目了:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理启动项目项目</pre>

    1. Django-管理启动项目项目

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理启动项目项目</pre>

    现在我们可以开始构建我们的第一个Django应用程序了:a用于列出和存储引线的简单API.

    Django REST:扩展Django应用程序

    Django项目包括许多应用...理想情况下,每个应用程序都应该做一件事。

    Django应用程序是模块化和可重用的。例如:我可以创建一个引线创建和列出引线的应用程序。

    如果另一个项目需要相同的应用程序,我可以安装引线包管理器,仅此而已。

    我建议你读如何编写可重用的应用程序看着DjangoCon 2008:可重用应用程序了解应用程序的最佳实践。

    要在Django中创建一个新应用程序,可以运行:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp_name</pre>

    1. Django-管理StartApp_name

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp_name</pre>

    要创建领导应用程序,请在项目文件夹中移动:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD项目</pre>

    1. CD项目

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD项目</pre>

    并初始化应用程序:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp领导</pre>

    1. Django-管理StartApp领导

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp领导</pre>

    注意:我假设你在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在运行上面的命令时!您的代码_DIR将类似于VenvDjango。下面是我的完整路径:/home/valentino/VenvDjango/django-drf-react-quickstart/project

    您将看到一个名为引线~/YOUR_CODE_DIR/django-drf-react-quickstart/project/.

    现在让我们告诉Django如何使用这个新应用程序。

    敞开./project/settings.py./project/set ings.pyand将应用程序添加到已安装的应用程序:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 264px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads', # add the leads app
    ]</pre>

    1. 已安装的应用程序=[
    2. ‘django.contrib.admin’,
    3. ‘django.contrib.auth’
    4. “django.contrib.contenttype”,
    5. “django.contrib.session”,
    6. “django.contrib.Messages”,
    7. “django.contrib.staticfiles”,
    8. “引线”,#添加引线应用程序
    9. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 264px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads', # add the leads app
    ]</pre>

    到目前一切尚好!

    在下一节中,我们将添加我们的第一个模型。

    Django REST with Reaction:创建Django模型

    确保你还在/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    随着应用程序的到位,是时候创建我们的第一个模型...一个模型是表示表数据...几乎每个Web框架都有模型的概念。Django也不例外。

    Django模型可能有一个或多个技术领域每个字段都是表中的一列。在继续之前,让我们定义我们对申请。

    首先我们需要一个铅模型.

    既然我在收集线索,我就能想到铅模型由下列领域组成:

    • 一个名字
    • 电子邮件
    • 讯息

    (随意添加额外的字段!)比如电话)。

    别忘了时间戳场也是!默认情况下,Django不添加已创建的_at列.

    井。

    敞开./leads/models.py./Lees/Models.pyand创建铅模型:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from django.db import models

    class Lead(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    message = models.CharField(max_length=300)
    created_at = models.DateTimeField(auto_now_add=True)</pre>

    1. 来自django.db导入模型

    2. 类领导(模型.模型):

    3. 名称=模型.Charfield(max_Length=100)

    4. EmailField()

    5. Message=Models.Charfield(max_Length=300)

    6. CREATED=Models.DateTimeField(AUTO_NOW_ADD=True)

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from django.db import models

    class Lead(models.Model):
    name = models.CharField(max_length=100)
    email = models.EmailField()
    message = models.CharField(max_length=300)
    created_at = models.DateTimeField(auto_now_add=True)</pre>

    关于模型的简短说明:花时间查看Django字段文档.

    在规划模型时,请尝试选择最适当的字段你的用例。

    在模型就位之后,让我们通过运行以下命令创建一个迁移:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">pythonmanagement.py makemigrations领导</pre>

    1. pythonmanagement.py makemigrations领导

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">pythonmanagement.py makemigrations领导</pre>

    最后,使用以下方法迁移数据库:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Python Manage.py迁移</pre>

    1. Python Manage.py迁移

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Python Manage.py迁移</pre>

    太棒了!在下一节中,我们将讨论序列化程序和视图。但首先要注意的是测试.

    Django休息与反应:一种零星的测试

    此时,您可能会想“Valentino,测试应用程序如何?”

    与其用TDD教程来烦你,不如给你一些提示。

    我已经看到了大量Django教程,开始时如下所示:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">class SomeModelModelTest(TestCase):
    def setUp(self):
    SomeModel.objects.create(
    name=fake.name(),
    email=fake.email(),
    phone=fake.phone_number(),
    message=fake.text(),
    source=fake.url()
    )

    def test_save_model(self):
        saved_models = SomeModel.objects.count()
        self.assertEqual(saved_models, 2)</pre>
    
    1. 类SomeModelModelTest(TestCase):

    2. DEF设置(自):

    3. SomeModel.objects.create(

    4. name=fake.name(),

    5. 电子邮件=伪造电子邮件

    6. 电话=fake.phone_number(),

    7. Message=fake.text(),

    8. 来源=fake.url()

    9. )

    10. DEF TEST_SAVE_MODEL(Self):

    11. 已保存的模型=SomeModel.objects.count()

    12. SETATESS(已保存的模型,2)

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">class SomeModelModelTest(TestCase):
    def setUp(self):
    SomeModel.objects.create(
    name=fake.name(),
    email=fake.email(),
    phone=fake.phone_number(),
    message=fake.text(),
    source=fake.url()
    )

    def test_save_model(self):
        saved_models = SomeModel.objects.count()
        self.assertEqual(saved_models, 2)</pre>
    

    别干那事。没有必要测试一个普通的Django模型或Django ORM。

    这里是Django测试的一个很好的起点:

    • 不要测试Django内置代码(模型、视图等)
    • 不要测试Python内置函数。

    概述:不要测试已经测试过的!

    那我该测试什么?你增加了一个定制方法一个Django模型?试试看!

    你有自定义视图?试试看!但是我怎么知道到底要测试什么呢?

    帮你自己一个忙。安装覆盖范围:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PIP安装覆盖率</pre>

    1. PIP安装覆盖率

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PIP安装覆盖率</pre>

    然后,每次在应用程序中添加一些代码时,请使用以下内容运行覆盖率:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖范围运行-Source=‘.’Manage.py检验</pre>

    1. 覆盖范围运行-Source=‘.’Manage.py检验

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖范围运行-Source=‘.’Manage.py检验</pre>

    并编写报告:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖率html</pre>

    1. 覆盖率html

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖率html</pre>

    寻找~/YOUR_CODE_DIR/django-drf-react-quickstart/project/htmlcov/index.html~/YOUR_CODE_DIR/django-drf-react-quickstart/project/htmlcov/index.htmland在浏览器中打开文件。

    你会看到到底要测试什么。

    如果您希望看到命令行上的报告,请运行:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖报告</pre>

    1. 覆盖报告

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">覆盖报告</pre>

    等等,你还在吗?我印象深刻!

    抓紧,在下一节中我们将看一看串行化!

    Django REST With Reaction:Django REST序列化程序

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    什么是序列化?

    什么是Django REST序列化程序?

    串行化是将对象转换为另一种数据格式的行为。

    在转换一个对象之后,我们可以将它保存到一个文件中,或者通过网络发送它。

    为什么需要序列化?

    想想Django模型:它是Python类。如何在浏览器中将Python类呈现为JSON?

    带着Django REST序列化程序!

    序列化程序的工作方式也是相反的:它进行转换。JSON到对象.

    这样你就可以:

    • 通过将Django模型转换为JSON在浏览器中显示Django模型
    • 向API发出带有JSON有效负载的CRUD请求

    概述:aDjango REST序列化程序对于通过API对模型进行操作是强制性的。

    创建一个名为./leads/serializers.py./铅/串行化。LeadSeriizer采用了我们的领先模型和一些领域:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from rest_framework import serializers
    from leads.models import Lead

    class LeadSerializer(serializers.ModelSerializer):
    class Meta:
    model = Lead
    fields = ('id', 'name', 'email', 'message')</pre>

    1. 从REST_Framework导入序列化程序

    2. 从引线.型号进口引线

    3. 类先导序列化器(序列化器.模型序列化程序):

    4. 元类:

    5. 模型=铅

    6. 字段=(‘id’,‘name’,‘email’,‘Message’)

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from rest_framework import serializers
    from leads.models import Lead

    class LeadSerializer(serializers.ModelSerializer):
    class Meta:
    model = Lead
    fields = ('id', 'name', 'email', 'message')</pre>

    如您所见,我们正在子类模型序列化器。

    A 模型串列器在Django休息就像ModelForm.

    当您想要将模型紧密映射到序列化程序时,它是合适的。

    除了显式定义每个字段之外,还可以映射所有模型字段:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from rest_framework import serializers
    from leads.models import Lead

    class LeadSerializer(serializers.ModelSerializer):
    class Meta:
    model = Lead
    fields = 'all'</pre>

    1. 从REST_Framework导入序列化程序

    2. 从引线.型号进口引线

    3. 类先导序列化器(序列化器.模型序列化程序):

    4. 元类:

    5. 模型=铅

    6. 字段=‘_ALL

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from rest_framework import serializers
    from leads.models import Lead

    class LeadSerializer(serializers.ModelSerializer):
    class Meta:
    model = Lead
    fields = 'all'</pre>

    保存并关闭文件。我们离完成申请还有一步。

    在下一节中,我们将看一看意见亚细亚.

    Django REST:设置控件…EHM观点

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    来自其他框架,您可能会发现令人惊讶的是Django没有控制器.

    控制器封装用于处理请求和返回响应的逻辑。在传统的MVC架构中,有模型、视图和控制器。

    MVC框架的示例如下钢轨, 凤凰城, 拉勒维尔.

    Django是MVT框架...也就是说,模型-视图-模板。视图负责请求/响应生命周期。

    Django中有许多类型的视图:功能视图, 基于类的视图,和泛型视图.

    虽然有些开发人员更喜欢函数视图而不是基于类的视图我非常喜欢后者。

    当我选择Django时,这是因为我重视开发速度、枯燥和更少的代码。

    当已经有一组正常的默认设置时,我认为手工编写视图是没有意义的。

    这是我的经验法则:

    使用函数视图只有在自定义泛型视图所花费的时间大于手工编写视图的时间时才会使用函数视图。.

    与平原Django一样,在Django REST框架中有许多编写视图的方法:

    对于本教程的范围,我将使用泛型API视图...目标是编写更少的代码。

    我们的简单应用程序应该:

    • 列出模型集合
    • 在数据库中创建新对象

    通过看看泛型API视图文档我们可以看到有一个列表和创建模型的视图。

    它是ListCreateAPIView.

    ListCreateAPIView接受一个queryset和一个序列化器_类。

    敞开./leads/views.py./Lees/views.pyand创建视图:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from leads.models import Lead
    from leads.serializers import LeadSerializer
    from rest_framework import generics

    class LeadListCreate(generics.ListCreateAPIView):
    queryset = Lead.objects.all()
    serializer_class = LeadSerializer</pre>

    1. 从引线.型号进口引线

    2. 从铅。串行化器导入引导串行化器。

    3. 从REST_Framework导入泛型

    4. 类LeadListCreate(Generics.ListCreateAPIView):

    5. queryset=Lead.objects.all()

    6. 串行化器_class=引导串行化器

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 216px;">from leads.models import Lead
    from leads.serializers import LeadSerializer
    from rest_framework import generics

    class LeadListCreate(generics.ListCreateAPIView):
    queryset = Lead.objects.all()
    serializer_class = LeadSerializer</pre>

    那是。使用3行代码,我们创建了一个处理GET和POST请求的视图。

    现在少了什么?URL映射!换句话说,我们应该将URL映射到视图。

    多么,怎样?转到下一节…

    Django REST With Reaction:设置Rout…EHM网址

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    如果您来自Rails、菲尼克斯或Laravel,您可能会发现Django中没有路由配置是令人惊讶的。

    即使DRF附带了一个资源路由器,将URL映射到视图的最简单方法是URL映射.

    我们的目标是将LeadListCreate连接到空气污染指数/铅/.

    换句话说,我们希望发出GET和POST请求空气污染指数/铅/用于列出和创建模型。

    要配置URL映射,请在./project/urls.py./project/urls.py:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">from django.urls import path, include

    urlpatterns = [
    path('', include('leads.urls')),
    ]</pre>

    1. 从django.urls导入路径,包括

    2. URLPATES=[

    3. PATH(‘,包括(’铅.urls‘),

    4. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">from django.urls import path, include

    urlpatterns = [
    path('', include('leads.urls')),
    ]</pre>

    接下来创建一个名为./leads/urls.py./铅/urls.py.

    在这个文件中,我们将LeadListCreate连接到空气污染指数/铅/:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 192px;">from django.urls import path
    from . import views

    urlpatterns = [
    path('api/lead/', views.LeadListCreate.as_view() ),
    ]</pre>

    1. 从django.urls导入路径

    2. 从。导入视图

    3. URLPATES=[

    4. PATH(‘api/lead/’,views.LeadListCreate.as_view()),

    5. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 192px;">from django.urls import path
    from . import views

    urlpatterns = [
    path('api/lead/', views.LeadListCreate.as_view() ),
    ]</pre>

    最后,让我们启用rest_frameworkREST框架已安装的应用程序.

    敞开./project/settings.py./project/set ings.pyand将应用程序添加到已安装的应用程序:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 288px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads',
    'rest_framework' # enable rest framework
    ]</pre>

    1. 已安装的应用程序=[
    2. ‘django.contrib.admin’,
    3. ‘django.contrib.auth’
    4. “django.contrib.contenttype”,
    5. “django.contrib.session”,
    6. “django.contrib.Messages”,
    7. “django.contrib.staticfiles”,
    8. “线索”
    9. ‘REST_Framework’#启用REST框架
    10. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 288px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads',
    'rest_framework' # enable rest framework
    ]</pre>

    现在,您应该能够对以下内容进行正常检查:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    1. PythonManage.py运行服务器

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    头过http://127.0.0.1:8000/api/lead/你会看到可浏览API

    [图片上传中...(image-168f77-1572572590956-1)]

    <figcaption style="box-sizing: border-box; display: block; color: rgb(0, 0, 0); min-width: 0px; width: 1146.19px; line-height: 24px !important; height: 24px;">Django REST可浏览API</figcaption>

    当你在做的时候,试着通过内置表单创建一些数据。

    在下一节中,我们将学习如何在Django中种子数据库.

    Django REST With Reaction:种子数据库

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    你可以用Django固定装置若要填充数据库,请执行以下操作。

    当您想要在前端提供一些数据的演示时,夹具是非常有用的。

    创建一个名为./leads/fixtures./引线/固定装置。

    然后创建一个名为./leads/fixtures/leads.json使用以下JSON的./Lees/Fixtures/Leads.json:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 576px;">[
    {
    "model": "leads.lead",
    "pk": 1,
    "fields": {
    "name": "Armin",
    "email": "something@gmail.com",
    "message": "I am looking for a Javascript mentor",
    "created_at": "2018-02-14 00:00:00"
    }
    },
    {
    "model": "leads.lead",
    "pk": 2,
    "fields": {
    "name": "Tom",
    "email": "tomsomething@gmail.com",
    "message": "I want to talk about a Python project",
    "created_at": "2018-01-14 00:00:00"
    }
    }
    ]</pre>

    1. [
    2. {
    3. “模型”:“领导,领导”,
    4. “PK”:1,
    5. “字段”:{
    6. “名字”:“阿明”,
    7. “电子邮件”:“Things@gmail.com”,
    8. “信息”:“我在找一位JavaScript导师”,
    9. “Created_at”:“2018-02-14 00:00:00”
    10. }
    11. },
    12. {
    13. “模型”:“领导,领导”,
    14. “PK”:2,
    15. “字段”:{
    16. “名字”:“汤姆”,
    17. “电子邮件”:“tomthing@gmail.com”,
    18. “信息”:“我想谈谈Python项目”,
    19. “Created_at”:“2018-01-14 00:00:00”
    20. }
    21. }
    22. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 576px;">[
    {
    "model": "leads.lead",
    "pk": 1,
    "fields": {
    "name": "Armin",
    "email": "something@gmail.com",
    "message": "I am looking for a Javascript mentor",
    "created_at": "2018-02-14 00:00:00"
    }
    },
    {
    "model": "leads.lead",
    "pk": 2,
    "fields": {
    "name": "Tom",
    "email": "tomsomething@gmail.com",
    "message": "I want to talk about a Python project",
    "created_at": "2018-01-14 00:00:00"
    }
    }
    ]</pre>

    保存并关闭文件,然后用以下内容加载夹具:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">pythonManage.py加载数据引导</pre>

    1. pythonManage.py加载数据引导

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">pythonManage.py加载数据引导</pre>

    就这样!

    在接下来的部分中,我们将实现一个简单的反应正面(终于!)

    Django休息与Reaction:Django和一起反应

    [图片上传中...(image-a20d80-1572572590959-6)]

    许多Python开发人员都很难回答一个简单的问题。如何粘合Django和反应一起?

    反应路由器接管路线?应反应在每个Django模板中挂载一个组件?(如果你想失去理智)。

    我会说“视情况而定”。它取决于你需要多少Javascript...但是多少Javascript是太多了?(我不知道,只是开玩笑!)

    除了笑话使用Reaction设置Django项目的多种方法.

    我看到以下模式(几乎每个Web框架都有这种模式):

    1. 在自己的“前端”Django应用程序中做出反应:加载单个HTML模板,让Reaction管理前端(难度:中等)
    2. Django REST作为一个独立的API+作为一个独立的SPA作出反应(困难:难,它涉及到用于身份验证的JWT)
    3. 混合和匹配:Django模板中的迷你Reaction应用程序(困难:简单)

    以下是我的建议.

    如果你刚开始和Django在一起休息和反应避免备选方案2.

    去争取选项1(在自己的“前端”Django应用程序中做出反应)如果:

    • 你在建造一个应用类网站
    • 这个界面有很多用户交互/ajax。
    • 您可以进行基于会话的身份验证
    • 没有SEO担心
    • 你对反应路由器没意见

    保持更接近Django的反应使有关身份验证和其他内容的推理更容易。

    您可以利用Django内置认证用于注册和登录用户。

    好好利用会话认证不要太担心令牌和JWT。

    去争取选项3(Django模板中的Mini Reaction应用程序)如果:

    • 这个网站不需要太多的Javascript
    • 你必须照顾SEO

    我们将探索方法1在下一节。

    顺便说一句,在某些情况下,对整个前端使用Reaction并不是一种选择。

    在这种情况下,你可以永远毫无负罪感地投入Vue.

    姜戈与反应休戚与共:设置反应与webpack

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前!!

    最受欢迎的地方Django和Reaction提供API端点的Django REST框架.

    带着在自己的应用程序“前台”中做出反应.

    我们已经知道如何创建Django应用程序了,所以让我们再做一次:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp前端</pre>

    1. Django-管理StartApp前端

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">Django-管理StartApp前端</pre>

    您将看到一个名为前端~/YOUR_CODE_DIR/django-drf-react-quickstart/project/~/YOUR_CODE_DIR/django-drf-react-quickstart/project/.

    下面是这个项目现在的样子:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">$ ls -1
    frontend
    leads
    manage.py
    project</pre>

    1. $ls-1
    2. 前端
    3. 引线
    4. manage.py
    5. 工程项目

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">$ ls -1
    frontend
    leads
    manage.py
    project</pre>

    让我们还准备一个目录结构来保存Reaction组件:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir-p./前端/src/组件</pre>

    1. mkdir-p./前端/src/组件

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir-p./前端/src/组件</pre>

    静态文件:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir-p./前端/{静态,模板}/前端</pre>

    1. mkdir-p./前端/{静态,模板}/前端

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">mkdir-p./前端/{静态,模板}/前端</pre>

    接下来我们将进行反应,webpack 4和Babel。

    前进前的快速笔记。

    因为前端是一个独立的应用程序,所以安装webpack和朋友是有意义的。./frontend./前端。

    但是,明确我们的意图并不是个坏主意。

    如果我把package.jsonjson在主目录中?

    每个开发人员都可以看着回购程序说“好的,那里有Reaction和webpack的东西”。

    你认为如何?那,我们做吧。

    假设你在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/~/YOUR_CODE_DIR/django-drf-react-quickstart/project/move到上层目录:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD.。</pre>

    1. CD.。

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD.。</pre>

    并初始化环境:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm init-y</pre>

    1. npm init-y

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm init-y</pre>

    下一步安装webpack和webpack CLI,并:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i webpack webpack-cli--扑救-dev</pre>

    1. npm i webpack webpack-cli--扑救-dev

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i webpack webpack-cli--扑救-dev</pre>

    现在打开package.json并配置脚本:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">"scripts": {
    "dev": "webpack --mode development ./project/frontend/src/index.js --output ./project/frontend/static/frontend/main.js",
    "build": "webpack --mode production ./project/frontend/src/index.js --output ./project/frontend/static/frontend/main.js"
    }</pre>

    1. “剧本”:{
    2. “dev”:“webpack--模式开发。/project/前端/src/index.js--输出。/project/前端/静态/前端/main.js”,
    3. “构建”:“webpack--模式生产./project/前端/src/index.js--输出./project/前端/静态/前端/main.js”
    4. }

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">"scripts": {
    "dev": "webpack --mode development ./project/frontend/src/index.js --output ./project/frontend/static/frontend/main.js",
    "build": "webpack --mode production ./project/frontend/src/index.js --output ./project/frontend/static/frontend/main.js"
    }</pre>

    关闭文件并保存它。

    要了解有关webpack 4的更多信息,请访问webpack 4教程:从0到生产模式

    现在,让我们安装Babel来传输我们的代码:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i@Babel/core Babel-加载器@babel/预设-env@babel/预设--对Babel-插件-转换-类-属性-保存-dev作出反应</pre>

    1. npm i@Babel/core Babel-加载器@babel/预设-env@babel/预设--对Babel-插件-转换-类-属性-保存-dev作出反应

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i@Babel/core Babel-加载器@babel/预设-env@babel/预设--对Babel-插件-转换-类-属性-保存-dev作出反应</pre>

    对于使用es6类静态属性来说,Babel-plugin-Transform-class-属性是必需的。

    拉扯反应和支柱类型:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i反应反应-dom支持类型--保存-dev</pre>

    1. npm i反应反应-dom支持类型--保存-dev

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i反应反应-dom支持类型--保存-dev</pre>

    通过创建名为.babelrc.babelrcin项目文件夹中:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 240px;">{
    "presets": [
    "@babel/preset-env", "@babel/preset-react"
    ],
    "plugins": [
    "transform-class-properties"
    ]
    }</pre>

    1. {
    2. “预置”:[
    3. “@Babel/预设-env”、“@Babel/预设-Reaction”
    4. ],
    5. “插件”:[
    6. “变换类-属性”
    7. ]
    8. }

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 240px;">{
    "presets": [
    "@babel/preset-env", "@babel/preset-react"
    ],
    "plugins": [
    "transform-class-properties"
    ]
    }</pre>

    最后创建一个名为webpack.config.js用于配置Babel加载程序的webPack.config.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">module.exports = {
    module: {
    rules: [
    {
    test: /.js$/,
    exclude: /node_modules/,
    use: {
    loader: "babel-loader"
    }
    }
    ]
    }
    };</pre>

    1. 出口={
    2. 模块:{
    3. 规则:[
    4. {
    5. 测试:/\js$/,
    6. 排除:/节点_模块/,
    7. 用途:{
    8. 装载机:“巴贝尔-装载机”
    9. }
    10. }
    11. ]
    12. }
    13. };

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">module.exports = {
    module: {
    rules: [
    {
    test: /.js$/,
    exclude: /node_modules/,
    use: {
    loader: "babel-loader"
    }
    }
    ]
    }
    };</pre>

    现在我们准备出发了!(欢迎来到2018年的前沿)。

    Django在Reaction中休息:Reaction前端

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前

    让我们看看我们怎样才能把我们的反应放在前面。

    首先,首先创建一个视图./frontend/views.py./前端/views.py:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">from django.shortcuts import render

    def index(request):
    return render(request, 'frontend/index.html')</pre>

    1. 从django.快捷方式导入呈现

    2. DEF索引(请求):

    3. 返回呈现(请求,‘前端/index.html’)

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">from django.shortcuts import render

    def index(request):
    return render(request, 'frontend/index.html')</pre>

    它是返回我们的模板的一个简陋的函数视图。

    然后在./frontend/templates/frontend/index.html./前端/模板/前端/index.html:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 576px;"><!DOCTYPE html>
    <html>

    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
    <title>Django DRF - React : Quickstart - Valentino G. - www.valentinog.com</title>
    </head>

    <body>
    <section class="section">
    <div class="container">
    <div id="app" class="columns"></div>
    </div>
    </section>
    </body>

    {% load static %}
    <script src="{% static "frontend/main.js" %}"></script>

    </html></pre>

    1. <!DOCTYPE html>

    2. <html>

    3. <head>

    4. <meta charset="utf-8">

    5. <meta name="viewport" content="width=device-width, initial-scale=1">

    6. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">

    7. <title>Django DRF - React : Quickstart - Valentino G. - www.valentinog.com</title>

    8. </head>

    9. <body>

    10. <section class="section">

    11. <div class="container">

    12. <div id="app" class="columns"></div>

    13. </div>

    14. </section>

    15. </body>

    16. {%加载静态%}

    17. <script src="{% static "frontend/main.js" %}"></script>

    18. </html>

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 576px;"><!DOCTYPE html>
    <html>

    <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.6.2/css/bulma.min.css">
    <title>Django DRF - React : Quickstart - Valentino G. - www.valentinog.com</title>
    </head>

    <body>
    <section class="section">
    <div class="container">
    <div id="app" class="columns"></div>
    </div>
    </section>
    </body>

    {% load static %}
    <script src="{% static "frontend/main.js" %}"></script>

    </html></pre>

    如您所见,模板将调用frontend/main.js前台/main.js,这是我们的webpack包。

    Psst!布尔玛是我最喜欢的快速原型CSS框架!

    配置新的URL映射以包含./project/urls.py./project/urls.py:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">urlpatterns = [
    path('', include('leads.urls')),
    path('', include('frontend.urls')),
    ]</pre>

    1. URLPATES=[
    2. PATH(‘,包括(’铅.urls‘),
    3. PATH(‘,包括(’Fronten.urls‘),
    4. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 144px;">urlpatterns = [
    path('', include('leads.urls')),
    path('', include('frontend.urls')),
    ]</pre>

    接下来创建一个名为./frontend/urls.py/前端/urls.py。

    在这个文件中,我们将视图连接到根目录:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 192px;">from django.urls import path
    from . import views

    urlpatterns = [
    path('', views.index ),
    ]</pre>

    1. 从django.urls导入路径

    2. 从。导入视图

    3. URLPATES=[

    4. 路径(‘’,views.index),

    5. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 192px;">from django.urls import path
    from . import views

    urlpatterns = [
    path('', views.index ),
    ]</pre>

    最后启用前端应用程序在……里面./project/settings.py./project/setings.py:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 312px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads',
    'rest_framework',
    'frontend' # enable the frontend app
    ]</pre>

    1. 已安装的应用程序=[
    2. ‘django.contrib.admin’,
    3. ‘django.contrib.auth’
    4. “django.contrib.contenttype”,
    5. “django.contrib.session”,
    6. “django.contrib.Messages”,
    7. “django.contrib.staticfiles”,
    8. “线索”
    9. “REST框架”
    10. “前端”#启用前端应用程序
    11. ]

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 312px;">INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'leads',
    'rest_framework',
    'frontend' # enable the frontend app
    ]</pre>

    在这一点上,您可以尝试使用:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    1. PythonManage.py运行服务器

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    and you will see nothing at http://127.0.0.1:8000/ because there’s one missing piece: 反应.

    为了创建一个简单的Reaction前端,我们将构建3个组件:

    1. APP,“母”组件
    2. DataProvider,用于获取数据的有状态组件(具有呈现支持!)
    3. 表,用于显示数据的无状态组件。

    App组件

    它是连接反应的主要部件<div id="app"> </div><div id="app"> </div>.

    创建一个名为./frontend/src/components/App.js./前端/src/Components/App.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">import React from "react";
    import ReactDOM from "react-dom";
    import DataProvider from "./DataProvider";
    import Table from "./Table";

    const App = () => (
    <DataProvider endpoint="api/lead/"
    render={data => <Table data={data} />} />
    );

    const wrapper = document.getElementById("app");

    wrapper ? ReactDOM.render(<App />, wrapper) : null;</pre>

    1. 进口反应来自“反应”;

    2. 从“Reactive-dom”中导入ReactDOM;

    3. 从“./DataProvider”导入DataProvider;

    4. 从“./Table”进口表;

    5. Const App=()=>(

    6. <DataProvider endpoint="api/lead/"

    7. 呈现={data=><表数据={data}/>}/>

    8. );

    9. Const包装器=document.getElementById(“app”);

    10. 包装纸?ReactDOM.Render(<App/>,包装器):NULL;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 360px;">import React from "react";
    import ReactDOM from "react-dom";
    import DataProvider from "./DataProvider";
    import Table from "./Table";

    const App = () => (
    <DataProvider endpoint="api/lead/"
    render={data => <Table data={data} />} />
    );

    const wrapper = document.getElementById("app");

    wrapper ? ReactDOM.render(<App />, wrapper) : null;</pre>

    DataProvider组件

    一种用于获取数据的有状态组件(以ReactiveProps为特色!)

    创建一个名为./frontend/src/components/DataProvider.js./前端/src/Components/DataProvider.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 840px;">import React, { Component } from "react";
    import PropTypes from "prop-types";

    class DataProvider extends Component {
    static propTypes = {
    endpoint: PropTypes.string.isRequired,
    render: PropTypes.func.isRequired
    };

    state = {
    data: [],
    loaded: false,
    placeholder: "Loading..."
    };

    componentDidMount() {
    fetch(this.props.endpoint)
    .then(response => {
    if (response.status !== 200) {
    return this.setState({ placeholder: "Something went wrong" });
    }
    return response.json();
    })
    .then(data => this.setState({ data: data, loaded: true }));
    }

    render() {
    const { data, loaded, placeholder } = this.state;
    return loaded ? this.props.render(data) : <p>{placeholder}</p>;
    }
    }

    export default DataProvider;</pre>

    1. 从“Reaction”导入Reaction,{Component};

    2. 从“支柱类型”进口PropType;

    3. 类DataProvider扩展组件{

    4. 静态类型={

    5. 端点:PropTypes.string.isRequired,

    6. 呈现:PropTypes.Func.isRequired

    7. };

    8. 州={

    9. 数据:[],

    10. 装:假,

    11. 占位符:“加载.”

    12. };

    13. 组件DidMount(){

    14. 获取(this.pros.终结点)

    15. 然后(回复=>{

    16. 如果(Response.Status!==200){

    17. 返回这个.setState({占位符:“出了问题”});

    18. }

    19. 返回response.json();

    20. })

    21. 然后(data=>this.setState({data:data,load:true}));

    22. }

    23. 渲染(){

    24. Const{数据,已加载,占位符}=this.state;

    25. 上膛了吗?呈现(数据):<p>{占位符}</p>;

    26. }

    27. }

    28. 导出默认DataProvider;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 840px;">import React, { Component } from "react";
    import PropTypes from "prop-types";

    class DataProvider extends Component {
    static propTypes = {
    endpoint: PropTypes.string.isRequired,
    render: PropTypes.func.isRequired
    };

    state = {
    data: [],
    loaded: false,
    placeholder: "Loading..."
    };

    componentDidMount() {
    fetch(this.props.endpoint)
    .then(response => {
    if (response.status !== 200) {
    return this.setState({ placeholder: "Something went wrong" });
    }
    return response.json();
    })
    .then(data => this.setState({ data: data, loaded: true }));
    }

    render() {
    const { data, loaded, placeholder } = this.state;
    return loaded ? this.props.render(data) : <p>{placeholder}</p>;
    }
    }

    export default DataProvider;</pre>

    表组件

    用于在表中显示数据的无状态组件。

    创建一个名为./frontend/src/components/Table.js./前端/src/Components/Table.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 888px;">import React from "react";
    import PropTypes from "prop-types";
    import key from "weak-key";

    const Table = ({ data }) =>
    !data.length ? (
    <p>Nothing to show</p>
    ) : (
    <div className="column">
    <h2 className="subtitle">
    Showing <strong>{data.length} items</strong>
    </h2>
    <table className="table is-striped">
    <thead>
    <tr>
    {Object.entries(data[0]).map(el => <th key={key(el)}>{el[0]}</th>)}
    </tr>
    </thead>
    <tbody>
    {data.map(el => (
    <tr key={el.id}>
    {Object.entries(el).map(el => <td key={key(el)}>{el[1]}</td>)}
    </tr>
    ))}
    </tbody>
    </table>
    </div>
    );

    Table.propTypes = {
    data: PropTypes.array.isRequired
    };

    export default Table;</pre>

    1. 进口反应来自“反应”;

    2. 从“支柱类型”进口PropType;

    3. 从“弱键”导入密钥;

    4. Const Table=({data})=>

    5. !数据长度?

    6. <p>Nothing to show</p>

    7. ) : (

    8. <div className="column">

    9. <h2 className="subtitle">

    10. 显示<强>{data.ength}项</强>

    11. </h2>

    12. <table className="table is-striped">

    13. <thead>

    14. <tr>

    15. {Object.entry(data[0]).map(el=><th key={key(El)}>{el[0]}</th>)}

    16. </tr>

    17. </thead>

    18. <tbody>

    19. {data.map(el=>)

    20. <tr key={el.id}>

    21. {Object.entry(El).map(el=><tdkey={key(El)}>{el[1]}</td>)}

    22. </tr>

    23. ))}

    24. </tbody>

    25. </table>

    26. </div>

    27. );

    28. 表.proTypes={

    29. 资料来源:PropTypes.array.isRequired

    30. };

    31. 出口违约表;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 888px;">import React from "react";
    import PropTypes from "prop-types";
    import key from "weak-key";

    const Table = ({ data }) =>
    !data.length ? (
    <p>Nothing to show</p>
    ) : (
    <div className="column">
    <h2 className="subtitle">
    Showing <strong>{data.length} items</strong>
    </h2>
    <table className="table is-striped">
    <thead>
    <tr>
    {Object.entries(data[0]).map(el => <th key={key(el)}>{el[0]}</th>)}
    </tr>
    </thead>
    <tbody>
    {data.map(el => (
    <tr key={el.id}>
    {Object.entries(el).map(el => <td key={key(el)}>{el[1]}</td>)}
    </tr>
    ))}
    </tbody>
    </table>
    </div>
    );

    Table.propTypes = {
    data: PropTypes.array.isRequired
    };

    export default Table;</pre>

    该组件以二进制方式生成行,因此我们需要依赖外部包来响应键id。

    正如巴托兹使用简写可能不是最优的。

    一个更好的替代反应的简写方法是弱键:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i弱键-保存-dev</pre>

    1. npm i弱键-保存-dev

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i弱键-保存-dev</pre>

    最后创建webpack的切入点./frontend/src/index.js./前端/src/index.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">从“./Components/App”导入应用程序;</pre>

    1. 从“./Components/App”导入应用程序;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">从“./Components/App”导入应用程序;</pre>

    保存并关闭文件。

    在这一点上,我们已经做好了测试的准备。

    webpack:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">NPM运行开发</pre>

    1. NPM运行开发

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">NPM运行开发</pre>

    启动开发服务器:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    1. PythonManage.py运行服务器

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py运行服务器</pre>

    然后走过去http://127.0.0.1:8000/

    如果您看到“出了问题”,请确保迁移并填充数据库:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py迁移&&pythonManage.py加载数据引导</pre>

    1. PythonManage.py迁移&&pythonManage.py加载数据引导

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">PythonManage.py迁移&&pythonManage.py加载数据引导</pre>

    然后重新启动服务器。

    惊喜!

    你终于应该看到你那神奇的反应应用程序ehm…了。桌子!

    [图片上传中...(image-e726de-1572572590958-5)]

    看上去怎么样?

    这相当简单。但它起作用了!

    Django REST:测试前端

    确保你还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前

    A 反应形式创建新的线索是我们项目的下一个自然步骤。

    在这样做的同时,我们将为前端引入一些测试。

    如果您想认真对待测试,请抓取服从试验山羊.

    它会教你很多(用硒)。

    但我不会在这里使用硒:我们的贸易工具是柏树.

    若要安装Cypress,请运行:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i柏树-储蓄-开发</pre>

    1. npm i柏树-储蓄-开发

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">npm i柏树-储蓄-开发</pre>

    等一下你就可以走了。

    现在,在前端应用程序中移动:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD./前端</pre>

    1. CD./前端

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">CD./前端</pre>

    打开柏树:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">./节点_模块/.bin/柏树打开</pre>

    1. ./节点_模块/.bin/柏树打开

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">./节点_模块/.bin/柏树打开</pre>

    这首歌和舞蹈的原因是因为Cypress为自己创建了一个目录。

    实际上,您将看到一个名为cypress在前端应用程序中。

    不过,不要担心,我们将配置一个NPM脚本,以便在正确的文件夹中运行Cypress。

    (你可以暂时阻止柏树)。

    将UI测试保存在前端文件夹中很有意义,但是可以在其他任何地方初始化Cypress。

    在进入下一步之前,将基本url配置为cypress.jsonjson(您可以在前端文件夹中找到该文件):

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 120px;">{
    "baseUrl": "http://127.0.0.1:8000"
    }</pre>

    1. {
    2. "baseUrl": "http://127.0.0.1:8000"
    3. }

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 120px;">{
    "baseUrl": "http://127.0.0.1:8000"
    }</pre>

    当您在那里时,让我们配置两个NPM脚本:

    1. 一个用来冲洗我们的Django数据库
    2. 另一种用于经营柏树的

    敞开package.json并配置脚本:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">"scripts": {
    "flush": "pipenv run python ./project/manage.py flush --no-input",
    "e2e": "cypress open --project ./project/frontend/",
    //...
    },</pre>

    1. “剧本”:{
    2. “刷新”:“pipenv运行python./project/management e.py刷新-无输入”,
    3. “e2e”:“柏树开放--项目。/项目/前端/”,
    4. //...
    5. },

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">"scripts": {
    "flush": "pipenv run python ./project/manage.py flush --no-input",
    "e2e": "cypress open --project ./project/frontend/",
    //...
    },</pre>

    现在让我们为表单编写一个简单的测试。

    我还在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/frontend**

    创建一个名为./cypress/integration/app_spec.js./cypress/Integration/app_spec.js。

    考试应访问我们的网站,找到表格并填写:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 864px;">describe("Django REST framework / React quickstart app", () => {
    const lead = {
    name: "Armin",
    email: "some-email@gmail.com",
    message: "I am looking for a React tutor"
    };

    before(() => {
    cy.exec("npm run dev");
    cy.exec("npm run flush");
    });

    it("should be able to fill a web form", () => {
    cy.visit("/");

    cy
      .get('input[name="name"]')
      .type(lead.name)
      .should("have.value", lead.name);
    
    cy
      .get('input[name="email"]')
      .type(lead.email)
      .should("have.value", lead.email);
    
    cy
      .get('textarea[name="message"]')
      .type(lead.message)
      .should("have.value", lead.message);
    
    cy.get("form").submit();
    

    });
    // more tests here
    });</pre>

    1. 描述(“Django REST框架/反应性快速启动应用程序”),()=>{

    2. Const铅={

    3. 姓名:“Armin”,

    4. 电子邮件:“一些-电子邮件@gmail.com”,

    5. 留言:“我在找一位反应家教。”

    6. };

    7. 前(())=>{

    8. Cy.exec(“NPM Run dev”);

    9. Cy.exec(“NPM运行刷新”);

    10. });

    11. 它(“应该能够填写一个web表单”,()=>{

    12. 访问(“/”);

    13. 赛伊

    14. .Get(‘put[name=“name”]’)

    15. .类型(铅名称)

    16. .应(“有.值”,铅.名称);

    17. 赛伊

    18. .Get(“输入[名称=”电子邮件“]”)

    19. .类型(铅.电子邮件)

    20. .应当(“有价值”,铅.电子邮件);

    21. 赛伊

    22. .Get(‘TextArea[name=“Message”]’)

    23. .类型(铅.讯息)

    24. .应当(“拥有.value”,铅.Message);

    25. ci.get(“表单”).submit();

    26. });

    27. //这里有更多的测试

    28. });

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 864px;">describe("Django REST framework / React quickstart app", () => {
    const lead = {
    name: "Armin",
    email: "some-email@gmail.com",
    message: "I am looking for a React tutor"
    };

    before(() => {
    cy.exec("npm run dev");
    cy.exec("npm run flush");
    });

    it("should be able to fill a web form", () => {
    cy.visit("/");

    cy
      .get('input[name="name"]')
      .type(lead.name)
      .should("have.value", lead.name);
    
    cy
      .get('input[name="email"]')
      .type(lead.email)
      .should("have.value", lead.email);
    
    cy
      .get('textarea[name="message"]')
      .type(lead.message)
      .should("have.value", lead.message);
    
    cy.get("form").submit();
    

    });
    // more tests here
    });</pre>

    现在让我们从另一个终端运行服务器:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 96px;"># Run inside ~/YOUR_CODE_DIR/django-drf-react-quickstart/project/
    pipenv run python manage.py runserver</pre>

    1. 在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/内部运行

    2. 运行python Manage.py runserver

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 96px;"># Run inside ~/YOUR_CODE_DIR/django-drf-react-quickstart/project/
    pipenv run python manage.py runserver</pre>

    启动柏树:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">NPM运行e2e</pre>

    1. NPM运行e2e

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 72px;">NPM运行e2e</pre>

    最后点击app_spec.js在集成测试部分。

    [图片上传中...(image-92c150-1572572590958-4)]

    这个考试会失败因为没有表格!当然,…

    让我们创造一个!

    为什么不用cy.exec启动Django服务器呢?这是一种反模式:不要从Cypress内部启动后端web服务器。

    Django REST with Reaction:构建Reaction表单

    ::确保你在~/YOUR_CODE_DIR/django-drf-react-quickstart/project/在前进之前

    我们应该创建一个表格,使我们的考试通过。

    创建一个名为./frontend/src/components/Form.js./前端/src/Components/Form.js:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 2112px;">import React, { Component } from "react";
    import PropTypes from "prop-types";

    class Form extends Component {
    static propTypes = {
    endpoint: PropTypes.string.isRequired
    };

    state = {
    name: "",
    email: "",
    message: ""
    };

    handleChange = e => {
    this.setState({ [e.target.name]: e.target.value });
    };

    handleSubmit = e => {
    e.preventDefault();
    const { name, email, message } = this.state;
    const lead = { name, email, message };
    const conf = {
    method: "post",
    body: JSON.stringify(lead),
    headers: new Headers({ "Content-Type": "application/json" })
    };
    fetch(this.props.endpoint, conf).then(response => console.log(response));
    };

    render() {
    const { name, email, message } = this.state;
    return (
    <div className="column">
    <form onSubmit={this.handleSubmit}>
    <div className="field">
    <label className="label">Name</label>
    <div className="control">
    <input
    className="input"
    type="text"
    name="name"
    onChange={this.handleChange}
    value={name}
    required
    />
    </div>
    </div>
    <div className="field">
    <label className="label">Email</label>
    <div className="control">
    <input
    className="input"
    type="email"
    name="email"
    onChange={this.handleChange}
    value={email}
    required
    />
    </div>
    </div>
    <div className="field">
    <label className="label">Message</label>
    <div className="control">
    <textarea
    className="textarea"
    type="text"
    name="message"
    onChange={this.handleChange}
    value={message}
    required
    />
    </div>
    </div>
    <div className="control">
    <button type="submit" className="button is-info">
    Send message
    </button>
    </div>
    </form>
    </div>
    );
    }
    }

    export default Form;</pre>

    1. 从“Reaction”导入Reaction,{Component};

    2. 从“支柱类型”进口PropType;

    3. 类表单扩展组件{

    4. 静态类型={

    5. 端点:PropTypes.string.isRequired

    6. };

    7. 州={

    8. 姓名:“”,

    9. 电子邮件:“”,

    10. 电文:“”

    11. };

    12. handleChange=e=>{

    13. this.setState({[e.Target t.name]:e.Target t.value});

    14. };

    15. handleSubmit=e=>{

    16. e.预防措施();

    17. Const{Name,Email,Message}=this.state;

    18. ConstLead={Name,Email,Message};

    19. Const conf={

    20. 方法:“POST”,

    21. 机构:JSON.strgify(牵头),

    22. 标题:新标题({“内容-类型”:“application/json”})

    23. };

    24. 获取(this.pros.终结点,conf).然后(Response=>控制台.log(Response));

    25. };

    26. 渲染(){

    27. Const{Name,Email,Message}=this.state;

    28. 返回(

    29. <div className="column">

    30. <form onSubmit={this.handleSubmit}>

    31. <div className="field">

    32. <label className="label">Name</label>

    33. <div className="control">

    34. <input

    35. className=“输入”

    36. 类型=“文本”

    37. name=“name”

    38. onChange={this.handleChange}

    39. 值={name}

    40. 所需

    41. />

    42. </div>

    43. </div>

    44. <div className="field">

    45. <label className="label">Email</label>

    46. <div className="control">

    47. <input

    48. className=“输入”

    49. 类型=“电子邮件”

    50. 名称=“电子邮件”

    51. onChange={this.handleChange}

    52. 值={电子邮件}

    53. 所需

    54. />

    55. </div>

    56. </div>

    57. <div className="field">

    58. <label className="label">Message</label>

    59. <div className="control">

    60. <textarea

    61. className=“textrea”

    62. 类型=“文本”

    63. name=“Message”

    64. onChange={this.handleChange}

    65. 值={Message}

    66. 所需

    67. />

    68. </div>

    69. </div>

    70. <div className="control">

    71. <button type="submit" className="button is-info">

    72. 发送讯息

    73. </button>

    74. </div>

    75. </form>

    76. </div>

    77. );

    78. }

    79. }

    80. 出口违约表;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 2112px;">import React, { Component } from "react";
    import PropTypes from "prop-types";

    class Form extends Component {
    static propTypes = {
    endpoint: PropTypes.string.isRequired
    };

    state = {
    name: "",
    email: "",
    message: ""
    };

    handleChange = e => {
    this.setState({ [e.target.name]: e.target.value });
    };

    handleSubmit = e => {
    e.preventDefault();
    const { name, email, message } = this.state;
    const lead = { name, email, message };
    const conf = {
    method: "post",
    body: JSON.stringify(lead),
    headers: new Headers({ "Content-Type": "application/json" })
    };
    fetch(this.props.endpoint, conf).then(response => console.log(response));
    };

    render() {
    const { name, email, message } = this.state;
    return (
    <div className="column">
    <form onSubmit={this.handleSubmit}>
    <div className="field">
    <label className="label">Name</label>
    <div className="control">
    <input
    className="input"
    type="text"
    name="name"
    onChange={this.handleChange}
    value={name}
    required
    />
    </div>
    </div>
    <div className="field">
    <label className="label">Email</label>
    <div className="control">
    <input
    className="input"
    type="email"
    name="email"
    onChange={this.handleChange}
    value={email}
    required
    />
    </div>
    </div>
    <div className="field">
    <label className="label">Message</label>
    <div className="control">
    <textarea
    className="textarea"
    type="text"
    name="message"
    onChange={this.handleChange}
    value={message}
    required
    />
    </div>
    </div>
    <div className="control">
    <button type="submit" className="button is-info">
    Send message
    </button>
    </div>
    </form>
    </div>
    );
    }
    }

    export default Form;</pre>

    表单本身并不清晰,但很容易实现重置功能。快动手!

    下一步修改./frontend/src/components/App.js./前端/src/Components/App.jsto包括新组件:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 456px;">import React from "react";
    import ReactDOM from "react-dom";
    import DataProvider from "./DataProvider";
    import Table from "./Table";
    import Form from "./Form";

    const App = () => (
    <React.Fragment>
    <DataProvider endpoint="api/lead/"
    render={data => <Table data={data} />} />
    <Form endpoint="api/lead/" />
    </React.Fragment>
    );

    const wrapper = document.getElementById("app");

    wrapper ? ReactDOM.render(<App />, wrapper) : null;</pre>

    1. 进口反应来自“反应”;

    2. 从“Reactive-dom”中导入ReactDOM;

    3. 从“./DataProvider”导入DataProvider;

    4. 从“./Table”进口表;

    5. 从“./form”进口表格;

    6. Const App=()=>(

    7. <React.Fragment>

    8. <DataProvider endpoint="api/lead/"

    9. 呈现={data=><表数据={data}/>}/>

    10. <Form endpoint="api/lead/" />

    11. </React.Fragment>

    12. );

    13. Const包装器=document.getElementById(“app”);

    14. 包装纸?ReactDOM.Render(<App/>,包装器):NULL;

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 456px;">import React from "react";
    import ReactDOM from "react-dom";
    import DataProvider from "./DataProvider";
    import Table from "./Table";
    import Form from "./Form";

    const App = () => (
    <React.Fragment>
    <DataProvider endpoint="api/lead/"
    render={data => <Table data={data} />} />
    <Form endpoint="api/lead/" />
    </React.Fragment>
    );

    const wrapper = document.getElementById("app");

    wrapper ? ReactDOM.render(<App />, wrapper) : null;</pre>

    在再次运行测试套件之前,让我们再添加一个小检查。

    测试用户是否可以看到表:

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">// insert after the first "it" block in ./cypress/integration/app_spec.js
    it("should be able to see the table", () => {
    cy.visit("/");
    cy.get("tr").contains(${lead.name}${lead.email}${lead.message});
    });</pre>

    1. //插入在./cypress/Integration/app_spec.js中的第一个“it”块之后插入
    2. 它(“应该能够看到表”,()=>{
    3. 访问(“/”);
    4. cy.get(“tr”).contains(${lead.name}${lead.email}${lead.message});
    5. });

    <pre style="box-sizing: border-box; font-family: "Courier 10 Pitch", Courier, monospace; font-size: 0.9375rem; background: rgb(238, 238, 238); line-height: 1.6; margin-bottom: 1.6em; max-width: 100%; overflow: auto; padding: 1.6em; color: rgb(0, 0, 0); height: 168px;">// insert after the first "it" block in ./cypress/integration/app_spec.js
    it("should be able to see the table", () => {
    cy.visit("/");
    cy.get("tr").contains(${lead.name}${lead.email}${lead.message});
    });</pre>

    确保Cypress和服务器仍然处于打开状态,并再次运行测试…

    应该过去!

    [图片上传中...(image-911b91-1572572590957-3)]

    太棒了。难到不是么?

    当然,这个应用程序非常简单,并且基于一个人为的例子。

    但这是一个很好的起点Reaction和Django休息.

    此时,您已经完成了一个简单Django/Reaction项目的Barebone.

    你已经学会了如何:

    • 建立一个简单的Django REST API
    • 用Reaction构造Django项目
    • 连接到Django RESTAPI

    可以通过向项目添加更多的功能(身份验证)来进行实验。

    Django REST:结束

    构建API有大量的框架。

    但是,当客户快速地想要一个原型时,该怎么办呢?

    你挑姜戈.

    为什么?

    姜戈干的...干法等于少码。更少的代码等于更少的bug。

    使用集成的测试工具进行测试是轻而易举的。

    身份验证是对建于Django auth.

    Django:

    • 允许您编写更少的代码。
    • 让您快速发送MVP
    • 为扩展项目提供了坚实的基础。

    最后但并非最不重要的姜戈休息会让你的生活更轻松。

    试试看。

    感谢你的阅读和快乐的编码!

    Django休息与反应:常见的问题

    在下面的评论中,我有一些很好的问题要回答。

    我如何得到我的反应前端联系人表格,以发送电子邮件使用Django?会很感激你的指点。

    当去耦合Django应用程序时,您仍然可以访问Django提供的所有东西,比如模型形式...这意味着您可以在HTML中使用Django模型表单。表单提交将触发新模型的创建:然后使用Django信号创建模型后,您将发送电子邮件。

    因此,如果您在Django模板中提供一个Reaction前端,那么没有什么可以阻止您混合常规HTML和一些Reaction组件。

    如果你想完全使用JavaScript前端处理表单提交这个概念几乎是一样的,但你会要求发邮件用于创建新模型实体的后端。该创建将触发Django信号,再次运行一些发送电子邮件的代码。

    Django依赖于Reaction:资源

    即使不再维护,这里还有一个用于教程=>Django-DRF-Reaction-快速启动

    查看最新版本Django-休息-反应-pycon.

    刚开始和Django和Django休息?确保退房:

    为夏洛特·梅斯的几乎任何东西编写一个api

    Django休息官方医生

    已经精通Django了?检查DjangoCon 2008:可重用应用程序

    姜戈书

    威廉·S·文森特有另一个很好的教程开始与Django休息和反应

    感谢科里·苏为宝贵的反馈

    [图片上传中...(image-891573-1572572590953-0)]

    瓦伦蒂诺·加利亚迪

    嗨!我是瓦伦蒂诺!教育家和顾问,我帮助人们学习编码现场和远程工作坊.寻找JavaScript和Python培训?我们联系吧!

    <footer style="box-sizing: border-box; display: block; color: rgb(0, 0, 0); height: 156px;">类别Python</footer>

    相关文章

      网友评论

          本文标题:教程:Django REST With Reaction(Dja

          本文链接:https://www.haomeiwen.com/subject/qrffbctx.html