how to send url parameter in POST request without form - django

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.

Related

CSRF-attack using Django

I'm working on a Django project and I can make a CSRF-attack from an external url or file. How I can block it?
The attack consist:
I create a file with this content:
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://XXXXXX.com/YYYYY/AAAAAA/LLLLLL">
<input type="submit" value="Submit request" />
</form>
</body>
</html>
I login on my page
I open the file in the same browser
Submit the button
The request is accepted and the action is executed.
Thanks for everything :)
Solved
django.middleware.csrf.CsrfViewMiddleware does not provide csrf protection if the request is GET
# Assume that anything not defined as 'safe' by RFC7231 needs protection
if request.method not in ('GET', 'HEAD', 'OPTIONS', 'TRACE'):
if getattr(request, '_dont_enforce_csrf_checks', False):
# Mechanism to turn off CSRF checks for test suite.
# It comes after the creation of CSRF cookies, so that
# everything else continues to work exactly the same
# (e.g. cookies are sent, etc.), but before any
# branches that call reject().
return self._accept(request)
Change your method to post and add csrf token
<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="https://XXXXXX.com/YYYYY/AAAAAA/LLLLLL" method="post">
{% csrf_token %}
<input type="submit" value="Submit request" />
</form>
</body>
</html>
and handle your view inside :
if request.method == 'POST':
# your logic here
Make sure that 'django.middleware.csrf.CsrfViewMiddleware' should come before any view middleware that assume that CSRF attacks have been dealt with.

Intermediate Django 2.0 admin action page not displaying

I have created an update custom admin action and want to ask for update confirmation by going to a new page before the update action is finalised.
Below is the code for various files:
admin.py`
class ProfileHolderAdmin(admin.ModelAdmin):
list_display = [field.attname for field in ProfileHolder._meta.fields]
actions = ['update_verified']
def update_verified(self, request, querySet):
users_verified=querySet.update(verified='y')
views.update_confirmation(request)
self.message_user(request,"No. of users verified = %s" %str(users_verified))
update_verified.short_description = "Mark selected users as verified"
admin.site.register(ProfileHolder, ProfileHolderAdmin)`
Code in views.py:
def update_confirmation(request):
return render(request,'Profile/confirm_update.html', context=None)
Code in confirm_update.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Confirm Update</title>
</head>
<body>
<form action="admin.py" method="post">
<p>
Are you sure you want to update the verification status of selected users?
</p>
<input type="hidden" name="action" value="update_status" />
<input type="submit" name="apply" value="Update status"/>
</form>
</body>
</html>
The path to the html file is:
website_name\Profile\templates\Profile\confirm_update.html
Profile is the name of my app and website_name is the directory name.
When I carry out the update function, the status is being correctly updated but the intermediate update page is not showing.
Please help.
Your admin action currently returns None which means the admin will take care of redirecting back to the normal change list page.
In order to render the page you need to return the response you get from update_confirmation. Of course you first want to render the page and then run the queryset update. For that you need to find a way to tell the two calls apart (e.g. by adding a POST parameter confirmed).
def update_verified(self, request, querySet):
if request.POST.get('confirmed') is None:
return views.update_confirmation(request)
users_verified=querySet.update(verified='y')
self.message_user(request,"No. of users verified = %s" %str(users_verified))

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']

pass variable through url to view

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?