CSRF error django 1.8 i18n internationalization - html

Hi I have django internationalization working on my django site. That is if i browse ".../en/foo/bar" and ".../nb/foo/bar" they work fine. But i am trying to get a drop down menu to automatically change the language but i get csrf error.
base.html
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}"/>
<select name="language">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for language in languages %}
<option value="{{ language.code }}"
{% if language.code == LANGUAGE_CODE %} selected="selected"{% endif %}>
{{ language.name_local }} ({{ language.code }})
</option>
{% endfor %}
</select>
<input type="submit" value="Go"/>
</form>
I however have another form in the same html but I do not but {% csrf_token %} in it. I rather place#csrf_exempt` on the view that handles the form.
I dont know whether having both froms on on html is what is causing the problem.
So what id did was that i created my own set_language view just like in django.veiws.i18n and places the #csrf_exempt on it.
#csrf_exempt
def set_language(request):
"""
Redirect to a given url while setting the chosen language in the
session or cookie. The url and the language code need to be
specified in the request parameters.
Since this view changes how the user will see the rest of the site, it must
only be accessed as a POST request. If called as a GET request, it will
redirect to the page in the request (the 'next' parameter) without changing
any state.
"""
print 'I am in setlang'
next = request.POST.get('next', request.GET.get('next'))
if not is_safe_url(url=next, host=request.get_host()):
print 'not safe'
next = request.META.get('HTTP_REFERER')
if not is_safe_url(url=next, host=request.get_host()):
next = '/'
response = http.HttpResponseRedirect(next)
if request.method == 'POST':
lang_code = request.POST.get('language', None)
if lang_code and check_for_language(lang_code):
if hasattr(request, 'session'):
request.session[LANGUAGE_SESSION_KEY] = lang_code
else:
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, lang_code,
max_age=settings.LANGUAGE_COOKIE_AGE,
path=settings.LANGUAGE_COOKIE_PATH,
domain=settings.LANGUAGE_COOKIE_DOMAIN)
return response
Though the CSRF validation error is solved the form has no effect when i change the language and submit. it just stays on the same page. it appears that if not is_safe_url(url=next, host=request.get_host()) is always true. I am not sure what i am doing wrong now
I just realised that my form sends a GET request to the view instead of a post so request.method is GET how and why is this so? The form data does not get to the view at all in this case but they submit when i leave the action attribute of the form blank. The the form submits to the view that called the page. Submitting to a specific view is not working as the request somehow becomes a get request

With first problem - csrf error, there is no simple solution (if you want csrf working, not bypassed) because we can't tell what is happening here - maybe some cookie-related issue.
But second problem is simple to solve. There is bug in django. In simple words, django won't translate url (change prefix in front of URL or translate whole URL) when user is changing language, so user will be redirected to old, not translated URL with old language prefix. That will cause to switch back to old language after redirection.
Solution to that problem is already submitted to django and will be available in django 1.9, but you can get code of that view from github and put it instead of your current language switching view.
Here is full commit for that fix, there is new function called translate_url in urlresolvers that is used in fixed view.

Related

Dynamic Display in Base HTML using DJango

I am new to DJango and i am creating a Website. I have created a base HTML page with a NAV bar which will be used across all pages. I want to display the message "Welcome 'username'" as the first line across all pages.
I had written the following code in views.py
def getusername(request):
uname=request.getusername()
return render(request,'main.html',{'uname':uname})
in the main.html after defining the title and nave bar, i have the following html code
<span class="label label-default">Welcome{{uname}}</span>
When i run this code, I am able to view the NavBar in all pages tat extends the base page(main.html)
but the welcome message does not fetch the username.
I have configured the following in urls.py
path("", views.getusername,name='getusername')
Note: Even when i hardcode a string to be returned from views.py, the string is not displayed as part of the welcome message
In every template you have access to user object.
You can check if user is authenticated:
{% if user.is_authenticated %}
Welcome, {{ user.username }}
{% else %}
# show register or(and) login button
{% endif %}

How to delete data from database inline using Symfony

I'm new with Symfony and I'm trying to delete some data from the database using an html table, something that looks like this but I don't know where to start:
Any help is appreciated :)
There are basically 3 choices, whether using symphony or not:
A link to a page (look at Symfony "routes") including the information which entry to delete.
A nice trick is to use the same page and add a query parameter.
This would look something like this in twig:
{% for row in table %}
delete
{% endfor %}
And in symfony:
if($request->get->has('delete'))
{
//delete it from the database
}
//the code that displays your table
This is the easiest way but has a few disadvantages. It is slow as the whole page has to be loaded again. The browsers back-button might not behave as the user might expect.
A html form doing basically the same as 1. but with post
{% for row in table %}
<form action="" method="POST">
<input type="hidden" name="delete" value="{{row.id}}">
<input type="submit" value="delete">
</form>
{% endfor %}
And in symfony use $request->request
Ajax triggered by an onclick event
A javascript deleterow function would send the id via ajax to a special symphony route that returns an JSONResponse and when successful delete the DOM Element with the row.
This is much more complicated and would need a lot more research on your part, but it is the modern way.

Preferred way to POST with params from a listing template in Django

I was looking for some input on the preferred way of making a post request from a list template in Django. The way I'm currently using doesn't quite seem right to me, even though it works.
Let's say I have a table of data from my model, SomeModel, which I'm outputting in a Django GCBV ListView.
class SomeModelList(ListView):
model = SomeModel
In my template I'm iterating over the list of models and outputting each row in a table with some of the data, and I want two buttons which make a POST to perform some operation on the current row's object.
I can write an entire form for each operation manually. Something like:
{% for object in object_list %}
{{ object.name }}</br>
<form method="POST" action="{{ url 'do_something' {{ object.pk }}"><input type="button" value="Do Something"/></form></br>
<form method="POST" action="{{ url 'do_something_else' {{ object.pk }}"><input type="button" value="Do Something Else"/></form></br>
{% endfor %}
It doesn't seem correct to be writing out these form tags like this.
Is this really the best way? Maybe I should have a single giant form around the whole list and use some properties of the button? Maybe I should be doing something with Django forms? Maybe something else entirely?
Thanks!

Simple (I hope) BoltForms questions

How can I change the text on a submit button?
I vaguely remember the option that it is possible to direct users to a page after submission. Is that documented?
The submit button just behaves like any Symfony Forms field, so you can simply to this:
submit:
type: submit
options:
label: My Button Text
As for redirect, sort of. You can't redirect yet, but you can give different HTML.
{% set html_pre = '<h1>This will appear above the un-submitted form</h1>' %}
{% set html_post = '<p>Thank you for submitting your form<p>' %}
{{ boltforms('formname', html_pre, html_post) }}

input type hidden value into the django template filters

I want to use one custom django filter.
It is having 2 variable movpath and projectname.
movpath is coming from input type hidden.
{% if movpath|is_path_exist:projectName %}
do something
{% else %}
do something
{% endif %}
Is it possible that we can take input type hidden value into the django template.
The standard way of using templates in Django consists in passing context variables to it. Consequently
So, at some point, you should have
context = {'form': form}, 'movpath': movpath}
render("template_name.html", context)
where movpath is obtained from the form's hidden field.
This way, the value of the hidden field of the form is passed to the context, which is passed to the template during rendering.