I am creating a website and already finished the frontend. Now I want to handle a form submit post request using python. I am trying to do this using django, but I can't figure out how I would
attach CSS classes, onchange eventhandlers and IDs to the django forms
insert divs and other html elements in between the django input elements within a single form
This is my current frontend:
<form method="post" autocomplete="off">
<p class="sub-header">Or just leave Us a Message:</p>
<div>
<div id="contact-layout">
<div class="input-container">
<input type="text" name="name" placeholder="Name">
<div class="input-bar"></div>
</div>
<div class="input-container">
<input type="text" name="email" placeholder="Email">
<div class="input-bar"></div>
</div>
<div class="input-container">
<input type="text" name="subject" placeholder="Subject">
<div class="input-bar"></div>
</div>
</div>
<div class="input-container">
<textarea name="message" placeholder="Type your message here..." id="message-input"></textarea>
<div class="input-bar"></div>
</div>
</div>
<div>
<p class="sub-header" id="user-image-header">Attach some images:</p>
<div id="file-upload">
<span class="form-button">Choose Files</span>
<input id="upload" type="file" onchange="LoadImage(this)" name="image" accept="image/*" multiple>
</div>
</div>
<div class="delimiter"></div>
<input class="form-button" type="submit" id="contact-submit" value="Submit">
<p id="submit-thanks">Thanks for submitting!</p>
as you can see I have a few "normal" html text inputs, a text area and an input for multiple image files.
In django I linked my static css files and setup my html frontend as a django template.
My django form looks like this so far:
class ContactForm(forms.Form):
name = forms.CharField()
email = forms.CharField()
phone = forms.CharField(required=False)
subject = forms.CharField(required=False)
message = forms.CharField(widget=forms.Textarea)
When I insert it into my frontend, It obviously doesn't look that good, as I have no Idea how I would represent my rather complex form design using django.
Could you point out how you would do this or maybe link a few good guides on how to approach something like this?
Also if possible provide some code examples :)
FYI I am familiar with python but I have never used django before, so maybe I am missing something obvious as for me it seem kind of overwhelming in it's complexity as a framework.
A good starting point is to familiarize yourself with what a default Django form generates. Here, for example, I was finding out for myself about the CheckboxSelectMultiple widget:
>>> class ZForm( forms.Form):
... foo = forms.MultipleChoiceField( choices=(('A','AA'),('B','BB'), ('C','CC')), widget=forms.CheckboxSelectMultiple )
...
>>> z = ZForm()
>>> z.as_p()
'<p><label>Foo:</label> <ul id="id_foo">\n <li><label for="id_foo_0"><input type="checkbox" name="foo" value="A" id="id_foo_0" />\n AA</label>\n\n</li>\n <li><label for="id_foo_1"><input type="checkbox" name="foo" value="B" id="id_foo_1" />\n BB</label>\n\n</li>\n <li><label for="id_foo_2"><input type="checkbox" name="foo" value="C" id="id_foo_2" />\n CC</label>\n\n</li>\n</ul></p>'
>>>
If you want to style it with css, the css ids generated by Django make it fairly. straightforward to describe any elements with css locators.If you don't want the default Django layouts, you can generate the form field-by-field in your template, or you can learn about django-crispy-forms (especially, layout helpers) which I wholeheartedly recommend.
As for where to inject css into Django, there are various ways, but a common one is through a block called something like css in your base template. The view template will look something like
{% extends "base.html" %}
{% block content %}
<!-- code to render your form -->
...
{ %endblock content %}
{% block css %}
/* base.html provides the surrounding style tags */
/* block.super inherits the css common to all pages using base.html */
{{block.super}}
/* additional styling for the form rendered in block content */
#id_foo label {
/* styling for labels on the foo field only */
whatever;
}
{% endblock css %}
In passing my own base.html also always loads Jquery (unsurprisingly in a block called scripts so I can per-template-override or augment should I need to) and has a block onready_js that gets rendered in this context, which saves an awful lot of easily-mistyped boilerplate around what can be a trivial Jquery snippet
<script type="text/javascript"> $(document).ready( function() {
{% block onready_js %}{% endblock onready_js %}
});
</script>
and you just put any per-template Jquery you need to be executed when the view is invoked into that block.
You can develop frontend and backend seperately in django. You can create a form on frontend and style it and handle it on your backend as
def my_route_handler(request):
if request.method == 'POST':
form = MyForm(request.POST)
if form.is_valid():
# do your processing
# return
There is no need to embed the django form in frontend.
Related
I am using wtforms as part of a Python + Flask project. There are some cases where I want multiple fields of a form to appear on the same line on the webpage. With SelectField, this works as expected. However, when I use IntegerField, it seems to automatically create a new line after the field is displayed, and I get have more than one on a line.
The Form:
class PremiumMandatory(FlaskForm):
match_dol = IntegerField('Dollar')
match_per = IntegerField('Percent')
The .html
{{form.match_dol.label}}
${{form.match_dol(size=3)}}
 
