django Is there a way to get a reversed url without passing parameters? - django

I am using ajax data to pass info to my page, but I need to create some links that use data from the javascript to call a view, so the parameters usually passed when one does a {% url 'jobs:close' foo %}, for example, are not available at the time the template is rendered, but imported later through an ajax call. Obviously, this causes errors when the template is rendered.
Is there a way to keep the benefit of having reverse url lookups in such a situation, and dynamically get the URL in the template without passing foo, or do I need to hard code the URL in the template and paste the parameter on the end later?

Instead of getting 'foo' in ajax response, get the reverse url in ajax response and replace the DOM where you need the url.

After thinking about it, and looking at comments, I decided on the answer of adding a fake parameter and removing it afterwards. Since it will be removed when the form is rendered, the parameter doesn't much matter. I chose 1.
So, in my template, I put {% url 'jobs:close' '1' %}. Then in my javascript, as I call the form in a modal, I use jquery to find the form. It makes it easy just to use the same URL again, so here it is:
var modal = $("#modal");
var closeUrl = '{% url 'jobs:close' '1' %}';
closeUrl = closeUrl.substring(0, closeUrl.length - 2) + event.data.id + /;
modal.find("#close-job").attr('action', closeUrl);
event.data.id is where I am storing the job ID that I really need.
It isn't as slick as I was looking for, but it works well.

Related

simple application pass value from django views to javascript

