Django -- pass "next" parameter to cancel button? - django

I know how to pass a next get parameter to a view so that when the view redirects, it goes to whatever url is in next. Is it possible to do this with the cancel button of a form?
If my form buttons are like this:
<input type="submit" value="Save Changes"><input type="button" value="Cancel Changes" onclick="window.location.href='/systems/'">
Is there some way to add the next parameter into the href instead of /systems/?
Thanks!

Well, this is just HTML in your template, so why can't you do
onclick="window.location.href='{{ myurl }}'">
?
Edit after comment
Sounds like you need a context processor, which automatically adds the value of the next GET parameter to the context. As simple as:
def get_next(request):
if 'next' in request.GET:
return {'next': request.GET['next']}
Now add this to the list of CONTEXT_PROCESSORS in settings.py, and make sure you use a RequestContext when rendering your template (or just the new render() shortcut).

Related

django request.POST.get different button name

HELLO,I have many buttons like:
<button name="A"></button>
<button name="B"></button>
<button name="C"></button>
When I click on a button, I want to get the corresponds name, then use it in my view to compare with some string.
request.POST.get how to get the value I need?
To be able to use request.POST.get you need to have the buttons wrapped in an HTML <form></form> and get the data using django forms

Django Crispy Forms - Add Button via Helper

I studied the Crispy-Forms documentation and I tried to put an extra button into one of my forms. With
self.helper.add_input(Button('back', "Back", css_class='btn'))
I can add a nice button. But the Button() wont take an onclick or on_click-attribute. So how can I add logic to this button? Adding an onclick event with JQuery isnt a very nice solution...
Thanks!
Ron
Are you certain that Button will not take onclick in its kwargs?
I just added an onclick="javascript here" to a Submit() element and it displayed fine.
I also peered a bit at the underlying code, and I think all inputs by default flatten the kwargs that aren't popped because of special use (i.e. template), and pass those through into the rendered HTML. This may be new since April '12 (when originally posted), but it currently seems to be as simple as the following:
self.helper.add_input(Button('back', "Back", css_class='btn', onclick="alert('Neat!');"))
This is not included by default (afaik..).
If you just need this once, is possible to use crispy-forms HTML Layout Object
HTML('<input type="button" name="Save" onclick="do_whatever" />')
What do you then dislike using jQuery? You could handle this rather easy and generic, using something like:
$('form :submit.ajax_submit').live('click', function(e) {
e.preventDefault();
var my_form = $(this).parents('form');
// do whatever
alert(my_form.attr('id'));
alert(my_form.attr('action'));
});
and then just pass the class:
Submit('save', 'save', css_class='ajax_submit')

Get the clicked submit button in a django form in a generic way

I have a finite state machine (django-fsm) which allows an object to go from a source state into one of several target states. I can add all the actions in a dictionary like:
ACTIONS { 'button_1': action1,
'button_2': action2,
...
}
This translates in a form with a submit button for each state.
{% for n,m in object.get_available_current_state_transitions %}
<input type="submit" class="btn" value="{{ n|get_action|capfirst }}"
name="button_{{n}}" />
{%endfor%}
<input type="submit" class="btn primary" value="Save">
<a class="btn" onclick="javascript:history.go(-1)">Cancel</a>
This usually results in more than 3 buttons.
Clicking a button results in a specific action, defined in my case in the model class.
Now, I know I can get the clicked button in the request.POST dictionary, but this would result in a cascade if like:
if 'button_1' in request.POST:
action_1()
elif 'button_2' in request.POST:
...
Is there any way to get the button pressed separately (ideally from the request object) in a variable so I can have something like
ACTIONS[clicked_button_name](...)
? In other words, is there any way to obtain the clicked button outside the POST dictionary?
PS: I've looked other replies on the "multiple buttons" question, but all offer request.POST as answer.
If all of the actions and strings are already in your view, why don't you just iterate over that actions dict?
for key, value in ACTIONS.items():
if key in request.POST:
value()
Just make your button names very unlikely to be used as a regular form field name.
A few alternatives: use javascript to handle the submission and have it set a single form field such as "action".
Use more unique keys and filter through request.POST.keys() with a regex pattern or string comparison.
action = [x for x in request.POST.keys() if 'FAIRLY_UNIQUE_BUTTON_PREFIX' in x]
if action:
ACTIONS[action]()
I don't think so directly, but a couple workarounds could be:
Send your buttons to different urlconfs with some variable (like a three letter arg). All of these confs point to the same view taking this three letter arg as an argument, which then knows what to do. This might still result in a cascade if else though.
Or, send them to different views all together.
You could try doing something ajaxy. The data will still be in a post dict, but you will have more control over how the post dict is structured.
I'm also assuming GET isn't an option for any of these (yet that still results in if else structures.)

