getting get method when running post method - json

I created class based view where In get method I am calling html page activate.html. and created post method where I posting some json data. I want to redirect same page and want to post data.
When I am running activate.html page I get it but when I click on button for activate user Its printing same which I print in get method
views.py
class ActivationView(View):
def get (self, request, uid, token):
print('get called in activate_user')
return render(request, 'activate.html')
def post(self, request, uid, token):
print('UID : ', uid)
print('Token : ', token)
payload = json.dumps({'uid': uid, 'token': token})
print("payload : " , payload)
protocol = 'https://' if request.is_secure() else 'http://'
web_url = protocol + request.get_host()
djoser_url = getattr(settings, 'DJOSER.ACTIVATION_URL')
post_url = web_url + djoser_url
print('post_url : ' + post_url)
response = request.post(post_url, data = payload)
return HttpResponse(response.text)
I want to print uid and token in json format when I click on post button from html.
activate.html
<form action="" method="post">
{% csrf_token %}
<td input type="submit"><a href="" target="_blank" >Click Here For Activate Account</a></td>
</form>

change your form
<form action="" method="post">
{% csrf_token %}
<td ><button type="submit">Click Here For Activate Account</button></td>
</form>
this will works.

Related

django: html form submit without jumping into new page or refreshing/reloading

I am new to django and html. below is my first test web page of a simple online calculator.
I found a problem that when clicking the "submit" button, it tends to jump to a new web page or a new web tab. this is not what I want. Once the user input the data and click "submit" button, I want the "result" field on the page directly show the result (i.e. partially update only this field) without refresh/jump to the new page. Also I want the user input data kept in the same page after clicking "submit".
I saw there might be several different ways to do this work, iframe/AJAX. Since I am new, what is the really simplest way to achieve this goal? BTW, I dont write javascripts.
html:
<form method="POST">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div>{{ result }}</div>
<button type="submit">Submit</button>
</form>
view.py
def post_list(request):
result = 0
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
print(request.POST)
print(result)
context = {
'result': result
}
return render(request, 'blog/post_list.html', context)
This is a simple example of using Ajax, which I hope will be useful to you.
first you need change post_list view:
view
from django.http import JsonResponse
def post_list(request):
if request.method == "POST":
num1 = request.POST.get('num_1')
num2 = request.POST.get('num_2')
result = int(num1) + int(num2)
return JsonResponse({"result":result})
else:
return render(request, 'blog/post_list.html', context={"result":0})
I use JsonResponse because I just want to get the result data in ajax and display it in the html , for GET request render the html file and for POST request use JsonResponse to return a json like context.
And your html file should to be a look like this:
html
<script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
<form method="POST" id="post-form">
{% csrf_token %}
<div>
<label>num_1:</label>
<input type="text" name="num_1" value="1" placeholder="Enter value" />
</div>
<div>
<label>num_2:</label>
<input type="text" name="num_2" value="2" placeholder="Enter value" />
</div>
<br />
<div id="result" >{{ result }}</div>
<button type="submit" >Submit</button>
</form>
<script>
$(document).ready(
$('#post-form').submit(function(e){
e.preventDefault();
var serializedData = $(this).serialize();
$.ajax({
type:"POST",
url: "/your_url/",
data: serializedData,
success: function(data){
$("#result").text(data["result"]);
}
});
})
);
</script>
First I added jQuery cdn and then your html file, except that I added attribute id=post-form to the form and added id=result, then <script> tag was added and jquery function inside the tag was execute when your form Submited(detect event by the id #post-form).
And get the data(num_1, num_2) by serialize method then use Ajax to send POST reqeust to the view function(post_list), in Ajax you just need to pass serializedData and url(also you can use the Django url tag or set it in action form or...), After that we need to send data to the html(means the result data we received from the View).
in success function Ajax you can add html tag to your html file or
replace the some values,...
In Ajax, you must specify your URL to send the data.
for example if you have this url.py
urls.py
from .views import post_list
urlpatterns = [
path("posts_list/", post_list, name="post_list"),
]
In ajax you can add an address like this:
$.ajax({
type:"POST",
url: "/posts_list/",
....
Or
$.ajax({
type:"POST",
url: "{% url 'post_list' %}",
....
And if you have app_name in urls.py you can added url: "{% url 'app_name:post_list' %}",

The browsable API HTML renderer performs a POST despite the button is configured to send and showing DELETE request

I'm testing API CRUD with browsable web API flask implementation, but the browser seems to send unexpected requests to the API.
Here is the code I'm testing :
from flask import request, url_for
from flask_api import FlaskAPI, status, exceptions
app = FlaskAPI(__name__)
notes = {
0: 'do the shopping',
1: 'build the codez',
2: 'paint the door',
}
def note_repr(key):
return {
'url': request.host_url.rstrip('/') + url_for('notes_detail', key=key),
'text': notes[key]
}
#app.route("/", methods=['GET', 'POST'])
def notes_list():
"""
List or create notes.
"""
if request.method == 'POST':
note = str(request.data.get('text', ''))
idx = max(notes.keys()) + 1
notes[idx] = note
return note_repr(idx), status.HTTP_201_CREATED
# request.method == 'GET'
return [note_repr(idx) for idx in sorted(notes.keys())]
#app.route("/<int:key>/", methods=['GET', 'PUT', 'DELETE'])
def notes_detail(key):
"""
Retrieve, update or delete note instances.
"""
if request.method == 'PUT':
note = str(request.data.get('text', ''))
notes[key] = note
return note_repr(key)
elif request.method == 'DELETE':
notes.pop(key, None)
return '', status.HTTP_204_NO_CONTENT
# request.method == 'GET'
if key not in notes:
raise exceptions.NotFound()
return note_repr(key)
if __name__ == "__main__":
app.run(host='0.0.0.0', debug=True)
When I tried to delete a specific note given its id (key) from the example notes list, the browser sends a POST method instead of DELETE, which is not supported by the route.
The base render template is located here where you can see DELETE button statement at line 104.
I edited the library code and move the form method there from POST to DELETE thinking it could solve the problem this way :
104 {% if 'DELETE' in allowed_methods %}
105 <form class="button-form" action="{{ request.url }}" method="DELETE" class="pull-right">
106 <!-- csrf_token -->
107 <input type="hidden" name="_method" value="DELETE" />
108 <button class="btn btn-danger js-tooltip" title="Make a DELETE request on the resource">DELETE</button>
109 </form>
110 {% endif %}
But not, the browser is now sending a GET request with the query string _method=DELETE, instead of DELETE request/method.
Everything is OK when sending request to the API using curl
Can one of you guys with good flask html rendering skills check this out and test on its side?
Never seen form with method=DELETE. MDN documentation says it should be either a GET or POST. Also see this old stackoverflow question that also says it is not supported in forms.
The template you're referencing is for an API so it seems to me that they are supporting direct calls to the API (such as with curl or Postman which would support PUT, DELETE, etc) and calls via forms (which would only be GET or POST)
You should keep your original code where method = POST and add POST as a method for def notes_detail i.e. you should have
#app.route("/<int:key>/", methods=['GET', 'POST', 'PUT', 'DELETE'])
def notes_detail(key):
I abandoned the effort of making the browser sending DELETE requests, and dealed with form hiden inputs, keeping POST as the form's method
104 {% if 'DELETE' in allowed_methods %}
105 <form class="button-form" action="{{ request.url }}" method="POST" class="pull-right">
106 <!-- csrf_token -->
107 <input type="hidden" name="_method" value="DELETE" />
108 <button class="btn btn-danger js-tooltip" title="Make a DELETE request on the resource">DELETE</button>
109 </form>
110 {% endif %}

Django HTML Send POST data to url as PK value when submitting

I have a form that's just a date field and submit button
Forms.py
from django import forms
from datetime import date
class DateInput(forms.DateInput):
input_type = 'date'
class HomeForm(forms.Form):
EnterDate = forms.DateField(widget=DateInput, initial=date.today())
Because of a user request, I just want to send the data to the url like this
home/2021-07-01
so I tried to do this for my html form, just stick the form.EnterDate.value in the form Action part, but it only works on the 2nd try.
<form method="POST" class="form-inline my-2 my-lg-0" action="{% url 'mint-post' form.EnterDate.value %}">
{% csrf_token %}
<label for="{{form.EnterDate.id_for_label}}">Enter Date</label>
{{form.EnterDate}}
<button class="btn btn-primary my-2 my-sm-0" type="submit">Submit Date</button>
#Inital loading the form
def mintHome(request):
form = HomeForm()
context = {
'form': form }
return render(request, 'mintyHome.html', context)
#after Post
def mintHomePost(request, pk):
if request.method =='POST':
form = HomeForm(request.POST)
if form.is_valid():
datePost = form.cleaned_data['EnterDate']
stringDate = datePost.strftime("%Y%m%d")
context = {
'form': form }
return render(request, 'mintyHome.html', context)
I made an example here:
https://alisayt.pythonanywhere.com/minty/home
It sends the form.EnterDate.value only in the 2nd submit, but not the first one.
Do you want the POST request to be sent to a URL based on the current date? Or to a URL based on the user input?
The template code {% url 'mint-post' form.EnterDate.value %} is only executed once on the server when you request the page, not when you change the date input and submit the POST request.
If you would like the action URL to change with the user input, this has to happen on the client side, i. e. using JavaScript.

Django ajax post method dont redirect

im following a tuto on how ajax work on Django, its my first time with ajax and im facing a little problem ,the data insertion is working but the success ajax dont redirect corectly, and thank you for the help
this the code
views.py :
class exo(View):
def get(self, request):
form = ExerciseForm()
tasks = task.objects.all()
context = {
'form': form,
'tasks': tasks
}
return render(request, 'coach/test.html',
context=context)
def post(self, request):
form = ExerciseForm()
if request.method == 'POST':
form = ExerciseForm(request.POST)
print(form)
if form.is_valid():
print('adding task', form)
new_exrercise = form.save()
return JsonResponse({'task': model_to_dict(new_exrercise)}, status=200 )
else:
print('not adding task')
return redirect('exo')
ajax function :
$(document).ready(function(){
$("#addExercise").click(function() {
var serializedData = $("#TaskForm").serialize();
$.ajax({
url: $("TaskForm").data('url'),
data : serializedData,
type: 'post',
success: function(response) {
$("#taskList").append('<div
class="card"><div class="card-body">'+ response.task.name
+'<button type="button" class="close float-right"> <span
aria-hidden="true">×</span></button></div></div>');
}
})
});
});
html content :
<form class="submit-form" method="post" id="TaskForm"
data-url="{% url 'session' %}">
{% csrf_token %}
<div class="form-group">
{% for field in form %}
<div style="margin-bottom: 2rem;"></div>
{{field}}
{% endfor %}
<div style="margin-bottom: 2rem;"></div>
<button type="submit" class="btn btn-success dropdown-toggle " id="addExercise">Confirm</button>
</div>
</form>
this is what i get (i get an object and nothing else )
output image
when i comeback to the page exo the insertion is done
and the console show me that the post is sending well :
[21/Dec/2020 22:25:38] "POST /coach/exo/ HTTP/1.1" 200 43
The problem is that your button:
<button type="submit" class="btn btn-success dropdown-toggle " id="addExercise">Confirm</button>
will submit the form, and not (only) by the AJAX call, but simply by the fact that you made it a submit button. This thus means that the browser will encode the form and make a POST request with that form, and then the browser will render the response.
You thus should remove the type="submit" part from the button:
<button class="btn btn-success dropdown-toggle " id="addExercise">Confirm</button>
I remove the submit type and nothing was working , the button wasnt posting anything to ajax then i switch my view class into a function and it work i really dont know why there is the view
def addsession(request):
template = loader.get_template('coach/addexercise.html')
exercises = exercise.objects.all()
# context = {'exercises': exercises}
UpperBody = exercise.objects.filter(category__name="Upper Body")
LowerBody = exercise.objects.filter(category__name="Lower Body")
FIIT = exercise.objects.filter(category__name="FIIT")
LIIT = exercise.objects.filter(category__name="LIIT")
form = ExerciseForm()
tasks = task.objects.all()
context = {'exercises': exercises,
'UpperBody': UpperBody,
'LowerBody': LowerBody,
'FIIT': FIIT,
'LIIT': LIIT,
'form': form,
'tasks': tasks
}
form = ExerciseForm()
if request.method == 'POST':
form = ExerciseForm(request.POST)
print(form)
if form.is_valid():
print('adding task', form)
new_exrercise = form.save()
return JsonResponse({'task': model_to_dict(new_exrercise)}, status=200 )
else:
print('not adding task')
return redirect('session')
return render(request, 'coach/addexercise.html', context=context)
and thank u guys for your answers i really didnt give attention to the input type of button

How to render a field request without refreshing the page?

I have a form with a few fields, the first being where a person enters their ID #, which is tied to a separate model for verification. I made this function get_employee_name, which returns the name based on the ID from the other model, but I'm not sure how to display it in the page, right on the top, without refreshing after the person tabs/clicks out? I'm not too familiar with html, but I was reading an ajax GET request would do the trick, but I'm not sure how to approach this.
This is basically so the person knows that the ID # they entered matches their name before proceeding to fill the rest out.
views.py
class EnterExitArea(CreateView):
model = EmployeeWorkAreaLog
template_name = "enter_exit_area.html"
form_class = WarehouseForm
def form_valid(self, form):
emp_num = form.cleaned_data['adp_number']
area = form.cleaned_data['work_area']
station = form.cleaned_data['station_number']
if 'enter_area' in self.request.POST:
form.save()
return HttpResponseRedirect(self.request.path_info)
elif 'leave_area' in self.request.POST:
form.save()
EmployeeWorkAreaLog.objects.filter(adp_number=emp_num, work_area=area, station_number=station).update(time_out=datetime.now())
return HttpResponseRedirect(self.request.path_info)
def get_employee_name(request):
adp_number = request.POST.get('adp_number')
employee = Salesman.objects.get(adp_number=adp_number)
employee_name = employee.slsmn_name
return employee_name
models.py
class EmployeeWorkAreaLog(TimeStampedModel, SoftDeleteModel, models.Model):
employee_name = models.CharField(max_length=25)
adp_number = models.ForeignKey(Salesman, on_delete=models.SET_NULL, help_text="Employee #", null=True, blank=False) #(max_length=50, help_text="Employee #", blank=False)
...
def __str__(self):
return self.adp_number
forms.py
class WarehouseForm(AppsModelForm):
class Meta:
model = EmployeeWorkAreaLog
widgets = {
'adp_number': ForeignKeyRawIdWidget(EmployeeWorkAreaLog._meta.get_field('adp_number').remote_field, site),
}
fields = ('adp_number', 'work_area', 'station_number')
enter_exit_area.html
{% extends "base.html" %}
{% block main %}
<form id="warehouseForm" action="" method="POST" data-stations-url="{% url 'operations:ajax_load_stations' %}" novalidate >
{% csrf_token %}
<div>
<div>
{{ form.adp_number.help_text }}
{{ form.adp_number }}
</div>
<div>
{{ form.work_area.help_text }}
{{ form.work_area }}
</div>
<div>
{{ form.station_number.help_text }}
{{ form.station_number }}
</div>
</div>
<div>
<div>
<button type="submit" name="enter_area" value="Enter">Enter Area</button>
<button type="submit" name="leave_area" value="Leave">Leave Area</button>
</div>
</div>
</form>
{% endblock main %}
We'll use ajax, with jQuery so be sure you have jQuery before you read.
first, you've to create an endpoint to GET, go to urls.py & add an endpoint say
path('/myserver/getID/', views.get_employee_name, name="whatever")
now, this calls get_employee_name right? Let's now call it in JS without refreshing.
here's the basic syntax ->
$.ajax({THIS IS A SIMPLE DICT})
ajax takes parameters
type which is the request type
url which is the request URL which we just made above (not the full url, you're specifying the endpoint from where you're located on the website so you just use /myserver/getID/)
it also takes data which is a dictionary with your posted data (yes a dictionary inside the bigger ajax dictionary
it CAN take success which is a function to call after getting the response with status 200 (success) and that success function can have the parameter response which is your response
it CAN take error which is a function that gets called after an error & takes error as argument
enough talking...
$.ajax({
url: 'myserver/getID',
type: 'GET',
data: // don't specify this, we're not posting any data,
success: function (response) {console.log(response.data)}, //this will be what returned from python
error: function (error){console.log(error)}
})
this is a simple ajax request
NOTE, if you return a redirect from python & accept it from ajax, it won't work, ajax can't redirect, be sure to remember that because most of the time people ask why redirect('mylink') doesn't work after I return it from ajax.
Another NOTE is the when dealing with post requests with ajax, you must include the csrf token which can be included by
csrfmiddlewaretoken: '{%csrf_token%}'
You can use Fetch API too if you want, or even normal XMLhttprequest.
Sounds like you have a few questions and should split them up but just to answer the main question in your title, "How to render a field request without refreshing the page?", this is how you do that part with some DOM manipulation. This is basic HTML and JavaScript you would need to fit into your project.
Once you get the name back from your lookup, you just need to insert the value into the DOM and that will render it, not requiring a refresh. Here's a simple example:
var clickMe = function() {
var element = document.getElementById('heading');
// Do your AJAX and lookup something...
element.textContent = "Name Lookup From Server Request";
}
<div>
<h1 id="heading"></h1>
<button onclick="clickMe()">Click Me</button>
</div>