{{form.match_per(size=3)}}%
{% for error in form.match_per.errors %}
Using the above, the two fields also appear on different lines on the webpage. Ho do I keep then on the same line?
This is an entirely HTML/CSS problem. There are many ways to put multiple fields of a form on the same line, for example, you could use Bootstrap's grid system, which is very easy to use.
Another simple way is:
<form>
<div style="display: table;">
<div style="display: table-row;">
<div style="display: table-cell;">
{{ form.match_dol.label }}
{{ form.match_dol(size=3) }}
</div>
<div style="display: table-cell;">
{{ form.match_per.label }}
{{ form.match_per(size=3) }}
</div>
</div>
<div style="display: table-row;">
...
</div>
</div>
</form>
I'm trying to make a website using django which I'm not familiar with. Not know what django forms do I wrote my html file purely in html and now I'm having difficulty trying to save uploaded files because django won't let me save them manually. I tried to bypass this with no luck, so I think that now I have to rewrite my html file in django html template, so I can save files. I have an html file like this:
html
<div class="w3-container w3-white">
<select class="w3-select" name="request_function" id="request_function" >
<option id="faces_embedding" value="faces_embedding" style="" onclick="pagechange()">faces_embedding</option>
<!-- <option id="faces_model" value="faces_model" style="" onclick="pagechange()"> faces_model </option> -->
<option id="image_recognizer"value="image_recognizer" style="" onclick="pagechange()">image_recognizer</option>
<option id="video_recognizer" value="video_recognizer" style="" onclick="pagechange()">video_recognizer</option>
<option id="stream_recognition" value="stream_recognition" style="" onclick="pagechange()">stream_recognizer</option>
<option id="help" value="help" style="" onclick="pagechange()">help</option>
</select>
</div>
<div id="AddFaces" style="visibility: visible; display: block;">
<div class="w3-row-padding" style="margin:0 -16px;" >
<div class="w3-half">
<input type="radio" name="input_method" id="input_method_0" onclick="datachange()" checked value="input_method_0">
<label>Add A Database</label>
</div>
<div class="w3-half">
<input type="radio" name="input_method" id=input_method_1" onclick="datachange()" value="input_method_1">
<label>Add A Face</label>
</div>
</div>
<div class="w3-row-padding" style="margin:0px -10px;">
<div id="dataset" class="w3-half w3-margin-bottom" style="visibility: visible; display: block;">
<label>Dataset Path</label>
<input class="w3-input w3-border" type="text" placeholder="directory path" name="dataset_path" id="dataset_path" required >
</div>
<div id="face" style="visibility: hidden; display: none;">
<div class="w3-half w3-margin-bottom">
<label>Images Path</label>
<input type="file" id="face_files" name="face_files" multiple >
</div>
<div class="w3-half">
<label>Name</label>
<input class="w3-input w3-border" type="text" placeholder="person name" name="face_name" id="face_name" >
</div>
</div>
</div>
</div>
where "datachange()" is a javascript function that hides different dives that I don't need
and my view.py
if request.method == "GET":
return render(request, 'index.html')
if request.method == "POST":
form = InputForm(request)
call_form_function(form)
return render(request, 'index.html')
where "InputForm.py" is a normal python class which takes forms id tags and use them as input for functions.
def __init__(self, request):
self.request_function = request.POST.get("request_function")
self.input_method = request.POST.get('input_method')
self.dataset_path = request.POST.get('dataset_path')
self.face_files = request.FILES.getlist['face_files']
self.face_name = request.POST.get('face_name')
from django documents, I used the this function:
def handle_uploaded_file(f):
with open('some/file/name.txt', 'wb+') as destination:
for chunk in f.chunks():
destination.write(chunk)
But django automatically close the file before I can write anything.
QUESTION:
So my question is that do I have to use django froms to save upload files? Is there a way to bypass this? and If there is no way to do so how can I change my html file in a way that is still looks the same in the webpage and my javascripts work with django templates.
p.s: I also don't have a database, models.py since I don't have a use for them.
Well, if you don't use forms and don't use database, why are you using Django :) As with all modern web frameworks that use MVC (Mode, View, Controller) or in Django case MTV (Model, Template, View) you will sooner or later need all three of those.
Model defines your database schema, Template defines html templates - what users will see, and View is actually where programming logic lives.
If the template has forms, you will need to define form in Django. It actually simplifies life a lot and it can be very simple definition if you use models. And information on your files (metadata) that someone can upload should be stored in a model (database). That will ease your handling of files quite a lot.
But in the end it really depends what is your application doing?
So, I did some benchmarks to see how many requests the app could handle. It turns out that when a database operation is involved, no more than 500-560 requests/sec can be handled before timing out subsequent requests, whereas without the database layer it easily comes to a whopping 1000-1100 requests/sec.
I still didn't manage to cut the db costs in most of the pages (and I'm working on it), but there's one where this overhead can be cut: the edit page.
I have the following view which is executed when you visit http://website.com/edit. What it does is get the id parameter in the url and find the post from the db (MongoDB) with it, which then pass the iterated output to the template:
def edit(id):
item = mongo.db.documents.find_one({'_id': id})
doc = item.iteritems()
return render_template('edit.html',
content=item[0],
title=item[3],
url=item[2],
id=post[1]
)
This code is executed when you click edit in the item page, which is made like this:
{% block body %}
{{ title }}
<p>{{ content }}</p>
<div>
<a href=delete>Delete</a>
<a href=edit>Edit</a>
</div>
<form method="post" action="/post">
<input type="hidden" name="id" value="{{ id }}" />
<input type="hidden" name="url" value="{{ url }}" />
<input type="hidden" name="title" value="{{ title }}" />
<input type="hidden" name="content" value="{{ content }}" />
<div>
<h5>Your Name :</h5>
<input type="text" name="name" id="add_comment_author" />
</div>
<div>
<h5>Your Thought :</h5>
<textarea name="content id="add_comment_content"></textarea>
</div>
<input type="submit" value="Send" />
</form>
{% endblock %}
As you can see there are already hidden inputs with the needed value, but they're used for the comments.
Is it possible to do something like this?:
def edit(id):
#item = mongo.db.documents.find_one({'_id': id})
#doc = item.iteritems()
doc = request.get.previous()
return render_template('edit.html',
content=doc[0],
title=doc[3],
url=doc[2],
id=doc[1]
)
Alternatively would it be possible to have two POST in one page (one for sending a comment, the other for sending the values to the edit page?
Or maybe use Flash? But I suspect that's highly suboptimal and prone to bugs.
Typical solution is to use a caching layer like Flask-Cache and a memcached server to cache recently accessed data.
Having an edit form in the page is good. You can have as many forms as you want. Btw the common approach is to have only some sort of "templated" forms hidden that you'll then fill using jQuery os similar JS libraries.
In your example you're also passing the content field as hidden. Why? One might modify your source and change the content. :)
I am trying to render data into a template file using the following Code. The error I encounter is something like :
This page contains the following errors:
error on line 13 at column 16: AttValue: " or ' expected
Below is a rendering of the page up to the first error.
Name,Author,Status
Code
def editbook(request):
if request.method == 'GET':
name = request.GET.get('name',False)
Details = bookInfo.objects.all().filter(Name=name)
id = Details.values_list('id',flat=True)
Name = Details.values_list('Name',flat=True)
Author = Details.values_list('Author',flat=True)
Status = Details.values_list('Status',flat=True)
return render(request, 'app/add.html', {'Name' : Name, 'Author' : Author, 'Status' : Status}, content_type="application/xhtml+xml")
Template Code
<html>
<head>
<title>Add</title>
</head>
<body>
<form action="add/" method="post">
{% csrf_token %}
<p style="font-family:Courier New;color:teal">Name <input type="text" placeholder="Name of the book" name="name"></input></p>
<p style="font-family:Courier New;color:teal">Author <input type="text" placeholder="Author of the book" name="author"></input></p>
<p style="font-family:Courier New; color:teal"> Status
<select name="status">
<option value=1>Read</option>
<option value=1>Unread</option>
</select>
</p>
<input type="submit" id="booksubmit" value="Add/Edit Book"></input>
</form>
</body>
</html>
I searched through Google and I found that this somewhat like XML parsing error (Please correct me if I am wrong). Now I am stuck at this position. Please help.
EDIT Here the form for adding the book has a different method for saving the field data into database.
Your HTML is malformed for whatever type is is, html and html5.
And to be picky, your python code should be refactored as well.
Normally we define variables with lowercase letter instead of a capital so
the variables Details, Name, Author, Status should be details, name, author, status.
Further more, is your class name bookInfo spelled like that?
Classes in python should start with a capital letter so bookInfo should be BookInfo.
The proper HTML5 is this:
<html>
<head>
<title>Add</title>
</head>
<body>
<form action="add/" method="post">
{% csrf_token %}
<p style="font-family:Courier New;color:teal;">Name <input type="text" placeholder="Name of the book" name="name" /></p>
<p style="font-family:Courier New;color:teal;">Author <input type="text" placeholder="Author of the book" name="author" /></p>
<p style="font-family:Courier New; color:teal;"> Status
<select name="status">
<option value=1>Read</option>
<option value=1>Unread</option>
</select>
</p>
<input type="submit" id="booksubmit" value="Add/Edit Book" />
</form>
</body>
</html>
If you're not using HTML5 and that depends on the Doctype you've defined.
You can't use placeholders in your input fields.
The inputs need to get closed with a /> and not a </input>.
The inline styles you've provided in your html is incomplete:
style="font-family:Courier New; color:teal"
should be
style="font-family:Courier New; color:teal;"
The return you're using doesn't need a content_type you can drop that.
You're not using your template variables anywhere so that's not it but if you would like to start using them the syntax for the template language is {{ variable_name }} and in your case that would be (until you refactor)
{{ Name }}, {{ Status }} for example.
Also you're seeing this error because of the content_type since you're actively telling the browser to parse the document as xhtml+xml and that's XHTML with rules, which you're effectively breaking.
For adding the value from your Django app to your input fields do this, (without a Django Form)
<input type="text" value="{{ Name }}" />
But I would recommend using a Django Form instead.
I think you're getting this error because you're template is not 'well formed'. My guess is that there's an error in the xml that's being output.
You've declared the content type of your http response to be application/xhtml+xml. xhtml requires you to put quotes around all your attributes. You're probably missing/adding a quotation mark somewhere. I can't see from your template where that is.
Either check what your template variables ({{ Name }}, {{ Author }} and {{ Status }}) are outputting to see if they're adding in a stray quotation mark, or try changing the content type (maybe just drop the content_type parameter you're passing to the render function).
I'm shifting an application from cgi to web.py. I want to use the web.form. However I've noticed that it creates a table on its own. Is it possible to style the created table (width, height, etc...)??? If yes, how???
The table is the result of form rendering, so naturally it’s placed within a form element. In my case it looks like this in the login.html template:
<form name="main" method="post" class="login">
$if not form.valid:
<p class="wrong">Login incorrect.</p>
$:form.render()
</form>
In the browser, when rendered, the form looks like this:
<form name="main" method="post" class="login">
<table>
<tr><th><label for="login">login</label></th><td><input type="text" id="login" name="login"/></td></tr>
<tr><th><label for="password">password</label></th><td><input type="password" id="password" name="password"/></td></tr>
<tr><th><label for="Login"></label></th><td><button id="Login" name="Login">Login</button></td></tr>
</table>
</form>
So you can apply arbitrary styling, including positioning, to this table using the following CSS:
form.login table { /* your styling */ }