I have my data in the form of a CSV file at the following location C:\xyz\data.csv in my system. How can I access this data from the controller of my grails application? Is it possible to do so? If yes, how? Any help would be much appreciated.
for reading file (cvs, xml, img ,...) from controller
def csv = grailsAttributes.getApplicationContext().getResource("/data/data.csv").getFile()
try this for your case...
If your Grails application runs on the same system you can access the file like this.
class MyController {
def myAction() {
def myFile = new File('your path')
def content = myFile.text
}
}
If your webapp runs somewhere else (which is most likely your case) you can use the file upload.
Related
FileSystemLoader loads templates from a directory, Is there anyway I could pull the template from a database as string into loader ?
env = Environment(
#loader=FileSystemLoader(templates),
loader = Filedb('template.j2') # fetch from db ?
undefined=StrictUndefined # Force variable to be defined
)
env.filters['custom_filter'] = func
t = env.get_template("template.j2")
From the Jinja docs:
If you want to create your own loader, subclass BaseLoader and override get_source.
For example:
class DatabaseLoader(BaseLoader):
def __init__(self, database_credentials):
self.database_credentials = database_credentials
def get_source(self, environment, template):
# Load from database... an exercise for the reader.
Because templates can depend on other templates, loading one template could require multiple database lookups. Database lookups could be minimized using bytecode caching to cache compiled templates.
It is also possible to load all of the templates from the database into a dictionary, and then load the dictionary using Jinja's DictLoader.
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?
In my windows store app using the Visual Studio 2012 designer I want to be able to load some model objects for the designer. I've done this plenty of times before where I supply a xaml file using the ms-appx:/// uri without error. However, for this project I need to be able to instantiate a class and have it convert raw xml of a different format into my model objects.
I'm using the following xaml to instantiate my class for the designer:
d:DataContext="{Binding Source={d:DesignInstance Type=model:Walkthroughs, IsDesignTimeCreatable=True}}"
In my Walkthroughs class had code that did this initially:
public Walkthroughs()
{
if (Windows.ApplicationModel.DesignMode.DesignModeEnabled)
AppDataLoader.LoadWalkthroughs(this, XDocument.Load("ms-appx:///SampleData/walkthroughs.xml"));
}
I first ran into an issue where the XDocument.Load did not understand the ms-appx:/// uri so I modified my code to something very simplistic:
AppDataLoader.LoadWalkthroughs(this, XDocument.Load(#"C:\walkthroughs.xml"));
Now I get access to path '' is denied.
I've tried several directories as well to no avail. I'm even running Visual Studio as an Administrator. If I remove the prefix altogether I get the following error:
Could not find file 'C:\Users\{me}\AppData\Local\Microsoft\VisualStudio\11.0\Designer\ShadowCache\omxyijbu.m4y\yofsmg1x.avh\walkthroughs.xml'.
Has anyone been able to load files from the file system when the designer instantiates objects?
Thanks,
-jeff
XDocument.Load(string uri) seems to have problems with loading Project resources from ms-appx:/
Regarding your second approach: Direct access to "C:" is not permitted. Ther is only a handful of special folders that you can access. Check out my workaround for this (my xml file is within the Assets folder of my project:
var storageFolder = Windows.ApplicationModel.Package.Current.InstalledLocation;
storageFolder = await storageFolder.GetFolderAsync("Assets");
var xmlFile = await storageFolder.GetFileAsync("data.xml");
var stream = await xmlFile.OpenReadAsync();
var rdr = new StreamReader(stream.AsStream(), System.Text.Encoding.GetEncoding("ISO-8859-1")); //needed if you have "ä,ß..." in your xml file
var doc = XDocument.Load(rdr);
So I am trying to create an Android mobile application and I am using CakePHP as my serverside. I will not be needing any HTML views, I will only be responding with JSON objects.
I have taken a look at http://book.cakephp.org/2.0/en/core-libraries/components/request-handling.html#RequestHandlerComponent and with that I've created this:
class LocationsController extends AppController
{
public $helpers = array('Html', 'Form');
public $components = array('RequestHandler');
function index()
{
$locations = $this->Location->getNearest();
$this->set(compact('locations'));
$this->set('_serialize', array('locations'));
}
}
and I have added this to my routes.php:
Router::mapResources('locations');
Router::parseExtensions('json');
Nothing is displayed when I run this apart from the default CakePHP layout style. If I remove the index.ctp view file, I get an error that it can't find the view file. Why does it still require a view file? I thought with the serialize approach it does not need a view. I have tried looking in the Google Chrome developer console and there is no response that contains the JSON object. However, the MySQL has performed perfectly fine.
Put $this->render(false); between
public $components = array('RequestHandler');
and
function index()
Now it doesn't require an index.ctp file anymore.
See this link for more information.
I just did the same thing, using the REST API, as I want the response in the JSON.
What I did is I used the Chrome advanced rest client. In that I made a request to my localhost server by using the appropriate GET method, and it succeeded.
like: GET /users/view/103.json
you will get the response as:
{"users":{"User":{"id":"103","username":"abc","password":"xyz",
"email-id":"abc#xyz.com"}}}
I have a simple grails file upload app.
I am using transferTo to save the file to the file system.
To get the base path in my controller I am using
def basePath = System.properties['base.dir'] // HERE IS HOW I GET IT
println "Getting new file"
println "copying file to "+basePath+"/files"
def f = request.getFile('file')
def okcontents = ['application/zip','application/x-zip-compressed']
if (! okcontents.contains(f.getContentType())) {
flash.message = "File must be of a valid zip archive"
render(view:'create', model:[zone:create])
return;
}
if(!f.empty) {
f.transferTo( new File(basePath+"/files/"+zoneInstance.title+".zip") )
}
else
{
flash.message = 'file cannot be empty'
redirect(action:'upload')
}
println "Done getting new file"
For some reason this is always null when deployed to my WAS 6.1 server.
Why does it work when running dev but not in prod on the WAS server? Should I be accessing this information in a different way?
Thanks j,
I found the best dynamic solution possible. As a rule I never like to code absolute paths into any piece of software. Property file or no.
So here is how it is done:
def basePath = grailsAttributes.getApplicationContext().getResource("/files/").getFile().toString()
grailsAttributes is available in any controller.
getResource(some relative dir) will look for anything inside of the web-app folder.
So for example in my dev system it will toString out to "C:\WORKSPACEFOLDER\PROJECTFOLDER\web-app\ with the relative dir concated to the end
like so in my example above
C:\WORKSPACEFOLDER\PROJECTFOLDER\web-app\files
I tried it in WAS 6.1 and it worked in the container no problems.
You have to toString it or it will try to return the object.
mugafuga
There's a definitive way...
grailsApplication.parentContext.getResource("dir/or/file").file.toString()
Out of controllers (ex. bootstrap)? Just inject..
def grailsApplication
Best regards!
Grails, when it's run in dev mode, provides a whole host of environment properties to its Gant scripts and the app in turn, including basedir.
Take a look at the grails.bat or grails.sh script and you will find these lines:
Unix: -Dbase.dir="." \
Windows: set JAVA_OPTS=%JAVA_OPTS% -Dbase.dir="."
When these scripts start your environment in dev mode you get these thrown in for free.
When you take the WAR and deploy you no longer use these scripts and therefore you need to solve the problem another way; you can either
Specify the property yourself to the startup script for the app server, eg: -Dbase.dir=./some/dir .. however
... it usually makes more sense to use the Grails Config object which allows for per-environment properties
Another option:
def basePath = BuildSettingsHolder.settings.baseDir