ReactJS & django-forms - json

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:
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.
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? :-)

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.

Thanks to Fabio, I now see how my approach couldn't work :-) Not sure if I take this advice, but it seems probable.
Note: I have server side rendering.
Note2: complete newbie to react & serializers & django-rest-framework
What I initially tried to achieve was a solution to this part of my react jsx files:
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;
Everything enclosed in render can be generated from django backend and actually is. Why writing it down again? Isn't there really a way to use ajax and fetch it from the back? I guess it probably is against react philosophy to fetch static content from server over and over again ...
But, more broader .. I am looking for a way to do this from developer perspective, only once before deployment: the server generates html and fills jsx files with it and go to production or something like that. Like a django app ... Is that also impossible, still a wrong way to think about this?

Related

Can we use python related api's on the Django templates?

I am new to Django and hence not having thorough knowledge about it. So I am facing a few errors in Django.
Currently I am trying to print the type of a variable from the Django template html file as follows:
<center><h2>The type of feature list report for version {%type(version)%} is<h2></center>
For the above, I am getting the following error:
Invalid block tag on line 9: 'type(version)'. Did you forget to register or load this tag?
So what's going wrong here? How can we use the python related api's (like type(), strip(), get(), etc) from the html template files? I think inside the {% .... %} we can use python related evaluations. Am I right?
Please throw some lights on this .
As said, this is not the philosophy of DTL, but some functions that transform input are implemented as filters.
In addition, you can write your own filters and supporting a "type" filter, would be very simple:
from django import template
from typing import Any
register = template.Library()
def filter_type(value: Any) -> str:
return str(type(value))
register.filter('type', filter_type)
See the documentation for details.
Both Jinja's and DTL's approach are explicit over implicit: instead of blindly supporting any python function with all it's dangers, you have to explicitly allow it or implement it.
Running arbitrary Python code in a Django template is intentionally disabled. Aside from security concerns, the reason is your project's business logic should be separate from your presentation layer. This is part of good application design.
There are three primary ways you can call an operation from a Django template.
Pass in a function and call it.
Use a template filter, either custom or built in.
Use a template tag, either custom or built in.
Pass in a function and call it.
Calling a passed in function from a Django template is standard. However, it has two caveats.
The function must return a value that can is a string or can be coerced to a string. (Otherwise nothing will be printed in the template.)
The function must not have any required arguments.
The most common use case is either a computed value or a getter e.g.
class Page(models.Model):
title = models.CharField()
def get_title(self):
return self.title
<h1>{{ page.get_title }}</h1>
Template filters
See Melvyn's answer for an example of template filters.
Template filters operate on a value. So this is perfect for a Python function like type().
Template Tags
Edited: see Melvyn's comment.
Simple Template tags on the other hand work more like a function. They accept positional and keyword arguments and should again return a value. I won't go into inclusion tags or advanced tag compilation and rendering here, but you can read about it in the Django custom template tag docs.
Here is an example of two template tags I often include in a project in debug.py.
import pprint
from django import template
register = template.Library()
pp = pprint.PrettyPrinter(indent=4, width=120)
#register.simple_tag(takes_context=True)
def print_context(context):
pp.pprint(context)
return ""
#register.simple_tag()
def print_thing(thing):
pp.pprint(thing)
return ""
I can use print_context to print the current context in terminal and print_thing to print something.
{% load debug %}
{% print_context %}
{% print_thing 'print this string' %}
You can create a template tag that will do anything a standard Python function can do. This is because a template tag essentially calls the function you create.
Use the constraints of the Django template system to your advantage to create well designed applications where the business logic is located in the views, models, and helpers, and not in the templates.
You may create a class which includes the type, so you can call the type like: variable.type or you can send the type data from the controller.
If you need to make reactive programming logic at the front end, I'd suggest you use Vue, React or Angular.

Working with complex json via HTTP request in Angular project (MEAN STACK)

