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

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.

Related

How Do I Properly Submit Two Forms Within One HTML Structure?

I am trying to submit a create view with two forms. The code below works fine if everything is filled out and the form submitted. However if fields are omitted in form2...the form submission fails and the field that was filled out for "form"..."name"....gets reset. I've read you can do multiple forms and I've largely got this working...I just need to figure out how to incorporate form2 into the if_valid().... Here's my view...
def tasklist_detail_view(request, id):
context = {}
context["tasklist"] = TaskList.objects.get(id=id)
context["tasks"] = Task.objects.filter(task_list=id).all()
obj = get_object_or_404(TaskList, id=id)
form = UpdateTaskListForm(request.POST or None, instance=obj)
form2 = TaskForm(request.POST or None)
context["task_list_id"] = id
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
context["form"] = form
context["form2"] = form2
return render(request, "my_task_list_tasklist_detail.html", context)
My HTML...
<form method="POST" enctype="multipart/form-data" id="forms">
{% csrf_token %}
{{ form.name }}
{% include "my_task_list_task_create_form1.html" with tasklist=tasklist %}
<button type="submit" class="button66" name="status" value="Submitted">Submit</button>
</form>
And then in my include HTML...
<div id="task-list-form" hx-target="this" hx-swap="outerHTML">
<button class="button35" hx-post="{% url 'MyTaskLists:task-create' id=task_list_id %}">Save</button>
{{ form2 }}
I did try to do something like....
if form.is_valid() and form2.is_valid():
form.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
But then nothing happens...the forms are not accepted at all even if the fields are filled out properly....From what I've read I understand the POST is being applied to both forms....if one is not filled out properly that is why the other errors out? I just can't quite figure out how to process them both properly.
Thanks in advance for any thoughts.
If you want the two forms to behave like one form, and save two objects only if both forms are valid, then the logic is
if form.is_valid() and form2.is_valid():
form.save()
form2.save()
return HttpResponseRedirect(reverse("MyTaskLists:my_task_list_main_menu"))
context["form"] = form
context["form2"] = form2
return render(request, "my_task_list_tasklist_detail.html", context)
If there is any field with the same name in form and form2 you need to use a prefix to remove the ambiguity.
form = UpdateTaskListForm(request.POST or None, instance=obj, prefix='form1')
form2 = TaskForm(request.POST or None, prefix='form2')

getting get method when running post method

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.

Using django Authentication form with the html form

I am trying to build a login module in django. I already have a nice HTML form for login which has username and password field.
But in my views.py I have imported default Django AuthenticationForm, but if integrate it with my nice-looking HTML form, there will be two forms. How can I import the Authentication form and use it with the my HTML form??
My code is here:
My view:
def login(request):
if request.method == 'POST':
form = AuthenticationForm(data=request.POST)
if form.is_valid():
user = form.get_user()
authlog(request, user)
return redirect('home')
else:
messages.error(request, 'Invalid username or password')
# back_page = request.META.get('HTTP_REFERER')
return redirect('login')
# return HttpResponse(back_page)
else:
content = {
'form': AuthenticationForm()
}
return render(request, 'sign-in.html', content)
If I use Django default form, the code will be following, but it won't look good as my other Html login page.
My sign-in html:
<hr>
<form action="" method="post">
{% csrf_token %}
{{form|crispy}}
<button type="submit" class=" btn btn-success ">Sign-Up</button>
</form>
I haven't posted my other HTML form though as it is very large. Hope it explains.

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>