ReactJS 和 django-forms

Posted

技术标签:

【中文标题】ReactJS 和 django-forms【英文标题】:ReactJS & django-forms 【发布时间】:2017-02-19 17:46:06 【问题描述】:

我在 django 后端有一个带有验证器、选择字段等的模型表单。我想通过它来做出反应并显示它。首先,这可能吗?我想用验证器完整地得到它,但只是 html 仍然很棒。原因是:

    避免正面和背面的双重常量声明。例如选择选项:“男”、“女”、“???”需要在后端进行验证,在前端进行显示和验证。 再次在前端为表单构建整个 html,尽管所有这些都可以通过 django 轻松创建。主要关注再次选择具有许多不同自定义值的选项。

有一个名为 drf-braces 的包有一个 FormSerializer,但它似乎有问题,我经常收到 500 错误“不是 JSON 可序列化错误”,例如:

name_or_event = CharFormSerializerField(error_messages=u'required':
<django.utils.functional.__proxy__ object>, help_text='', initial=None, 
label='Name', required=True, validators=[]) is not JSON serializable

这是基于 drf-braces 的序列化器,如 drf-braces 表单序列化示例所示:

from drf_braces.serializers.form_serializer import FormSerializer

from myapp.forms import SignupDataForm

class MySerializer(FormSerializer):
    class Meta(object):
        form = SignupDataForm

以及基于rest-authRegisterView的API视图:

from myapp.serializers import MySerializer

class TestView(RegisterView):

    permission_classes = (AllowAny,)
    allowed_methods = ('GET', )
    serializer_class = MySerializer

    def get(self, *args, **kwargs):
        serializer = self.serializer_class()
        return Response('serializer': serializer, status=status.HTTP_200_OK)

如果我在浏览器中打开分配给 TestView 的 url,我可以看到表单字段。但是当从 react 加载 ajax 时,我得到一个 500,上面有“不是 JSON 可序列化错误”。调用是从 React.component 构造函数进行的,如下所示。我并没有说它会正确显示该字段,到目前为止,我大多尝试将响应打印到控制台并查看引发了什么错误,但它并没有那么远:

loadUserDetail() 
    this.serverRequest = $.get("myUrl", function (result) 
      console.log(result);
      this.setState(
        username: result.name_or_event,
        email: result.email
      );
    .bind(this));

任何其他想法如何做到这一点?我的方法完全错误,对吧? :-)

【问题讨论】:

【参考方案1】:

在我看来,将 django 生成的表单和 React 混合起来会一团糟。 一个更简洁的方法是让 React 处理前端并使用 Django 来公开一个 JSON api。 没有办法在服务器端渲染表单然后让 React 从那里“拾取”,除非你也在服务器上使用 Nodejs 和 React(React 支持服务器端渲染)。

您的 Python 代码存在的问题是 DRF 序列化程序应该读取发送到服务器的输入,并序列化您想要作为响应发送的数据。 ModelSerializer 知道如何对 Django 模型进行 json 编码,在您的代码中,您尝试对序列化器对象进行 JSON 编码,这不起作用,因为没有神奇的方法可以将该对象转换为 json。

我知道你不想重复你的表单定义和选项,但是你可以很容易地告诉 React 你需要在表单中使用的选项/选择。通常,您可以通过在模板中呈现一个脚本标签来实现这一点,您可以在模板中将任何初始数据作为 JSON 传递并从 Js 端读取。

class TestView(RegisterView):

    permission_classes = (AllowAny,)
    allowed_methods = ('GET', )


    def get(self, *args, **kwargs):
        initial_data = 'gender_options': [...]  # anything you need to render the form, must be json-serialisable.
        return Response('initial_data': json.dumps(initial_data), status=status.HTTP_200_OK)

然后在你渲染的 Django 模板中(在你实际加载 js 应用文件之前):

<script>var INITIAL_DATA =  initial_data|escapejs ;</script>

小心escapejs,如果您不确定initial_data 仅包含受信任的数据,这可能是一个安全问题。

然后此时您的 js 代码可以全局使用 INITIAL_DATA,因此您可以在此基础上创建 React 组件。

您仍然可以使用 Django 表单定义来执行服务器端验证。

【讨论】:

【参考方案2】:

感谢 Fabio,我现在知道我的方法是如何行不通的 :-) 不确定我是否接受了这个建议,但似乎很有可能。

注意:我有服务器端渲染。

注意2:完整的新手反应和序列化器和django-rest-framework

我最初试图实现的是我的 react jsx 文件的这一部分的解决方案:

import React from 'react';
import Router, Route, Link from 'react-router';

class GenderField extends React.Component 
    render() 
        return (
                <div className="form-group">
                    <label htmlFor="gender">Gender</label>
                    <input type="text" className="form-control" id="gender"
                           placeholder="Gender" ref="gender"/>
                </div>
                )
            


export default GenderField;

render 中包含的所有内容都可以从 django 后端生成,实际上是。为什么又写下来了?真的没有办法使用ajax并从后面获取它吗?我想一遍又一遍地从服务器获取静态内容可能违反反应哲学......

但是,更广泛.. 我正在寻找一种从开发人员的角度来执行此操作的方法,仅在部署之前执行一次:服务器生成 html 并用它填充 jsx 文件并进入生产或类似的东西。就像一个 django 应用程序......这也是不可能的,仍然是错误的思考方式吗?

【讨论】:

查看此 Q/A 以了解有关同一主题的更多信息。 ***.com/questions/42297614/django-forms-with-reactjs/…

以上是关于ReactJS 和 django-forms的主要内容,如果未能解决你的问题,请参考以下文章

ReactJS:通过表单获取和更新数据的惯用方式是啥?

使用 ReactJS 和 Skeleton Css 滚动表格

如何在骨干和angularjs中使用reactJS组件

ReactJS 中的“context”和“localStorage”有啥区别?

ReactJS:处理空间导航(键盘和游戏手柄)[关闭]

Reactjs、父组件、状态和道具