Call Django on HTML button click - html

I'm trying to make a basic sort function for a Django project, but I don't know how to call the sort function when I click the 'sort' button
Django view:
def sort_btn(request):
if request.GET.get('sort-btn'):
cits = Citizen.objects.all().order_by('name')
return render_to_response(request, 'civil_reg/index.html', {'cits': cits})
HTML button:
<button name="sort-btn" id="sort-btn">sort</button>

you need to wrap your <button> with <form> tag, as following snippet:
<form action='actionUrl' method='GET'>
<button type='submit'> sort me</button>
</form>
and in your urls.py module you should point the actionUrl with specific view from the views.py module as follow:
from django.urls import path
from . import views
urlpatterns = [
path(actionUrl, views.yourSort),
]
you should more read about request lifecycle on Django:
user submit request
Django tries to get the first match between request's URL and routes defined in urls.py
the request is passed to the matched view
the view get executed, usually this some model processing
a response (template) is returned by the view as HttpResponse

I don't know about your program but my implementation is the full as it is that worked.
<button name="button" type="submit" onclick="location.href='{% url "actionUrl" %}'"> Send</button>
I am trying to call a function in views named "sendEmail"
path('actionUrl/', views.sendEmail,name='actionUrl')
And above one is the line which I included in urls file.

Related

Django forms. Make ChoiceField required on frontend <select>