I'm currently working on a project of my own, and I'm having problems when handling "large" JSON files. I get the data from a MongoDB online (Mongo Atlas), then I access that data through a simple node JavaScript REST API. Given that the complexity of the JSON is large, I'm not sure how to proceed. I normally create a model of the JSON to handle it. But in this case, I don't really know how to do it. The schema is this:
Swagger documentation
As you can see it has a lot of nested arrays.
My question is, should I use classes or maybe interfaces? For every array do I need to make a new class?
Currently, this is the model that I was working with:
(this was working on JavaScript, but of course does not work in TypeScript because the object is not truly defined)
export class Match{
constructor(
public _id: string,
public game: Object
){}
}
I know I could import the whole swagger UI to my own project (don't really know how to do it, https://www.npmjs.com/package/swagger-ts-generator, this might work), but I only really need that one schema.
Any help would be appreciated.
To be frank, when a JSON exceeds a specific length, I really don't use models to handle it (Java side), in fact I'm not using them at all in Angular. It has advantages and also disadvantages, especially when talking about a typescript context, it's not really the recommended thing, but it does the job.
public getData(): Observable<any> {
return this.http.get(environment.apiBaseUrl + "/data/", this.prepareHeader());
}
Then you actually just subscribe on the Observable and access the variables you need by their key, e.g.
this.dataAcquireService.getData().subscribe(
(res) => {
this.data = res;
for (let i = 0; i < this.data.length; i++) {
if (!this.selectGroups[this.data[i].name]) this.selectGroups[this.data[i].name] = [];
this.selectGroups[this.data[i].name].push(this.data[i]);
}
},
(err) => this.dataAcquireService.handleErrorResponse(err)
)
In the end, it's down to taste and expectations because both ways lead to the desired goal, the one might be considered dirty by dogmatists, the other might be considered too tedious.

Is there a way to lazily load static json during Angular6 routing?

I've got an Angular6 app that is being built as more of a framework for internal apps. The header / footer / major navigation will be shared, but each app (feature module) should have internal flows separate from each other. For example one feature might be purchasing, another might be onboarding, another might be a sales dashboard. They're very different from each other.
What I'm trying to do is come up with a declarative way to define known configurations for each feature. For example, the minor navigation (page to page within a feature), top level header title, and various other context related data points. My initial thought was to have them defined as JSON within each feature, which works great except I now have to import every feature's config regardless of whether a user navigates, or even has access to, that feature.
I've already got the context service set up that is checking the URL on navigation and setting some items, but again, it has to import all possible configs using this at the top of that service.
import { fooConfig } from '#foo\foo.config';
import { barConfig } from '#bar\bar.config';
import { bazConfig } from '#baz\baz.config';
So the question is: Is there a way for me to check the URL on navigation, and within that subscription, pick up the config from the correct file without pre-maturely importing them? Or maybe I can use the module to express / declare those options?
Using Typescript's Dynamic Import Expressions might be a viable option in your case..
let config;
switch (val) {
case 'foo': config = await import('#foo\foo.config'); break;
case 'bar': config = await import('#bar\bar.config'); break;
case 'baz': config = await import('#baz\baz.config'); break;
}
Though, as far as I know, there's now way at the time of writing to use variables for the import string (e.g. await import(path)).
updateConfig(feature: string) {
import(`../configs/${feature}.config.json`).then(cfg => {
this._currentConfig$.next(cfg);
});
}
The above snippet shows what I came up with. It turns out WebPack can't digest the # paths you normally use on imports and you also can't use fully variable paths. All possible options for the module package must have some common part of the path. I ended up moving my configs from #foo\foo.config.ts to #core\configs\foo.config.json. Which makes them less modular because now core is holding their config, but it makes the module lazy.

Using same model from store in a component used in all routes in Ember 2.8.0

My use case: application has a header that displays current user's name. This header is the same on all pages.
User data is loaded from JSON API into the Store when user logs in.
Now, how am I supposed to access this data from Store to use it on every page?
One option is to pass it from routes:
{{app-header user=model}}
But then I would have to use the same model in all the routes and also would be unable to use any other? How can a (supposedly reusable) component expect from me to adjust every route to its data structure?
The other option is that component always loads data from Store on its own, but this seems strongly unrecommended and actually very hard to do for me without any proper guide. I managed to discover service injection method (store: Ember.inject.service() in the component) but still can't get the component to properly display data from store in the template.
When I use:
name: () => {
return this.store.peekRecord('user', 1).get('name');
}
then {{name}} in template renders function definition, not what it returns.
When I use:
name: Ember.computed(() => {
return this.store.peekRecord('user', 1).get('name');
})
then {{name}} renders: <!---->
Could you please explain what is a good way to do this? Is there some "master model" defined in application.js besides models from routes? Should I really pass the same data to component in every route? Any information or suggestions will be greatly appreciated.
You could try using a service (guide here).
// app/services/store.js
import DS from 'ember-data';
export default DS.Store.extend({});
// app/services/user-service.js
import Ember from 'ember';
export default Ember.Service.extend({
store: Ember.inject.service(),
user: Ember.computed(function() {
return this.get('store').findRecord('user', ':id');
})
});
Then, in all your other components, controllers, and routes, you can access the service.
// Inside a controller
export default Ember.controller.extend({
userService: Ember.inject.service(),
firstName: Ember.computed.alias('userService.user.firstName')
});
The first name, or even the user object itself is now available in you template.
{{userService.user.firstName}}
OR
{{firstName}}
First approach, (Keeping it in Application Route)
1.Define it in application route model hook - refer multiple modelsin single route.(https://guides.emberjs.com/v2.9.0/routing/specifying-a-routes-model/#toc_multiple-models)
2.If its required in another route, then you can access already resolved model of the parent route through modelFor method.(http://emberjs.com/api/classes/Ember.Route.html#method_modelFor)
Second Approach, (Service)
Like #devman answer, you can load it in service and inject and get it wherever you require.
userService:Ember.inject.service();
name: Ember.computed.alias('userService.name')

Grails with JAX-RS vs UrlMappings for RESTful Services

I started out looking at the JAX-RS plugin for grails and thought that was the way to go mainly because it was based on JSR-311 and I figure following standards is usually the smart thing to do. However, using Grail's UrlMappings it seems I basically achieve the same thing. I figure I'm missing something, however, we aren't doing anything overly complex. We basically just need to expose CRUD via an API. Example of doing the same thing with both versions:
JAX-RS:
#PUT
#Consumes(['application/json'])
#Produces(['application/json'])
Response putUser(User user) {
user.save(flush:true)
ok user
}
Grails:
def update = {
def user = new User(params['user'])
user.save(flush:true)
render user as JSON
}
Obviously, this is an overly-simplified example and like I said, maybe I'm missing something important. Also, the nice thing about the Grails built in mechanism is I can utilize Content Negotiation along with it.
Anyone have any opinions on this?
I had to make the same decision, and I found it just easier to use URL Mappings because the API was not that complex and there were a limited number of API calls that needed to supported.
If came down to what would be easier to maintain based on the LOE and the resources able to support the implementation.
The jax-rs plugin is very useful if you are creating web services straight to your domain models. It gives you a "generate-resource" command that automatically creates CRUD apis for your model.
grails generate-resource mydomain.Model
This part seems to work fine, however, I encountered quite a few bugs/problems with the plugin that I finally had to implement the REST services using URL-mappings.
Although the URL-mapping method seems to be more coding, it works perfectly.
import grails.converters.JSON
class ModelServiceController {
def id = params.id
def myModel = MyModel.findById(id)
render myModel as JSON
}
Here's the link for grails REST
http://grails.org/doc/1.0.x/guide/13.%20Web%20Services.html