How to limit form submit request in Django app - django

I want to limit submitting request for visitors(anonymous) in my django app.
Suppose 10 or 50 limits per day/month. If they try to search more than my given limit I want to show a message "you have reached your daily or monthly limit!"
How can I do this?
Here is views:
def homeview(request):
if request.method == "POST" and 'text1' in request.POST:
text1 = request.POST.get('text1')
text2 = request.POST.get('text2')
data = my_custom_function(text1, text2)
context = {'data': data}
else:
context = {}
return render(request, 'home.html', context)
here is form in template:
<form action="" method="POST">
{% csrf_token %}
<input class="form-control m-3 w-50 mx-auto" type="text" name="text1" id="text1" placeholder="">
<input class="form-control m-3 w-50 mx-auto" type="text" name="text2" id="text2" placeholder="">
<input class="btn btn-primary btn-lg my-3" type="submit" value="Submit">
</form>

You can use throttling from the Django REST framework. But there is no throttle rate for a month out of the box. Maybe you can use https://stackoverflow.com/a/50371440/4151233 to create a specific class.
Otherwise, I recommend writing your own implementation. This should be adapted to the requirements with questions such as:
Are my users authenticated when making the requests?
How fast should it be and how much load is expected?
Is a standard DB query acceptable or does it need to be implemented
with the cache framework?

Related

how to cancel form w/o validation in django + bootstrap4

