django url tag performance - django

I was trying to integrate django-voting into my project following the RedditStyleVoting instruction.
In my urls.py, i did something like this:
url(r'^sections/(?P<object_id>\d+)/(?P<direction>up|down|clear)vote/?$',
vote_on_object,
dict(
model=Section,
template_object_name='section',
template_name='script/section_confirm_vote.html',
allow_xmlhttprequest=True
),
name="section_vote",
then, in my template:
{% vote_by_user user on section as vote %}
{% score_for_object section as score %}
<form class="sectionvote" id="sectionup{{ section.id }}"{% if vote and vote.is_upvote %} action="{% url section_vote object_id=section.id, direction="clear" %}"{% else %} action="{% url section_vote object_id=section.id, direction="up" %}"{% endif %} method="POST">
<input type="image" id="sectionuparrow{{ section.id }}" src="{{ MEDIA_URL }}/aup{% if vote and vote.is_upvote %}mod{% else %}grey{% endif %}.png"></form>
{{ score.score|default:0 }}
<form class="sectionvote" id="sectiondown{{ section.id }}"{% if vote and vote.is_downvote %} action="{% url section_vote object_id=section.id, direction="clear" %}"{% else %} action="{% url section_vote object_id=section.id, direction="down" %}"{% endif %} method="POST">
<input type="image" id="sectiondownarrow{{ section.id }}" src="{{ MEDIA_URL }}/adown{% if vote and vote.is_downvote %}mod{% else %}grey{% endif %}.png"></form>
It takes over 1.3s to load the page, but by hard coding it like this:
<form class="sectionvote" id="sectionup{{ section.id }}"{% if vote and vote.is_upvote %} action="sections/{{section.id}}/clearvote/"{% else %} action="sections/{{section.id}}/clearvote/"{% endif %} method="POST">
<form class="sectionvote" id="sectiondown{{ section.id }}"{% if vote and vote.is_downvote %} action="sections/{{section.id}}/clearvote/"{% else %} action="sections/{{section.id}}/downvote/"{% endif %} method="POST">
I got 50ms. Just avoid the url tag resolving stuff I got a 20+ times performance improvement.
Is there something I did wrong? If not, then what's the best practice here, should we do things the right way or the fast way?

If you're using the development version, there has recently been a regression which has massively increased the time it takes to reverse-lookup URLs - see the ticket here. It is scheduled to be fixed before the final release of 1.2.

Related

How to let user select currency in Django using Django-money?

I am currently working on an online store. I want a user to be able to change their currency option in the header and convert the whole site to the currency choice. I have found app called django-money, which seams to have that functionality, but I cannot find any implementation examples.
I want it to work like localize work in django. Having a form that will redirect to URL and saving choice in session and in cookie. This is the example of the language selection code.
/template.html
<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
<input name="next" type="hidden" value="{{ redirect_to }}">
<select name="language" onchange="this.form.submit()">
{% 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{% endif %}>
{{ language.code|upper}}
</option>
{% endfor %}
</select>
</form>
And then whenever I need something to be translated I will use this inside html:
{% trans "Some text to translate" %}
So is there something similar for currency? What would be the action for the form? Please can somebody help if you have ready solution! I will really appreciate.

how to save user's inputs without backeneds

I am just learning Django and web development in general and I was wondering if what I want to do is possible. I would like to write a Django quiz that saves the answers a user inputs without needing a backend. Is this possible?If it is not possible what is the simplest and easiest way I can do this. My template:
{% extends "base.html" %}
{% block title %}Exam Questions{% endblock %}
{% block content %}
{% if all_questions %}
<form action="{% url 'save_answer' %}" method="post">
{% csrf_token %}
{% for question in all_questions %}
<h3>{{question.text }}</h3>
<input type="hidden" name="exam_id" value="{{ question.exam.id }}">
<input type="hidden" name="question_id" value="{{ question.id }}">
<input type="hidden" value="{{question.answer_set.all}}" name="answers">
{% for answer in question.answer_set.all %}
<p><input type="radio" name="answer" value="{{ answer.id }}">{{ answer.text }}</p>
{% endfor %}
{% endfor %}
<input type="submit" value="Send">
</form>
{% else %}
<h2>No questions available</h2>
{% endif %}
{% endblock %}
Now I would like to know how to save user answers without backends
Afaik, you can save it in your backend (django forms doc), or save it with javascript in a client browser cookie.
First, make a litle change with your template to make radio choices work
<p><input type="radio" name="answer_{{ question.id }}" value="{{ answer.id }}">{{ answer.option }}</p>
Then, here is the code to store answers to session:
def post(self, request, *args, **kwargs):
post = request.POST
question_ids = post.getlist('question_id')
results = dict()
for id in question_ids:
answer = post.get('answer_%s' % id)
results[id] = answer
# Save to session or do whatever you want.
request.session['results'] = results
# Response to review
return JsonResponse(results)

Django comments flag "cancel" returns wrong url

I've set up django's built in comments in my application and I'm employing the flagging ability. The flagging works fine, but the 'cancel" link that appears on the template returns the following error:
could not find http
The template/form is as follows:
{% extends "base.html" %}
{% load i18n %}
{% block title %}{% trans "Flag this comment" %}{% endblock %}
{% block content %}
<h3>{% trans "Are you sure you want to flag this comment?" %}</h3>
<br />
<blockquote>{{ comment|linebreaks }}</blockquote>
<form action="." method="post">{% csrf_token %}
{% if next %}<div><input type="hidden" name="next" value="{{ next }}" id="next" /></div>{% endif %}
<p class="submit">
<input type="submit" class="btn btn-danger button-left" name="submit" value="{% trans "Flag" %}" /> or cancel
</p>
</form>
{% endblock %}
Any insight into this would be greatly appreciated.
I suspect it might be that you're site settings aren't correct. Check the sites app and see if you can make some changes there to get it working.

Django csrf forbidden on url variation

Hi I have an html template for switching languages on my site:
<form action="{{ SITE_URL }}i18n/setlang/" name="postlink" method="post">{% csrf_token %}
<ul class="lang">
<li class="lang">
{% for lang in LANGUAGES %}
{% if lang.0 != LANGUAGE_CODE %}
<input type="hidden" name="language" value="{{ lang.0 }}">
<a class="active" href=# onclick="submitPostLink()">{{ lang.1 }}</a>
{% else %}
{{ lang.1 }}
{% endif %}
{% if forloop.last %}{% else %} | {% endif %}
{% endfor %}
</li>
</ul>
</form>
All this works fine on the dev server and in production and in production at the normal url of www.mysite.com/project/
However, if I try project.mysite.com or mysite.com.project I get my home page as normal but changing the language brings up the 403 Forbidden failure.
Do I need to define the root url variations I need for setlang somewhere?
Any help much appreciated.
Since these urls are running on different subdomains, you should check the domain setting for the CSRF cookie CSRF_COOKIE_DOMAIN: https://docs.djangoproject.com/en/1.3/ref/contrib/csrf/#subdomains

Django: Redirect after posting a comment

I am trying to redirect the user back to the page where the comment was posted. I found this post on Django's site but I am doing something wrong because it won't redirect back.
Where should the input be placed to have it properly redirected?
{% load comments i18n %}
<form action="{% comment_form_target %}" method="post">{% csrf_token %}
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
{% for field in form %}
{% if field.is_hidden %}
{{ field }}
{% else %}
{% if field.errors %}{{ field.errors }}{% endif %}
<input type="hidden" name="next" value="{% url proposal proposal.id %}" />
<p
{% if field.errors %} class="error"{% endif %}
{% ifequal field.name "honeypot" %} style="display:none;"{% endifequal %}
{% ifequal field.name "name" %} style="display:none;"{% endifequal %}
{% ifequal field.name "email" %} style="display:none;"{% endifequal %}
{% ifequal field.name "url" %} style="display:none;"{% endifequal %}
{% ifequal field.name "title" %} style="display:none;"{% endifequal %}>
<!-- {{ field.label_tag }} -->{{ field }}
</p>
{% endif %}
{% endfor %}
<p class="submit">
<!-- <button><input type="submit" name="post" value="{% trans "Send" %}" /></button> -->
<button type="submit">Send</button>
<!-- <input type="submit" name="preview" class="submit-preview" value="{% trans "Preview" %}" /> -->
</p>
</form>
Maybe you don't need to check for next variable in your template. You could try changing:
{% if next %}<input type="hidden" name="next" value="{{ next }}" />{% endif %}
to just:
<input type="hidden" name="next" value="/added/comment/page/" />
In case you use views.py, redirecting from there seems more obvious, at least for me, as it helps keep the concern away from the template:
from django.http import HttpResponseRedirect
HttpResponseRedirect("/path/to/redirect")
The problem with axel22's answer is that it requires a change to each template that requires the comment form - if you have multiple object types that can be commented on, this is not DRY.
Unfortunately, I'm also still looking for an answer that works.
if you are using {% render_comment_form for object %} tag in your template, just add something like {% url object's_named_view object.id as next %} or wrap it with {% with object.get_absolute_url as next %} ... {% endwith %} construction.
See my solution here: Django: Redirect to current article after comment post
It basically uses a view that's triggered by the comment post url which redirects back to the original referrer page.