Using Babel with Mako templates in tornado Web Application - internationalization

I have a tornado application, which uses Mako for templating. Using Babel I was able to create translations (mo files) but When I am not able to render the translated string.
My html block (index.mako):
`<li> <a id="login"> ${_('Login')} / ${_('Signup')} </a></li>`
handler.py
class HomeHandler(BaseHandler):
def get(self):
hometemplate = makoLookup.get_template("index.mako")
response_str = hometemplate.render()
self.write(response_str)
response_str returns
<li> <a id="login"> Login / Signup </a></li>
How do I implement internationalization in mako? All the document i searched explains extracting translations but could not find any document on using translations in mako templates.
I have tried using Tornado-Babel but could not find document on integrating with mako templates.

Using TornadoBabelMixin. I pass the self._ to my template rendering function. Now my handler code looks like this.
class HomeHandler(TornadoBabelMixin, BaseHandler):
def get_user_locale(self):
return locale.get("en_US")
def get(self):
hometemplate = makoLookup.get_template("index.mako")
response_str = hometemplate.render(_ = self._)
self.write(response_str)

Related

How can I create a DjRF API endpoint that returns a RML-generated PDF?

Django documentation has the following example for ReportLab.
from reportlab.pdfgen import canvas
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
# Create the PDF object, using the response object as its "file."
p = canvas.Canvas(response)
# Draw things on the PDF. Here's where the PDF generation happens.
# See the ReportLab documentation for the full list of functionality.
p.drawString(100, 100, "Hello world.")
# Close the PDF object cleanly, and we're done.
p.showPage()
p.save()
return response
However. I want to use RML to generate my PDF. ReportLab Plus offers an rml2pdf function that can turn an RML document into a PDF using a similar markup to Django's templating. How can I provide Django the RML template and have Django return the PDF in the API response, similar to the example in the documentation?
Figured it out.
RML Template
Put this in your Django templates folder so Django can find it.
Call it templates/rml_template.rml
<!DOCTYPE document SYSTEM "rml.dtd">
<document filename="example_01.pdf">
<template>
<!--this section contains elements of the document -->
<!--which are FIXED into position. -->
<pageTemplate id="main">
<frame id="first" x1="100" y1="400" width="150" height="200"/>
</pageTemplate>
</template>
<stylesheet>
<!--this section contains the STYLE information for -->
<!--the document, but there isn't any yet. The tags still -->
<!--have to be present, however, or the document won't compile.-->
</stylesheet>
<story>
<!--this section contains the FLOWABLE elements of the -->
<!--document. These elements will fill up the frames -->
<!--defined in the <template> section above. -->
<para>
Welcome to RML!
</para>
<para>
This is the "story". This is the part of the RML document where
your text is placed.
</para>
<para>
It should be enclosed in "para" and "/para" tags to turn it into
paragraphs.
</para>
</story>
</document>
Django View
This view loads the template as a string and rml2pdf uses the response object as its "file" to write to, similar to the Django documentation example.
from django.template import loader
from rlextra.rml2pdf import rml2pdf
from django.http import HttpResponse
def some_view(request):
# Create the HttpResponse object with the appropriate PDF headers.
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="somefilename.pdf"'
context = {} # You can add values to be inserted into the template here
rml = str(loader.render_to_string('rml_template.rml', context))
rml2pdf.go(rml, outputFileName=response)
return response

AJAX Routing to Django URLs (Using Django 2.0 "path" urlpatterns)

