Sequential Forms in web.py - html

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.

Related

How would I be able to send a Popup upon submitting a form when a user doesn't exist?

Im creating a login and signup system and upon logging in, if the user doesn't exist I want to return a popup message saying "Please signup first" and then an 'OK' button in the popup that when pressed will send the user back to main page 'index.html'. Also same thing when password entered is wrong.
here is login part of main.py:
#app.route("/login", methods = ['GET', 'POST'])
def login():
if request.method=='GET':
return render_template("login.html")
else:
email = request.form['email']
password = request.form ['password']
user = get_user(email)
if user != None:
if user.password == password:
return render_template("home.html")
else:
return render_template("index.html")
else:
return render_template ('index.html')
I tried using flash and it didn't work, the html part of login (login.html).
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="{{ url_for('static', filename='css/style.css') }}">
<title>DeBank</title>
</head>
<body style = "text-align: center; font-family: arial">
<form action="/login" method="POST">
<input type="text" name="email" placeholder="email:" required>
<br>
<input type="text" name="password" placeholder="password:" required>
<br>
<input type="submit" value="Submit">
</form>
<script src="{{ url_for ('static', filename='js/script.js')}}"></script>
</body>
</html>
Thanks
From your code, you are submitting your form directly when user clicks on submit and you are doing a return render_template which means you are returning an entire page (new page).
If you use flash in the above code, it will simply display the message at the top of the 'new' page that you have returned to.
To display a popup, you have to programmatically submit the form i.e. when the user clicks the submit button, you need to intercept it with Javascript and then via the same Javascript do an asynchronous post to your server. Your server output will get returned to your code. If it was a successful login, you redirect user. If it's not, you trigger a popup. Essentially, something like (this is a very rough outline)
a) On form submit, intercept it
document.getElementById(<form_id>).onsubmit = function() {
}
b) Submit your form via something like fetch. See this example on how to submit a form via fetch
c) If no password match, trigger a popup else redirect user
d) Your python code should not do a return render_template. You should just return a value that lets you know if everything was a success or something failed

HTML components using Typescript, Knockout and Require - HTML is not rendered?

I am trying to learn how component driven development works and I have followed the documents here https://knockoutjs.com/documentation/component-custom-elements.html (Including the many nested links relevant to this topic) however although the TS/JS files are loaded without error the HTML component is never rendered.
Here you can see the the typescript is loaded correctly by RequireJS:
Login-User typescript loaded in browser
And here is the HTML component in the webpage:
HTML component
This is the content within the HTML 'template':
<div class="panel">
<label>Username:</label>
<input type="text" data-bind="Value: $component.Username()" />
<br />
<label>Password:</label>
<input type="text" data-bind="Value: $component.Password()" />
<br />
<label>Valid:</label>
<input type="text" data-bind="Value: $component.ValidUser()" />
</div>
Here is the registration of the HTML template:
const componentName = "Login-User";
ko.components.unregister(componentName);
ko.components.register(componentName, {
viewModel: LoginViewModel,
template: { require: `text!/Views/Components/${componentName}.html` }
});
I do not get any errors in the console but the constructor in the TS file is never hit when adding breakpoints to debug which suggests the me that there was no attempt to actually render the HTML component at all?
I have checked all file paths are correct and deleted and re-compiled the TS files to generate JS files to ensure everything is up to date, I assume I have not properly configured require in some way and so the HTML component is never actually registered however due to no errors being logged I am a bit stuck for where to go next! As I said previously I have read the documentation on Knockout and also for RequireJS however when searching google for issue when implementing a HTML component I seem to only get results for Angular.
Any advice on how to determine the issue would be greatly appreciated, even better if there is any documentation/guides on how to use Knockout/Require/Typescript/HTML Components together which someone could point me at that would be great!
I think I have provided everything need but if not let me know.
Thanks,
Danny
Okay after a couple more hours of trial and error I figured out I had a few problems, for anyone else having this issue try the below resolutions:
I was not calling ko.applybindings();
import * as ko from "knockout";
export default class LoginViewModel {
Username: KnockoutObservable<string>;
Password: KnockoutObservable<string>;
ValidUser: KnockoutComputed<boolean>;
constructor(username: string, password: string) {
this.Username = ko.observable(username);
this.Password = ko.observable(password);
this.computedMethods();
}
private computedMethods(): void {
this.ValidUser = ko.pureComputed(() => {
return this.Username() === "Danny" && this.Password() === "pasword";
});
}
}
const componentName = "login-user";
ko.components.register(componentName, {
viewModel: LoginViewModel,
template: { require: `text!Scripts/Typescript/${componentName}.html` }
});
ko.applyBindings(); << This is important as it actually binds the custom element i.e login-user params="username: 'Danny', password: 'none'"></login-user> and without it nothing will be rendered on the page
After correcting this issue I then got a 404 in console when trying to load the custom element and although the filepath was correct I found that the best way to resolve this was to have the custom element in the same folder as it's TS counter-part:
Before:
template: { require: `text!/Views/Components/${componentName}.html` }
After:
template: { require: `text!Scripts/Typescript/${componentName}.html` }
Google searches recommended installing the following nuget packages although I think only require.text is actually required, if it doesn't resolve your issue it's worth a shot..:
Require Packages
I initially had my components named using camel case i.e Login-User.ts and Login-User.html, I read somewhere that they should be lower case to be valid html 'Tags' and both the .ts and .html files should be named exactly the same
Hope this helps anyone else having issues.