I have created a Django form, which uses a ChoiceField:
control_model = forms.ChoiceField(choices=(), required=True)
(The reason 'choices' are empty is because they are set using a function based on my backend database)
The following is the entire form:
class CreateWorkflowForm(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(CreateWorkflowForm, self).__init__(*args, **kwargs)
self.request = kwargs.pop("request")
self.fields['control_model'].choices = my_function()
control_model = forms.ChoiceField(choices=(), required=True)
class Meta:
model = CreateWorkflowModel
fields = ['control_model']
The model used looks the following:
class CreateWorkflowModel(models.Model):
control_model = models.CharField(max_length=100)
I use this form in a Django template the following way:
<div class="form-content">
{{ form.media }}
{{ form.as_p }}
<input type="submit" id="id_submit" value="Submit" />
</div>
However on my webpage the <select> that corresponds to my ChoiceField doesn't have the attribute 'required':
This means that my form will fail if no value is input into the ChoiceField (because its required in the form) However I would much prefer if a popup box appeared on frontend stating "You need to enter a value on this field".
I know having the "required" value on the <select> would do this exact thing, however I don't know how to make django generate the <select> with this attribute.
If you need required attribute on your select, you must have first chose element with empty value, otherwise it's invalid HTML.
See source code of the widget

How to call view function via button from template in Django?

I've searched some of the related questions and I couldn't figure out how to do it. That is why I am posting a new question here.
I have a base.html file and there is a button which should run a function from views.py file. Here is the button code:
<form role="form" action="" method="POST">
{% csrf_token %}
<input type="submit" class="btn" value="Click" name="mybtn">
</form>
And here is my function from views.py file:
def create_new_product(request):
if request.method == 'POST':
'''Execute the code here'''
return render (request, 'products/base.html')
And in my Products' urls.py file:
app_name = 'products'
urlpatterns = [
path('create-new-product/', views.create_new_product),
path('', views.IndexView.as_view(), name='base'),
path('<int:pk>/', views.DetailView.as_view(), name='detail'),
]
Normally I have an IndexView class in views.py file which lists all the current products and what I expect from the above function is that it will generate new products and new products will also be listed in 'products' page.
The above function is not inside the IndexView class by the way.
You will stay on the same page with action="#"
Try instead action="" so you will stay on the same page but reloaded.
Update:
Read your comment.
The name argument is useful to call your url in Django template like :
path('create-new-product/', views.create_new_product, name='create_new_product')
The app_name = 'products' is very important. It tells Django where to check your path. So you can call your view everywhere in your project by:
...
<form action="{% url 'products:create_new_product' %}">...</form>
you can either use browser fetch api or jquery ajax to implement search functionality
include a js script to your template file
include this js snippet
$(elementSelector).on("click", async (e) => {
const fetchOptions = {}
const response = await fetch(YOUR_URL, {...fetchOptions});
const responseUrl = response.url // see fetch api docs
window.location = responseUrl // if you want to redirect
)

Differentiate form actions in GCDWebServer?

I am using two forms on an HTML page hosted via GCDWebServer. I have the first form setup like this...
<form name=\"vendorInput\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">
<input type=submit value='Add Vendor' action=\"/\">
and the second form setup like this...
<form name=\"vendorInput\" method=\"post\" enctype=\"application/x-www-form-urlencoded\">
<input type=submit value='Add Item' action=\"/\">
I can't find any documentation that provides support for this; and any action string I type other than / causes the HTML request to break. Is there a way to parse different actions for form submit buttons in GCDWebServer?
You just need to have the action be a different path for each form and then implement a GCDWebServer handler for each path:
[webServer addHandlerForMethod:#"POST"
path:#"/path1"
requestClass:[GCDWebServerURLEncodedFormRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
// Do something with form data i.e. [[(GCDWebServerURLEncodedFormRequest*)request arguments]
return [GCDWebServerDataResponse responseWithHTML:#"<html><body>OK</body></html>"];
}];
[webServer addHandlerForMethod:#"POST"
path:#"/path2"
requestClass:[GCDWebServerURLEncodedFormRequest class]
processBlock:^GCDWebServerResponse *(GCDWebServerRequest* request) {
// Do something with form data i.e. [[(GCDWebServerURLEncodedFormRequest*)request arguments]
return [GCDWebServerDataResponse responseWithHTML:#"<html><body>OK</body></html>"];
}];
See https://github.com/swisspol/GCDWebServer#advanced-example-2-implementing-forms for an example.

Sequential Forms in web.py

I am trying to write a web interface to start a recording or playback process. I am using web.py and have one controlling python script (code.py) and three templates (main.html, record.html and playback.html) in a templates directory. The main page shows a form for playback and a form for recording, each with a button, which loads the relevant template with entered data when pressed. I would like to be able to cancel these processes and return to the main screen, so I have a form containing a 'Cancel' button which is rendered in both the record and playback templates. However, when I press this button. nothing happens. Any ideas would be appreciated.
code.py:
import web
from web import form
import os
import glob
import socket
render = web.template.render('templates/',
globals={'os':os, 'glob':glob, 'form':form})
urls = ('/*', 'index')
recordForm = form.Form(
form.Dropdown(name = 'rmode',
description='Recording Mode:',
args=<a list of tupels>),
form.Button('Record'),
)
os.chdir("/home/stingray/Documents/")
playbackForm = form.Form(
form.Dropdown(name='pmode',
description='Playback Mode:',
args=<a list of tupels>),
form.Dropdown(name='pfile',
description='Playback File:',
args=[(file,file) for file in glob.glob("*.*")]),
form.Button('Playback'),
)
cancelForm = form.Form(
form.Button('Cancel'),
)
class index:
def GET(self):
r = recordForm()
p = playbackForm()
return render.main(socket.gethostbyname(socket.gethostname()),
'Not Present',r,p)
def POST(self):
formData = web.input()
c = cancelForm()
try:
return render.record(formData.rmode,c)
except AttributeError:
return render.playback(formData.pmode,formData.pfile,c)
if __name__ == "__main__":
app = web.application(urls, globals())
app.run()
main.html
$def with (ipAddress,linkStatus,recordForm,playbackForm)
<html>
<title>
Test Bridge Control - Main
</title>
<body>
<center>
<b>Test Bridge Control</b><br><br>
<form method="POST">
$:recordForm.render()
</form>
<br>
<form method="POST">
$:playbackForm.render()
</form>
<br>
Test bridge IP address: $ipAddress<br>
Link status: $linkStatus<br>
</center>
</body>
</html>
record.html
$def with (mode,cancelForm)
<html>
<title>
Test Bridge Control - Record
</title>
<body>
<center>
Recording in mode $mode <br>
<form method="POST">
$:cancelForm.render()
</form>
</center>
</body>
</html>
And playback.html is very similar to record.html. Note that even though I'm not validating the form data, I can still access it - form entries appear in the rendered record.html and playback.html.
[EDIT] Should probably emphasize that searches for similar issues haven't been successful; no-one else seems to be trying to use multiple forms one after the other (or if they are, they're succeeding).
[EDIT] Doesn't appear to be a problem in Firefox 18 running in Fedora, originally seen in IE9 in Windows 7, which is probably what it will have to work in.
Turns out it was an IE problem. Apparently IE9 does not treat buttons as being of type "submit" unless explicitly stated. Bizarrely the buttons in main did work as submit then stopped. All are now working after adding type="submit" to the button's declaration.

How to display a date attribute of an object as the default value in HTML date input type

Hi I am trying to implement a editing page that accept the id of an object and load all its original value && enable editing/updateing.
e.g
for text type ,I use
<label>Field1:</label>
<input type="text" id="id_field1" value='{{ objectInstance.filed1}}' name="field1"/>
for Textares
<label>Field2:</label>
<textarea id="id_field2" name="field2">
{{ objectInstance.field2}}
They both worked fine in loading original data of the instance and allowing editing. But for the date field, I cannot find out how to load it..
I am trying something like
<label>Deadline:</label>
<input type="date" id="id_deadline" name="deadline" value={{objectInstance.deadline}}>
(the deadline is of date data type e.g 2013-6-4)
Can anyone help solving this problem? Thanks very much.
You can use the UpdateView generic class based view to simplify this process. A similar question was answered before.
The other way to fix this is to use a ModelForm, and pre-load it with an instance. This is actually what UpdateView does, but if you don't want to use class based views, here is the alternative:
In your forms.py:
from django import forms
from someapp.models import SomeModel
class SomeModelForm(forms.ModelForm):
class Meta:
model = SomeModel
In your views.py:
def someview(request):
obj = SomeModel.objects.get(pk=1) # Fetch the object to be edited
form = SomeModelForm(instance=obj) # Load the form with the object's data
return render(request, 'edit.html', {'form': form})
In edit.html:
<form method="POST">
{% csrf_token $}
{{ form }}
<input type="submit">
</form>
This will automatically create the form, fill it in with the data from the model. You would still have to write the logic to update the record in your view.