Hi i am using django + bootstrap4 to render forms. I have 'submit' and 'cancel' buttons on the forms. i am using ModelForm with Validators assigned to most of the form attributes.
template file
<form action="{% url 'actor-create' %}" method="post" class="w-25 mx-auto">
{% csrf_token %}
{% bootstrap_form form layout="horizontal" %}
<button class="btn btn-primary" type="submit"><i class="fas fa-plus"></i> Save</button>
<button class="btn btn-primary" type="submit"><i class="fas fa-times"></i> Cancel</button>
</form>
in the view
def actor_create(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
print(request.POST)
if "cancel" in request.POST:
return HttpResponseRedirect('/')
..... rest of the code
When cancel button is pressed validation of the form attributes prevents the form from submitting. so view functionality never gets executed.
I want to know how to avoid validation when form is cancelled?
Following Q&A has a JavaScript based solution, I preferably don't want to write such code for every form in my website.
How to cancel form submission?
as suggested by Iain Shelvington making it a 'a' worked for me!
<i class="fas fa-times"></i> Cancel

Django why request.method=='GET' when refreshing the page

I want to have some search boxes on my page and my related codes are like below, my problem is why when i refresh the page the if clause: " if request.method=='GET':" executes without i click on any button ?
def allstocks_view(request):
if request.method=='GET':
question_set =Stocks.objects.all().filter(confirm=_('approved') )
name=request.GET.get('namesearch')
number=request.GET.get('numbersearch')
brand=request.GET.get('brandsearch')
if name is not None :
question_set = question_set.filter(name__icontains = name)
if number is not None :
question_set = question_set.filter(number__icontains = number)
if request.GET.get("brandsearch"):
question_set = question_set.filter(brand__icontains = brand)
print(">>>>>>>>>>>>>>>>>>>>")
print(question_set)
template :
<form method="get">
{% csrf_token %}
<div class="">
<label for="namesearch">Name</label>
<input type="text" name="namesearch" >
<label for="numbersearch"> Number</label>
<input type="text" name="numbersearch" >
<label for="brandsearch"> Brand</label>
<input type="text" name="brandsearch" >
<label for="brandsearch"> City</label>
<input type="text" name="citysearch" >
<input type="submit" name="search" value="Search">
</div>
</form>
A refresh of a page is a GET request unless your last action was a POST request so that is going to execute every time. What you could do is make the form a post and handle in a request.method == 'POST' block. Another option if you wanted to continute with GET would be have your view take an optional parameter such as search=None and set up your urls accordingly. Then in your view you could check for if search exists instead of request.method == 'GET'.

access form data in view

I hava a form in my template which is for search.I did not made any form class to it. Is it possible to have access form data in view or should I make a form class to it.
<form class="navbar-form" role="search" action="{% url 'my_url_name' %}" method="get">
<div class="input-group add-on">
<input class="form-control" placeholder="search" name="srch-term" id="srch-term" type="text">
<div class="input-group-btn">
<button class="btn btn-default" type="submit"><i class="glyphicon glyphicon-search"></i></button>
</div>
</div>
</form>
I use this form for its style and I can not make this style with Form class
You can access form data in the request.GET (or request.POST if it is a post request) dictionary in your view. For example:
srch_term = request.GET.get('srch-term')
You can by using the QueryDict object you get with the request :
def myview(request):
if request.method == "POST":
data = request.POST
print(data['foo']) # <--Will print the value I entered into my form.
[...]
But be careful with this : There is no validation tool to ensure the data you receive is correctly formated.

save form data from pure html to datastore

I have a simple form
<form name="input" action="" method="get">
Username: <input type="text" name="user" id = "xxx">
<input type="submit" value="Submit">
</form>
On view.py I want to write a function to get value that user input
def add(request):
if request.method =="POST":
abc=request.args.get('xxx')
return render_to_response('myapp/addtour.html')
But it does not work. Please tell me how to do it in Google App Engine or Django
1: You're checking for POST while your form uses GET -- the if block will never fire.
2: xxx is an HTML ID - it has nothing to do with GET/POST. The name parameter does. So request.GET.get('user') - not 'xxx'

Django template nt displaying in drop down box and view is showing error

you can view full source code here dpaste.com/hold/167199
Error:
delete() takes exactly 2 arguments (1 given)
Copied from linked code:
index.html
............................................
<form method="POST" action="/customer/(?P<name>[a-z]*)/delete/">
<div style="float: right;
margin: 0px; padding: 05px; ">
<label for="id_customer">Customer:</label>
<select name="customer" id="id_customer">
<option value="" selected="selected">---------</option>
<option value="{{ customer.customer_name|escape }}"></option>
</select>
<input type="submit" value="delete">
</div>
</form>
......................................
Urls.py
(r'^customer/(?P<name>[a-z]*)/delete/', 'quote.excel.views.delete')
Views.py
def delete(request, name):
if request.method == "POST":
Customer.objects.get(name=name).delete()
This is how, i am using it.First,select should display the values presented in db into drop down box but it is rendering dd box,values are empty.
In views,i get 2 params needed only 1 given and problemwith urls.py is 404.
You are mixing the usage of GET and POST requests. You have to do the following:
Either use GET requests, then you have to change your template this way:
<form method="GET" action="/customer/{{customer.customer_name}}/delete/">
<input type="submit" value="delete">
</form>
The name must be part of the URL, because you have set up your urls.py this way. I don't recommend this way, as everybody can just type the URL customer/foo/delete into the address bar to delete customer foo.
The other way is to use post. Therefore you have to change your URL pattern and the view:
(r'^customer/delete/', 'quote.excel.views.delete')
def delete(request):
if request.method == "POST":
name = request.POST.get('customer', False)
if name:
Customer.objects.get(name=name).delete()
But as it seems that you can only delete one customer, there is no need to create a select input element as it only contains one value.
Update:
To make this for all customers, you have to get all of them in your view, e.g. in a variable customers and pass this to the template. In the template, you iterate over all of them:
<form method="POST" action="/customer/delete/">
<label for="id_customer">Customer:</label>
<select name="customer" id="id_customer">
<option value="" selected="selected">---------</option>
{% for customer in customers %}
<option value="{{ customer.customer_name|escape }}">{{ customer.customer_name|escape }}</option>
{% endfor %}
</select>
<input type="submit" value="delete">
</form>
As for the part Django template nt displaying in drop down box I don't know what you mean with it, maybe you can clarify what you want.