Django, Effective way to redirect URL - django

When a DOM change occurs, a Javascript function fires and redirect to the same website's page with certain parameters.
From the performance point of view, is the below method right?
const fire=(arg)=>{
location.href = '/admin/arg/';
}
Or should I use the {% URL 'path' %} tag ? if so, how ?

The {% url 'name' %} is obviously less efficient than calling the absolute url, but it's not going to break the bank rendering your html. What difference is it going to make? A few milliseconds?

Related

I need to cache a TemplateView with a querystring - how?

Basically, I'm trying to cache a simple search results page (generated with a TemplateView view) with a URL pattern of:
/search/?q=foo
I've tried:
#cache_page - doesn't work with querystrings (why? the stated reason "querystrings usually do not affect the results" completely depends on 'usually' meaning 'always' which is demonstrably false);
django-fancy-cache - doesn't work with CBVs (but in principle appears to do exactly what I want);
Adjusting the action on my form with an onSubmit() to change the url pattern (so that there's no querystring) - for SOME reason this messes up every other page on the site even though the test form doesn't exist on any of those pages.
I can't be the first person in the universe who needs this :-) ... Pointers to something I've missed in the Django docs or to a package that has eluded my search for it GREATLY appreciated.
You could use template fragment caching for that purpose, using the query string to uniquely identify the cache fragment. In your template:
{% load cache %}
{% cache 3600 search_results request.META.QUERY_STRING %}
<!-- search results here -->
{% endcache %}

Make django url tag fail silently

The Django {% url %} templatetag raises a NoReverseMatch error when it can't reverse the provided URL. This is useful in development, but in production, this stops the user dead in their tracks with an ugly 500 error, blocking the whole page, and leading them to think our site is broken.
Template developers shouldn't be able to bring down the whole site with a typo. What I want to do is transparently override this behavior so that, in production only, if a reverse match can't be found, it outputs a default url, like "#", and reports the error to our exception tracking system in the background, but still lets the user continue with what they were doing without raising the 500 error.
Is there a way to replace the default {% url %} tag with my own safer version, transparently? I don't want to have to add a {% load my_custom_url_tag %} at the top of every single template on the site, because at some point people will forget, and the behavior of the tag is will otherwise be the same, the only difference is how it handles errors.
You can use the built-in url tag in silent mode, try the lookup, and then use the URL it finds—if it finds something.
From the Django docs:
This {% url ... as var %} syntax will not cause an error if the view is missing. In practice you’ll use this to link to views that are optional:
{% url 'path.to.view' as the_url %}
{% if the_url %}
Link to optional stuff
{% endif %}
Hope that helps.
By implementing your own url tag, you're opening yourself up to lots of forward compatibility issues. My recommendation would be to add custom 500 error handler instead: https://docs.djangoproject.com/en/1.4/topics/http/views/#the-500-server-error-view
I would think you would actually want the view to throw an error if a template developer has made a typo. Trying to mask that behavior seems illogical - isn't that reason enough to have some simple unit tests to make sure your views are at least returning a 200 response code?

Getting the root url in Django

In my view, I want to make a request to mine.com/more/stuff/ from an arbitrary page such as mine.com/lots/of/stuff/to/use or from mine.com. Thus, I can't make this a relative request using ./ or ./../ type things. Do I have to use a context processor to do {{URL_BASE}}more/stuff/? Is there a set way to do this in Django or a best way?
why don't you use named urls? it's always works.
for example {% url 'admin:index' %} always printed as url to admin(in case if you using default django.contrib.admin app).
if you'll have in urls.py smth like
url(r'^lots/', Lots.as_view(), name='lots'),
then just use smth like
{% url 'lots' %}
Don't hardcode your urls!
Instead of a relative url, use an absolute url: /
If you're on mine.com/lots/of/stuff/to/use or mine.com, hitting a link with url: /foo/ will both go to mine.com/foo/

New url syntax from django 1.3/dev onwards

Why did the django core developers allow the url templatetag to point directly to a django view function? (reference - https://docs.djangoproject.com/en/dev/ref/templates/builtins/#url)
{% load url from future %}
{# 1st method: pointing to a view function #}
{% url 'app_views.client' %}
{# 2nd method: pointing to a named url #}
{% url 'myapp:view-name' %}
One can already name the url in urls.py and hence use the 2nd method to point to a specific url. It doesn't feel right to allow developers to actually reference a view function directly from the template.
Does anyone know why this decision was made?
Passing a dotted view function name to the {% url %} template tag is simply the form the template tag took in the earlier days of Django, before you could name URLs. It's still supported, though as you point out, you probably wouldn't use it in a modern application.
URLs in Django are just mappings to views. Therefore, in the template, using a named URL is just indirectly referencing the view anyway.
The exception is where a single view is mapped to by multiple URLs.
Also note that they are planning to change the syntax of the url tag in 1.5. It will take a context variable as the parameter, rather than a string. It will still take views or named URLs though.

Render to response to a redirected url in Django

In a form submission scenario, form is post to "/submit". I want to redirect user to "/sucess" on success and pass render some message to a template at new url. How to do this in Django? render_to_response doesn't do redirect and HttpResponseRedirect doesn't do template rendering.
The response from Daniel Roseman is potentially dangerous, opening your site to XSS vulnerabilities.
Make sure you strip html tags from whatever message is passed if you must do it this way.
A better way would be to redirect to /success/?msg=ok, and have in your view a dictionary:
{ 'ok': 'Your success message' }
If your success page needs a dynamic message, you need to pass it there somehow. You can either do this via GET parameters in the URL you are redirecting to - eg return HttpResponseRedirect('/success/?msg=My+success+message+here') - or by setting some values in the session, which the success view can pick up.
The best way to do what you want is:
In your view set the success message (or error message) as a dict. And use the render_to_response to display any template.
In your template you can verify if there is a message and if the message is an error message or a success message.
Some like this:
In your view:
if anyError:
dict = {"message" : {"error" : "The error message"}}
else:
dict = {"message" : {"success" :"The success message"}}
in your template:
{% if message %}
{% if message.error %}
{{ message.error }}
{% else %}
{{ message.success }}
{% endif %}
{% endif %}
Hope i've helped
There is no good way to do what you want. The browser submits the form, which will take the user to /submit. Once you decide whether it's "successful", it's too late; the browser has already decided on it's destination. All you can do is redirect. But, as you're finding out, it's going to be hard to keep your POST state when you redirect.
I would give up on this. It's not how websites are supposed to work.
I think Django does this already if you extend the generic view. On create there's an optional argument "post_save_redirect". This functionality is used in the automatically generated Django admin system. For example if you want a new resource, say user, you go to the url "/user/add". After you submit it redirects you to "/user/1" with a success message "you just saved user #1". So this is possible, but I'm still researching how to do it without extending the generic view. I'm still very new to Django and python, so looking through Django core to find how they did it is not so easy for me.
I would recommend to use Django message framework which is used for one-time notification messages.
https://docs.djangoproject.com/en/1.8/ref/contrib/messages/