Call Django on HTML button click

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.

Grails 2.3.7 redirecting controller action with flash.message, i18n and html markup

I use Grails 2.3.7 and want to understand the following: I have a controller which sets a flash.message object with HTML markup from an i18n file (messages.properties) and args with no HTML markup.
When I call render, the corresponding GSP renders as expected, with HTML markup. When I call a redirect to another action, that does exactly the same (calling render), the rendered GSP shows the escaped HTML markup.
So what happens to the flash variable during a redirect? A simple println shows no difference. For reference, here is my code:
Controller:
class DebugController {
def testFlashEncoding(){
flash.message=message(code: "debug.flash.test", args: ["inner text with no markup"]) //debug.flash.test=<div style="border:1px solid red;">{0}</div>
flash.each {
println("flash in testFlashEncoding(): " + it)
}
// redirect(action: "index") //redirects to index(), html is rendered as text
render view: "testFlashEncoding" //renders testFlashEncoding.gsp, html is interpreted
}
def index(){
flash.each {
println("flash in index(): " + it)
}
render view: "testFlashEncoding" //renders testFlashEncoding.gsp, html is rendered as text
}
}
GSP:
<!DOCTYPE html>
<html>
<head>
<meta name="layout" content="main">
<title>DEBUG</title>
</head>
<body>
<g:if test="${flash.message}">
<div class="alert alert-success" role="status">${flash.message}</div>
</g:if>
<g:if test="${flash.error}">
<div class="alert alert-danger" role="status">${flash.error}</div>
</g:if>
</body>
</html>
So when I call the testFlashEncoding() action as shown above, the GSP is shown with a red border around the simple text. But when I use the redirect to the index() action instead, the GSP shows <div style="border:1px solid red;">inner text with no markup</div>.
The println statements show the expected values:
flash in testFlashEncoding(): message=<div style="border:1px solid red;">inner text with no markup</div>
flash in index(): message=<div style="border:1px solid red;">inner text with no markup</div>
So the content of flash is not touched, but somehow during the redirect Grails has some kind of switch that tells the rendering engine to escape the flash.message object.
For clarification, I use a freshly setup standard grails application, so my page codec ist set to grails.views.default.codec = "html" and I do know about the possibilities to alter the page codec or to force raw rendering, I just want to know what happens during the redirect (that scenario happens quite often in my current project).
Try either one of these:
${raw(flash.message)}
<%= flash.message %>
Worked for me. It printed correct marked up HTML

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.