How to get the previous URL in Django

I'll give the step by step info.
Let's say we're in the about page, the URL is example.com/about.
There's an email a friend button, when clicked, the URL is example.com/emailafriend.
Then when I clicked the submit button, the referal URL will be submitted is example.com/emailafriend. Question, how to get the about page URL? BTW, I'm using request.META['HTTP_REFERER'].
You could work with the request path attribute and add that to your form's action attribute, like so:
<form method="post" action="/tell-a-friend?return_url={{ request.path }}">
...
</form>
Then, in your tell-a-friend view, HttpResponseRedirect to the return_url query parameter.
It looks like maybe you are using APPEND_SLASH which will do a redirect if you don't have a slash. Try changing the button link to sample.com/emailafriend/, note the ending slash.
Maybe simply pass sample.com/about as GET or POST param? Or even through session.

Redirect to views according to form selection

User registration in my application is performed in steps. After submitting the form, some validation is performed and then register_prompt view is called. It renders a form, with two options - 'ok' and 'cancel'. Clicking ok will run registration, and clicking cancel should redirect to main page. Problem is that no matter which of the two I choose, I'm redirected to .../user/registration/function_1_or_2_name with a blank page (although I have specified url in HttpResponseRedirect ). How can I make it work ?
def register_prompt(request):
context = RequestContext(request)
return render_to_response('user/data_operations/alert.html', context_instance=context)
Form loaded on alert.html :
<form action="" method="post">
<input type="submit" class="submit" name="submit" onClick="this.form.action='{% url register_new %}'" value="Ok" />
<input type="submit" class="submit" name="submit" onClick="this.form.action='{% url redirect_home %}'" value="Cancel" />
</form>
Redirect views (maybe there is a better way to do that ?):
def redirect_home(request):
return HttpResponseRedirect('/')
def register_new(request):
(... registration magic here ...)
return HttpResponseRedirect('/user/registration/complete/')
Finally url conf :
url(r'^register_new/$', register_new, name="register_new"),
url(r'^redirect_home/$', redirect_home, name="redirect_home"),
url(r'^register_prompt/$', register_prompt, name="register_prompt"),
At first I was trying to add some abstract values to form's buttons (like 'action=ok'), and then catch them in register_prompt but it was a total disaster.
I'm not sure if that onClick="" hack is really valid (I'll let someone else weigh in on that), but did you try just using normal links, to see if it's that or something else?
OK
Cancel
(Or check out <button> if you really want it to look like buttons. Or just use two <form>s, each with a separate action="" attributes.)
Hum, other than that... You say ".../user/registration/function_1_or_2_name" -- what exactly does the {% url .. %}s give you? Does it not add the final / (which you require in your patterns)?
At first I was trying to add some
abstract values to form's buttons
(like 'action=ok'), and then catch
them in register_prompt but it was a
total disaster.
But you seem to want to manipulate the action attribute, so you can't catch anything in register_prompt()?
All in all I'd suggest you either use normal links, or actually handle the POST in the view that presented it:
def register_prompt(req):
if 'ok' in req.POST:
return register_new(req)
if 'cancel' in req.POST:
return register_cancel(req)
return render_to_response('user/data_operations/alert.html',
context_instance=RequestContext(req))
Maybe something like that? Renaming your buttons to ok and cancel, and having the form post back to itself...