Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ReactJS & django-forms

I have a modelform in django backend with validators, choicefields and etc. I would like to pass it to react and display it. First of all is that even possible? I would like to get it completly with validators, but just html is still great. The reason for that is:

  1. Avoiding double constant declarations on the front and back. For example select options: "male", "female", "???" would need to be on the backend for validation and frontend for display and validation.
  2. Constructing the whole html on the frontend for the form again, despite that all of it can also be easily created by django. Main concern again select options with many different custom values.

There is a package called drf-braces that has a FormSerializer but it does seem to have a problem, I constantly get a 500 error "is not JSON serializable error", like in:

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

This is the drf-braces based serializer as seen in drf-braces form serialization example:

from drf_braces.serializers.form_serializer import FormSerializer

from myapp.forms import SignupDataForm

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

and the API view based on rest-auth RegisterView:

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)

If I open the url assigned to TestView in browser I can see the form fields. But when loading with ajax from react I get a 500 with "is not JSON serializable error" above. The call is made from React.component constructor like bellow. I don't say it would display the field correctly, so far mostly I tried to print the response in to console and see what error that throws, but it dosn't get that far:

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

Any other ideas how to do this? I am completely wrong with my approach, right? :-)

like image 704
Stefan Avatar asked Oct 11 '16 08:10

Stefan


People also ask

What is ReactJs used for?

The React. js framework is an open-source JavaScript framework and library developed by Facebook. It's used for building interactive user interfaces and web applications quickly and efficiently with significantly less code than you would with vanilla JavaScript.

Is ReactJs coding?

React is a declarative, efficient, and flexible JavaScript library for building user interfaces. It lets you compose complex UIs from small and isolated pieces of code called “components”.

Is React for HTML or JS?

To get an overview of what React is, you can write React code directly in HTML. But in order to use React in production, you need npm and Node.js installed.

Is React better than Python?

If you're looking for a versatile language that is easy to learn, then Python is a great choice. However, if you're looking for a language specifically designed for developing user interfaces, then ReactJs is the better option.


1 Answers

In my opinion mixing the django-generated forms and React is going to be a mess. A much cleaner approach would be to let React handle the frontend side and use Django to just expose a JSON api. There is no way to render the form server side and then let React "pick up" from there, unless you use Nodejs and React on the server too (React supports server side rendering).

The problem you have with your Python code is that DRF serialisers are supposed to read input sent to the server and to serialise data you want to send as a response. The ModelSerializer knows how to json-encode Django models, in your code you're trying to JSON-encode a serializer object, which doesn't work as there's no magic way to turn that object into json.

I understand you don't want to duplicate your form definitions and options, but you can just easily tell React the options/choices you need to use in the form. Normally you can achieve that by rendering a script tag in the template where you pass any initial data as JSON and you read that from the Js side.

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)

Then in the Django template you render (before you actually loads the js app files):

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

Be careful about escapejs, that can be a security issue if you are not absolutely sure initial_data contains only trusted data.

Then at this point you have INITIAL_DATA that is globally available to your js code, so you can base your React components on that.

You can still use the Django form definitions to perform server-side validation.

like image 173
fabio.sussetto Avatar answered Nov 13 '22 20:11

fabio.sussetto