ReactJS 和 django 表单

ReactJS & django-forms

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

  1. 避免前后双重声明常量。例如 select 选项:"male"、"female"、“???”需要在后端进行验证,在前端进行显示和验证。
  2. 再次在前端为表单构建整个 html,尽管所有这些也可以由 django 轻松创建。再次主要关注 select 具有许多不同自定义值的选项。

有一个名为 drf-braces 的包有一个 FormSerializer 但它似乎确实有问题,我经常收到 500 错误 "is not JSON serializable error",如:

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-auth RegisterView:

的 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,我可以看到表单字段。但是当从反应中加载 ajax 时,我得到一个 500,上面有 "is not JSON serializable error"。该调用是从 React.component 构造函数发出的,如下所示。我并不是说它会正确显示该字段,到目前为止,我主要尝试将响应打印到控制台并查看抛出的错误,但它并没有那么远:

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

关于如何做到这一点还有其他想法吗?我的方法完全错了,对吧? :-)

在我看来,混合使用 django 生成的表单和 React 会很麻烦。 一种更简洁的方法是让 React 处理前端并使用 Django 只公开一个 JSON api。 没有办法在服务器端渲染表单然后让 React "pick up" 从那里,除非你在服务器上也使用 Nodejs 和 React(React 支持服务器端渲染)。

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

我知道您不想重复您的表单定义和选项,但您可以轻松地告诉 React 您需要在表单中使用的 options/choices。通常你可以通过在模板中渲染一个脚本标签来实现这一点,你将任何初始数据作为 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 仅包含受信任的数据,这可能是一个安全问题。

然后在这一点上你有 INITIAL_DATA 对你的 js 代码全局可用,所以你可以基于它来构建你的 React 组件。

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

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

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

注 2:完整的 React 新手 & 序列化器 & 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应用程序......那也是不可能的,还是一个错误的思考方式?