This used to work before Django 2.0 changed url patterns from "url" to "path":
index.html
<!DOCTYPE html>
{% load static %}
<head>
<script type="text/javascript" src="{% static 'main/js/jquery-3.3.1.js' %}">
</head>
<body>
<div id='test'>
<p><button class="btn">Click Here!</button></p>
</div>
<script>
$('.btn').click(function(){
console.log('button is clicked!')
$.ajax({
url: 'main/all_json',
sucess: function(serverResponse){
console.log('success.serverResponse', serverResponse)
}
})
});
APP LEVEL urls.py
urlpatterns = [
url(r'^all_json$',views.all_json, name="all_json")
]
Project Level urls.py
app_name= "main"
urlpatterns = [
path('', include ('apps.main.urls', namespace='main')),
path('admin/', admin.site.urls),
]
views.py
def all_json(request):
return HttpResponse ('hello world!')
But now, Django 2.0 uses "path" instead of the url regex pattern. When I use path:
app_name= "name"
urlpatterns = [
path('all_json',views.all_json, name="all_json"),
]
I get the:
GET http://127.0.0.1:8000/main/all_json 404 (Not Found)
I looked in the new documentation and release notes and there are some SO answers that explain how to use it SO post 1 & SO post 2. That has been useful up to this point, where I'm unable to pass the url from the AJAX function to the "path".
I'm new to AJAX and I'm used to using the {% url main:all_json %} in Django for my actions. But with AJAX I believe I can't use this notation. Is that right?
And for some reason, the examples that I have that used url(r'^$') urlpatterns before Django 2.0 worked, but now I get a code 404 when using 'path'. Most of the questions and tutorials available are pre Django 2.0 and use url(r'^$') urlpatterns. Release notes and documentation do not mention anything about differences in working with AJAX.
My questions is the following:
Is there something else that I need to add in my template and/or urls.py to help it find the urls(get rid of the 404)?
First, url is still perfectly valid in Django 2.0. In later versions exactly the same functionality is available as re_path.
However, the problem is not there. It is that you have added a final slash in the new version where you didn't have one before. Remove it:
path('all_json', ...)
or, preferably, add it to the Ajax call:
url: 'main/all_json/',
Note finally that since the Ajax script is directly in the template file, it's absolutely possible to use the {% url %} tag there.
Try to build API's that clear and useful. Using main, all_json names are unclear. Nevertheless, let's try on your examples:
In your urls.py use main/all_json/ and name="all_json". Accoding to documentation:
There’s no need to add a leading slash, because every URL has that. For example, it’s articles, not /articles. link
...each pattern requires that the URL end with a slash. link
In your HTML template (by the way, it's maybe mistake, but you named it html.py. I advise to refactor this to somename.html), in the js block use template tag {% url "all_json"" %} like:
$.ajax({
url: '{% url "all_json" %}',
sucess: function(serverResponse){
console.log('success.serverResponse', serverResponse)
}
})
By using url template tag you can avoid many mistakes when changing urls.

How to use ajax in Brython

I am writing a web application using Flask and would like to use browser.ajax functionality in Brython but couldn't find a workable example. It would be very nice if someone demonstrates a short example how to use ajax in Brython. More specifically, how to pass data entered by a user into a textfield to a textarea by clicking submit button. Any help is highly appreciated!
(I am writing this several weeks after I posted the question above). I followed this tutorial on how to implement ajax in Flask (http://runnable.com/UiPhLHanceFYAAAP/how-to-perform-ajax-in-flask-for-python) and tried to replace jquery.ajax by Brython. Unfortunately, I still cannot get it work. Here is my code:
Flask's portion:
#app.route('/')
def index():
return render_template('index.html')
#app.route('/_add_numbers')
def add_numbers():
a = request.args.get('a', 0, type=int)
b = request.args.get('b', 0, type=int)
return jsonify(result=a + b)
Brython/HTML:
<body onload="brython()">
<script type="text/python">
from browser import document as doc
from browser import ajax
def on_complete(req):
if req.status==200 or req.status==0:
doc["txt_area"].html = req.text
else:
doc["txt_area"].html = "error "+req.text
def get(url):
req = ajax.ajax()
a = doc['A'].value
b = doc['B'].value
req.bind('complete',on_complete)
req.open('GET',url,True)
req.set_header('content-type','application/x-www-form-urlencoded')
req.send({"a": a, "b":b})
doc['calculate'].bind('click',lambda ev:get('/_add_numbers'))
</script>
<div class="container">
<div class="header">
<h3 class="text-muted">How To Manage JSON Requests</h3>
</div>
<hr/>
<div>
<p>
<input type="text" id="A" size="5" name="a"> +
<input type="text" id ="B" size="5" name="b"> =
<textarea type="number" class="form-control" id="txt_area" cols="10" rows = '10'></textarea>
<p>calculate server side
</div>
</div>
</body>
</html>
What I get is "result":0. It looks like brython does not send data to the Flask's view function but I don't know how to fix that. So, it would be great if some one could point out what exactly I am doing wrong.
In your example, the Ajax request is sent with the method GET. In this case, the argument of send() is ignored : the data must be sent in the query string appended to the url
The Brython code should be :
def get(url):
req = ajax.ajax()
a = doc['A'].value
b = doc['B'].value
req.bind('complete',on_complete)
# pass the arguments in the query string
req.open('GET',url+"?a=%s&b=%s" %(a, b),True)
req.set_header('content-type','application/x-www-form-urlencoded')
req.send()
If you want to use the POST method, then you can keep the Brython code as is, but the Flask code should be modified : you must specify that the function handles a POST request, and you get the arguments with the attribute "form" instead of "args" :
#app.route('/_add_numbers_post', methods=['POST'])
def add_numbers_post():
a = request.form.get('a', 0, type=int)
b = request.form.get('b', 0, type=int)
return jsonify(result = a+b)
I am working on that - there is nothing ready made, but writing Python code makes it really painless.
I can't post the code I am working on, (and it is far from minimal) - but basically, you write a (Br)Python function to iterate on the HTML, or form DOM, and collect everything that has a "value" in a json-nish structure (a dictionary with nested dicionaries and lists at will) - Them you simply use the browser.ajax object as documented in http://brython.info/doc/en/index.html#, and pass the object with your data as a parameter to the "send" method.
The object data will be URLencoded in the request body. You just have to decode it from there to JSON on the client side.
As an extra hint:
I did not go deep on the question, but I feel like the URLencoding used by default may fail to express everything that is possible in JSON. So imported brython's json module, and do the send like this:
ajax_object.send({"data": json.dumps(json_data)})
This allows me to do this on the client-side:
json_data = json.loads(urllib.unquote(request.body).split(":",1)[-1] )
(the "request.body" is from Pyramid - for flask it is "request.data", but only if the conte-type is not understood by the flask - check How to get data received in Flask request )

How to create a simple ajax form in Drupal 7?

I want to create a simple form in Drupal7 with only one field. When hitting the submit button I need to call an ajax function with the field value and update a DIV on the page without reload.
I'm not familiar with Drupal form API, and I tried to implement the examples form the form api documentation but I always get errors like this:
Notice: Undefined index: #title_display form_pre_render_conditional_form_element() függvényben (/var/www/nmtest/includes/form.inc 2986 sor).
Notice: Undefined index: #value theme_textarea() függvényben /var/www/nmtest/includes/form.inc 3727 sor).
I can do it by creating a custom page and simply use native PHP but this is not an "elegant" way.
I want something similar like the one here, but without form valitation, page reload or so: Create a VERY simple form in Drupal
I only want one button that calls an ajax function. Shoud I do this with forms API or just use plain old native PHP and jQuery?
Edit: Looks like I don't even need a real ajax call, because I only need to change an SRC of an IMG tag.
Here's what I did in native PHP. I want to achive this trough forms api:
<script>
function getstar() {
starpoints = jQuery('#starpoints').val();
rand = Math.floor(Math.random() * 9999) + 1;
src = "test.php?star=" + starpoints + '&rand=' + rand;
jQuery('#starimg').attr("src",src);
return false;
}
</script>
<form>
<input type="text" name="starpoints" id="starpoints" />
<input type="submit" onclick="return getstar();" />
</form>
<img src="/test.php?star=5" id="starimg" />
Edit: Ok, I managed to render a form with the Drupal API. Now the only thing is that I want to insert the placeholder for the IMG via my module, but I don't know how to do it. The form renders fine, but I want to add a HTML block after it. Currently I do it by javascript:
jQuery(document).ready(function() {
jQuery('<div><br /><img id="starimg" src="" /></div>').insertAfter('#drawstar-form');
});
What hook should I catch to render this HTML block after the form? I tried drupal_get_form but that returns an array and I cannot attach the HTML block.
The Form API provides everything that you need to do this without writing a single line of JavaScript code. See http://drupal.org/node/752056 and http://api.drupal.org/api/examples/ajax_example!ajax_example.module/function/ajax_example_simplest/7 and .

HtmlAgilityPack Div Class Contains String

I'm trying to scrape only article text from web pages. I have discovered that the article is always surrounded with div tags. Unfortunately the class of these div tags is slightly different for each web page. I looked into using XPath but I don't think it will work due to the different class names. Is there a way I can get all the div tags and then get the class?
Examples
<div class="entry_single">
<p>I recently traveled without my notebook for the first time in ages.</p>
</div>
<div class="entry-content-pagination">
<p>Ward 9 Ald. Steven Dove</p>
</div>
That'd be easier using Linq.
foreach(HtmlNode div in doc.DocumentNode.Descendants("div"))
{
string className = div.GetAttributeValue("class", string.Empty);
// do something with class name
}

Resources