It has been 2day i am trying to figure out how to do that. I am a novice so please give as detailed explanation as possible.
I am doing this in my views.py
dict1 = simplejson.dumps(dict1)
return render_to_response('main_page.html', {
'js_testsuite':testsuite_dict,
'js_testset':js_testset,
'dict1':dict1})
In main_page.html
{% if js_testsuite %}
<select id="testsuites" name="testsuite" onchange="setOptions(document.selection.testsuite.selectedIndex);">
{% for key, value in js_testsuite.items %}
<option value={{ value }} name="testsuite">{{ key }}</option>
{% endfor %}
</select>
{% endif %}
In setoptions.js, which contains the function setOptions(value), to which i am passing selected index of the select box, and using this value i have to set the second select box and the data for this select box has to come from the views.py given above.
Also, I tried doing
var value_from_django = {{ dict1 }};
what are the other things im missing. Could you please provide a detailed explanation on this. I had been trying this for 2 days.
Is there a way in which I can pass the value from django views to the javascript directly bypassing the django template?
Can I pass the information from django views to the html template and then to the javascript?
The javascript I am referring to is a simple javascript not jquery.
Thanks for your support,
Vinay
You cannot pass values to javascript bypassing the template, unless you use an ajax call to start a separate request or unless you do something very unusual like embedding the data in a response header (don't actually do this, it is not what response headers are for!). The response, which includes the header and the body (the body being the part generated by the template) is the sum total of the information your application provides to your client, so unless you generate an additional request and fetch an additional response with ajax, you have no other options.
If you don't want to do that, then your options for passing information to the javascript via the template are basically the following:
Using an inline tag, create properly formatted javascript dynamically via the templating system. The example line you have, var value_from_django = {{ dict1 }}; is essentially what I'm talking about here, except that I'm not sure you can pass a dict through from django to javascript like that, because django's text output of a dict in the template is unlikely to be exactly the correct formatting for a javascript variable declaration. So, instead you can...
Translate your data into JSON and put that into your template, and then process that with the javascript. (This is usually done with an ajax call, but there's nothing stopping you from injecting the JSON data into the initial template directly.)
Or populate your HTML with the data you want and then use javascript to locate the HTML tag containing the data and parse the data out.
If you are trying to pass simple variables like integers, it might be easiest to do it with the first or third options. If you are trying to pass a more complex data structure like a dictionary, you will probably be better off using JSON (that's what it's for!)
I would like to give you more detailed and concrete instructions, but for that you will need to post more detail about what exactly is going wrong with your current approach and what your desired functionality is.
By the way: if it is at all feasible to include jquery on this page and use that instead of trying to use basic javascript, you should do so. It will make your life much, much easier.

identical views different URLs

I have following routs:
url(r'^future/programs/$', main.programs, {'period': 'future'}),
url(r'^past/programs/$', main.programs, {'period': 'past'}),
When I try to display link in template, using template tag url like this
{% url main.views.main.programs %}
I always get link /past/programs/. When I try like this
{% url main.views.main.programs period="future" %}
I get an error:
Caught NoReverseMatch while rendering: Reverse for
'main.views.main.programs' with arguments '()' and keyword arguments
'{'period': u'future'}' not found.
How i can display link to /future/programs/?
I think you might want to approach it with one single url pattern:
url(r'^(?P(<period>[\w]+)/programs/$', main.views.programs),
and in your view:
def programs(request, period):
if period == 'future':
...
elif period == 'past':
...
and in templates:
{% url main.views.main.programs period="future" %}
In your approach, you are mistaking the forward flow with the reverse flow, i.e. the extra keyword arguments of the url conf with the keyword arguments that are passed to match a pattern.
The former is extra data you are allowed to pass to a view when it is matched (i.e. when a user goes to /future/programs/, the pattern is matched and period=future is passed to the view), the latter is the actual data used to match the url (i.e. the period=future is passed to the reverse() function which tries to match a pattern that excepts those keyword arguments - which you haven't outlined)
Edit:
A more appropriate pattern to use in your url would be something like:
url(r'^(?P(<period>past|future)/programs/$', main.views.programs),
where the selection could only be 'past' or 'future'. This is fine for incoming urls, but django's reverse() function (which is used in the url template tag) can't handle alternative choices:
https://docs.djangoproject.com/en/dev/topics/http/urls/#reverse
The main restriction at the moment is that the pattern cannot contain alternative choices using the vertical bar ("|") character.
I would rather assign each url a name:
url(r'^future/programs/$', main.programs,
{'period': 'future'},
name='future_programs'),
url(r'^past/programs/$', main.programs,
{'period': 'past'},
name='past_programs'),
And to display the link in your template:
Past programs: {% url past_programs %}
Future programs: {% url future_programs %}
I think this solution is better because if you just have two options for that view, you can forget about passing parameters and validating them.
Now, if those two options (future, past) can grow into several more, the other solution would be better, but I think this is not the case.

Django Generic object_list pagination. Adding instead of replacing arguments

I'm having some trouble with the django generic object_list function's pagination not really being "smart" enough to compensate my daftness.
I'm trying to do a url for listing with optional arguments for page number and category.
The url in urls.py looks like this:
url(r'^all/(?:(?P<category>[-\w]+)/page-(?P<urlpage>\d+))?/$',
views.listing,
),
The category and urlpage arguments are optional beacuse of the extra "(?: )?" around them and that works nicely.
views.listing is a wrapper function looking like this( i don't think this is where my problem occurs):
def listing(request,category="a-z",urlpage="1"):
extra_context_dict={}
if category=="a-z":
catqueryset=models.UserProfile.objects.all().order_by('user__username')
elif category=="z-a":
catqueryset=models.UserProfile.objects.all().order_by(-'user__username')
else:
extra_context_dict['error_message']='Unfortunately a sorting error occurred, content is listed in alphabetical order'
catqueryset=models.UserProfile.objects.all().order_by('user__username')
return object_list(
request,
queryset=catqueryset,
template_name='userlist.html',
page=urlpage,
paginate_by=10,
extra_context=extra_context_dict,
)
In my template userlist.html I have links looking like this (This is where I think the real problem lies):
{%if has_next%}
<a href=page-{{next}}>Next Page> ({{next}})</a>
{%else%}
Instead of replacing the page argument in my url the link adds another page argument to the url. The urls ends up looking like this "/all/a-z/page-1/page-2/
It's not really surprising that this is what happens, but not having page as an optional argument actually works and Django replaces the old page-part of the url.
I would prefer this DRYer (atleast I think so) solution, but can't seem to get it working.
Any tips how this could be solved with better urls.py or template tags would be very appreciated.
(also please excuse non-native english and on the fly translated code. Any feedback as to if this is a good or unwarranted Stack-overflow question is also gladly taken)
You're using relative URLs here - so it's not really anything to do with Django. You could replace your link with:
Next Page> ({{ next }})
and all would be well, except for the fact that you'd have a brittle link in your template, which would break as soon as you changed your urls.py, and it wouldn't work unless category happened to be a-z.
Instead, use Django's built-in url tag.
Next Page> ({{ next }})
To make that work, you'll have to pass your category into the extra_context_dict, which you create on the first line of your view code:
extra_context_dict = { 'category': category }
Is /all/a-z/page-1/page-2/ what appears in the source or where the link takes you to? My guess is that the string "page-2" is appended by the browser to the current URL. You should start with a URL with / in order to state a full path.
You should probably add the category into the extra_context and do:
next page ({{next}})
"Instead of replacing the page argument in my url the link adds another page argument to the url. The urls ends up looking like this "/all/a-z/page-1/page-2/"
that is because
'<a href=page-{{next}}>Next Page> ({{next}})</a>'
links to the page relative to the current url and the current url is already having /page-1/ in it.
i'm not sure how, not having page as an optional argument actually works and Django replaces the old page-part of the url
one thing i suggest is instead of defining relative url define absolute url
'Next Page> ({{ next }})'

Django url and request GET in template

I am using "url" tag in my template and everything works fine, except I cant capture anything thats behind it. Since I have multiple filters on that page, that are kept via GET request in the url, I need to be able to apend them to it. What happens is, that when I select one filter url will change to some/url/?f=1, then when I select another filter previous filter will get overriden, since the url is just some/url without request.
Here is a piece from urls.py:
url('^products/$', products_list, name = 'products_list'),
Is there anyway to modify it so the url tag will capture the GET request? Or do I need to create a filter which will add it there?
Any help is appreciated
Regards
There is no way to generate a query string using the url tag. If you need to add a query string to the output then do it manually, e.g. {% url foo bar %}?var={{ val|urlencode }}.

View referenced by two urls and url tag

I am using url tag in my template for a view, that is used by two different urls. I am getting the wrong url in one place. Is there any way to force django to retrieve different url? Why it doesn't notify my, that such conflict occured and it doesn't know what to do (since python zen says, that is should refuse temptation to guess).
Code in template:
{% url djangoldap.views.FilterEntriesResponse Entry=entry.path as filter_url %}
Code in urls:
(r'^filter_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'filter_entries.html',
'results_template': 'filter_results.html'}),
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'}),
As you can see, those two urls use the same view, but with different templates. How I can force django to retrieve former url, rather than latter?
Name your URLs by adding another item to the tuple:
(r'^choose_entries/(?P<Entry>.*)/$',
'djangoldap.views.FilterEntriesResponse',
{'filter_template': 'search_entries.html',
'results_template': 'search_results.html'},
'sensibleprefix-choose_entries') # <-- this is the name
Then you can use the name in the URL tag.