pass variable through url to view - django

I want to pass my input text value through url when i click my submit button.
views.py
def profile(request,username):
current_user = User.objects.filter(username=username)
return render_to_response ('profiles/search.html', {'current_user':current_user,
context_instance=RequestContext(request),)
search.html
<form action="{%url 'profiles:profile' username=user.username %}" id="search_by_username" method ="get">
<input type="text" name = "searchname" class="text" placeholder="Search by username" />
<input type="submit" value="button" />
</form>
urls.py
url(r'^view/(?P<username>\w+)/$', views.profile, name="profile"),
after clicking the submit button ,Iam getting a url like this:
192.168.1.33:8000/profiles/view/abraham/?searchname=merlin
Here abraham is the loggin user but actually i need to search for merlin.So how can i replace abraham by merlin.

You can't get a form field to automatically put its value into the URL the form is submitting to (except by mucking about with the form in Javascript, which would be horrible).
But as you can see, you do get that data in the request parameters: since you're doing a GET, it's in request.GET['searchname']. So why don't you drop the username parameter to the URL/view in the first place, and just use that?

Related

'ManagementForm data is missing or has been tampered with' when submitting a form via XHR

I want a user to be able to select from an existing list of options. If the option is not within the ones already in the database, though, they need to be able to add a new item, while remaining on the main form, because after having added the new item they need to be able to save the main form
I was using the JQuery library select2, which allows a tags:True option, thanks to which users can add a new item to a list if not present. Nevertheless, Django validates that field and if it finds an item which is not in the database is raises an error. My initial plan was that of capturing the new value in the view and then (saving first the form with commit=False), if it was not in the database, save it. But this is not doable without forcing Django not to validate the field, which I haven't managed to do.
Another option, which I'm currently investigating, is that of adding a modal pop-up containing the sub-form. Of course I'd like to avoid opening the sub-form in another page, which would work but would be quite non-user-friendly.
models.py:
class Venue(models.Model):
venue_name = models.CharField(max_length=30)
class performanceOfCompositionNoDb(models.Model):
venue = models.ForeignKey(Venue, on_delete=models.SET_NULL, null=True, blank=True)
forms.py:
class VenueForm(forms.ModelForm):
class Meta:
model = Venue
fields = ['venue_name']
views.py:
def composition_edit_view(request, id=id):
form_composition = CompositionForm(request.POST or None, instance=obj)
form_venue = VenueForm(request.POST or None)
if request.method == "POST" and form_composition.is_valid():
form_composition.save()
context = {
'form_composition': form_composition,
'form_venue': form_venue
[...]
def venue_add_view(request):
form_venue = VenueForm(request.POST or None)
if form_venue.is_valid():
form_venue.save()
context = {
'form_venue': form_venue,
}
return render(request, "venue-add.html", context)
my template.html:
{% include '../venue-add.html'%}
<form id="compositionForm" action='.' enctype="multipart/form-data" method='POST'>
{{form_composition}}
<p>Add new venue</p>
<input class="button" type='submit' id='save' value='Save' />
</form>
venue-add.html:
<div class="reveal" id="addvenueModal" data-reveal>
<form action='.' enctype="multipart/form-data" method='POST'>
{% csrf_token %}
<div class="grid-container">
<div class="grid-x grid-padding-x">
{{ form_venue }}
</div>
<input class="button" type='submit' value='Save' />
</div>
</form>
</div>
I'm expecting to open the venue-add form when I click on the 'Add new venue' button, which happens. With the modal open and the new text input, I then click the 'submit' button of the modal. At that point I get a 'Validation error - ['ManagementForm data is missing or has been tampered with']'. I have other formsets in the main template, and it all works correctly if I don't add a new venue.
How can I solve this? Also, if there's a way of using the select2 library and add a new venue in a more dynamic way, do let me know! Thanks.
Testing with XHR
Using XHR gives the same ['ManagementForm data is missing or has been tampered with'] error in the response:
<div class="reveal" id="addVenue" data-reveal>
<form id="addVenueForm" action='.' onsubmit="addVenue(this); return false;" enctype="multipart/form-data" method='POST'>
{% csrf_token %}
<div class="grid-container">
<div class="grid-x grid-padding-x">
{{ form_venue }}
</div>
<input class="button" type='submit' value='Save' />
</div>
</form>
<script type="text/javascript"> "use strict";
function addVenue (oFormElement) {
var oReq = new XMLHttpRequest();
var data = new FormData(oFormElement)
oReq.onload = {}
oReq.onreadystatechange = function() {
if (oReq.readyState == XMLHttpRequest.DONE) {
var result = oReq.responseText;}
}
oReq.open("post", oFormElement.action, true);
oReq.send(data);
} </script>
As I said, I do have formsets (working correctly) in the main form from which I'm launching this modal. This modal doesn't contain any formset though, it's a simple one-field form, with its own csrf token.
Edit 2
OK, so upon further investigating I've found that the error springs from
return render(request, "compositions/composition_edit.html", context)
in the view.py. In other words, when I hit 'submit' in the modal, for some reason the 'submit' of the main form kicks in also, thus generating issues. How can I isolate the 'submit' of the modal and get the 'submit' of the main form not to kick in unless explicitly clicked?
I had to change the action of the modal form to the address I mapped in my urls.py (action='/venue-add/') for that form. That solved the issue.
Now, the newly-added items are not displayed in the main form unless I refresh the page, no matter ho many times I destroy/empty/repopulate the select2() dropdown list. I think this has to do with the fact that the data to the venue dropdown list is sent by the view at the loading of the main form, and that the context remains the same no matter what updates to the database have been made after the page loading.
For the above reason I'm investigating using an API on my own application and GET and POST data via an AJAX call, which still gives me issue. I'm opening another question for that though.

Custom `password_reset_confirm.html` template won't redirect to `password_reset_complete` view

I made a custom password_reset_confirm.html template. But when a user enters a new password and hits submit, the browser does not redirect to the admin view password_reset_complete.
Here's the form I made in the custom password_reset_confirm.html template:
<div ng-app="app" ng-controller="Ctrl">
<form id="reset-pw-confirm-form" name="newPWForm" method="post" action="">
{% csrf_token %}
<input
id="id_new_password1"
type="[[[ newPW.showPW ? 'text' : 'password' ]]]"
name="new_password1"
ng-model="newPW.pw"
ng-minlength="8"
ng-maxlength="32"
required>
<button class="btn btn-primary" type="submit" ng-disabled="!newPW.pw">Submit</button>
<input
id="id_new_password2"
type="hidden"
value="[[[ newPW ]]]"
name="new_password2"
ng-model="newPW"
ng-minlength="8"
ng-maxlength="32"
required>
</form>
</div>
When I fill out the password and hit submit, the browser sends a POST request to the same URL it landed on, but the page seems to just refresh with nothing changed. The user's password remains unchanged. It seems Django's auth/views.py did not execute properly.
In that view, there's this code:
if post_reset_redirect is None:
post_reset_redirect = reverse('password_reset_complete')
else:
post_reset_redirect = resolve_url(post_reset_redirect)
When I have the view print post_reset_redirect, it prints None. Could this be the issue?
How can I make my custom template compatible with Django's password_reset_confirm view?
When you specifies "action" attribute for the form it will be used as your link for data sending so probably your logic isn't handled. Try to remove it and check you js files that the data is sent to the the specified link.
Also please check all required parameters for the password_reset_confirm
https://docs.djangoproject.com/en/1.8/_modules/django/contrib/auth/views/
My hidden input's value and ng-model attributes needed to be set to newPW.pw.

How to send data from django template to views method in post request or in a way data is not visible in the URL

I have a django template which has multiple <a> tags.
<a class="label label-success" href="get_status/?token={{book.token}}">Update</a>
On click of it, a method from views is called where I can access the token from the url as
tkn = request.GET.get('token')
But now I want not to send the token in the url.
I searched for this and get to know about forms but I did not clearly understand them. Can anyone please help here.
For future ref: I created a form and added a hidden input field in it.
on click of submit button it will send the token value.
<form action="get_Status/" method="post">
{% csrf_token %}
{{ form }}
<input type="hidden" name="book_token" value="{{book.token}}">
<input type="submit" class="submit_btn btn label-success" value="Update" />
</form>
Ans in the views.py
book_token=request.POST.get("book_token"," ")
You can use the basic HTML form concept here.
Please check the link:
How to submit a form with JavaScript by clicking a link?
Use javascript/Jquery to submit the form.
Insert the token value in a hidden field and use form to submit it to views.
Then in the views,you can get the value as :request.POST['token']

Django: passing form input to the url

In django, I'm having problems passing the number that was inputed into a form to an URL:
I try like this:
templates->index.html
<form action="/mysite/{{ number }}/details.html" method="post">
<p><label for="number">Give me a number:</label>
<input type="text" name="number" id="number" /></p> <input type="submit" value="Submit" />
but the result is /mysite//details.html, instead of /mysite/123/details.html (when the user inputs 123 in the requested form)
Can you please give me an advise?
Thanks,
JJ
You shouldn't be configuring your action url in this manner. And the user POST-ed number 123 is passed in to your view function as request.POST['number'] without you specifying it in the action url.
Your action url can simply be {% url 'send_details' %} corresponding to a url definition that is
url(r'^mysite/details/$',
'send_details',
name='send_details'),
And your send_details view function will receive request.POST['number'] when the user submits it.
There's no necessity to have the number in your template as a context variable.

how to send url parameter in POST request without form

I have to pass a parameter in url. I can't send it in as usual GET request the variable and value is shown in the address bar with the request. So, the end user can change the value for this variable value and send request which will be processed.
href="url=/admin/usermanagement/?flag=2
I want to send this hiding flag=2
now this goes as a GET request and it is seen in the address bar. Please give your suggestion if you have any idea on changing this to POST to hide and send the value.
You can still use a html form but "hide" it from the user:
<!DOCTYPE html>
<html>
<body>
<form id="myform" method="post" action="/">
{% csrf_token %}
<input type="hidden" name="flag" value="2" />
Let's go!
</form>
</body>
</html>
And the view:
def index(request):
if request.method == 'POST':
try:
flag = request.POST['flag']
# TODO use flag
except KeyError:
print 'Where is my flag?'
return render_to_response('index.html', {},
context_instance=RequestContext(request))
You can use AJAX to get rid of forms entirely.
Just add this to your JavaScript:
function postTo(url, query) {
var request = (XMLHttpRequest?new XMLHttpRequest():new ActiveXObject());
request.open('POST', url, true);
request.send(query);
}
Then call with something like this:
postTo('/admin/usermanagement/','flag=2');
Note that this will NOT reload the page. If you want to reload the page, use Borges' answer.