I've just started with web2py, so this might be obvious but I struggle to see how it works:I have a controller action which returns a form:def register():
return dict(form=auth.register())I also have a view 'register.html' for this action, which is self-contained as it does NOT use any of the web2py frontend .css or .js stuff. All the HTML, CSS and JS are already done for the form too, e.g....
<form method="post" class="h5form">
<div class="own-labels">
<label>First name<sup>*</sup></label>
<input type="text" name="firstName" class="span3" placeholder="enter text…" required="required" tabindex="0">
<label>Last name<sup>*</sup></label>
<input type="text" name="lastName" class="span3" placeholder="enter text…" required="required" tabindex="1">
<label>Email<sup>*</sup></label>
<input type="email" name="email" class="span3" placeholder="enter text…" required="required" tabindex="3">
</div>
<div class="pull-left"><input type="submit" class="btn pull-right" style="margin-top: 15px;" value="Register"></div>
</form>
...So now, how do I link the returned 'form' variables to the right fields in this pre-defined view? In the manual, it briefly mentions the use of{{=form.custom.begin}}
...
{{=form.custom.end}}
but it is not very clear to me how should I use it in my case. Is this only and right approach for implementing custom forms whose views are already fully defined in HTML, CSS and JS? Thank you.
def register():
return dict(form=auth.register())
...
<form method="post" class="h5form">
<div class="own-labels">
<label>First name<sup>*</sup></label>
<input type="text" name="firstName" class="span3" placeholder="enter text…" required="required" tabindex="0">
<label>Last name<sup>*</sup></label>
<input type="text" name="lastName" class="span3" placeholder="enter text…" required="required" tabindex="1">
<label>Email<sup>*</sup></label>
<input type="email" name="email" class="span3" placeholder="enter text…" required="required" tabindex="3">
</div>
<div class="pull-left"><input type="submit" class="btn pull-right" style="margin-top: 15px;" value="Register"></div>
</form>
...
But you need to replace <form...> with {{=form.custom.begin}}, </form> with {{=form.custom.end} and you need input field names corresponding to the column names in the db.auth_user table. If you use the custom form you must also find your own way to display form.errors
I've just started with web2py, so this might be obvious but I struggle to see how it works:I have a controller action which returns a form:def register():
return dict(form=auth.register())I also have a view 'register.html' for this action, which is self-contained as it does NOT use any of the web2py frontend .css or .js stuff. All the HTML, CSS and JS are already done for the form too, e.g.
...
<form method="post" class="h5form">
<div class="own-labels">
<label>First name<sup>*</sup></label>
<input type="text" name="firstName" class="span3" placeholder="enter text…" required="required" tabindex="0">
<label>Last name<sup>*</sup></label>
<input type="text" name="lastName" class="span3" placeholder="enter text…" required="required" tabindex="1">
<label>Email<sup>*</sup></label>
<input type="email" name="email" class="span3" placeholder="enter text…" required="required" tabindex="3">
</div>
<div class="pull-left"><input type="submit" class="btn pull-right" style="margin-top: 15px;" value="Register"></div>
</form>
...
If you refuse to use web2py's css and js files, remember that response.flash and session.flash wont work
and also your validators also wont work. so you would have to handle form validation yourself.
When I used customform for login, it won't give me any errors to be shown whenever the password was invalid or email is not existing. I put it on jquery mobile website. Any idea?
When I used customform for login, it won't give me any errors to be shown whenever the password was invalid or email is not existing. I put it on jquery mobile website. Any idea?
{{=form.custom.begin}}
#in between the opening and closing tags put in your normal html code and make sure the element names corresponds to the column names as defined in your database. web2py will handle the rest automatically. This is the most flexible way while still making use of web2py's validators.
{{=form.custom.end}}
{{extend layout.html}}
<head>
<link href="css/page_specific_css_1.css" rel="stylesheet"> <link href="css/page_specific_css_2.css" rel="stylesheet">
</head>{{=form.custom.begin}}
# my custom html code here
{{=form.custom.end}}1. I want to utilize 'layout.html' to some extent such that it stores some common css files for the rest of the view pages. Kinda like a shared base template, and I want to add page-specific css (or js) files on individual html view page. Is it as simple as including:{{extend layout.html}}
<head>
<link href="css/page_specific_css_1.css" rel="stylesheet"><link href="css/page_specific_css_2.css" rel="stylesheet">
</head>
in the <head> section of a html view page? By doing this, do we append the above two css files to the list of the files in response.files (which is already set in 'layout.html')
{{response.files.extend([URL('static', 'css/css_1.css'), URL('static', 'css/css_2.css')])}}
{{extend 'layout.html'}}No, because the layout already includes a <head> section. The content of the view gets inserted in the layout.html file at the point of the {{include}}, which presumably is not in the head.
Instead, you have a couple options. First, you could add the files to response.files before extending the layout:
Then, if your layout includes web2py_ajax.html, it will link those css files in the head. Alternatively, you could create a block in the head of layout.html, and then customize the content of that block in your page view -- see http://web2py.com/books/default/chapter/29/5#Blocks-in-views.{{response.files.extend([URL('static', 'css/css_1.css'), URL('static', 'css/css_2.css')])}}
{{extend 'layout.html'}}
def myaction():
response.files.append(URL('static','css/page_specific_css_1.css'))
response.files.append(URL('static','css/page_specific_css_2.css'))
# rest of the action
...The layout also include a <body> section, does this mean that in my custom view I shouldn't have another <body> section such that I should just write all the custom html content without <body></body> tags?
Another thought, can I add page-specific files for the view in the corresponding controller action, e.g.def myaction():
response.files.append(URL('static','css/page_specific_css_1.css'))
response.files.append(URL('static','css/page_specific_css_2.css'))
# rest of the action
...Would this be enough? If so, how does this compare with the two options you've proposed below?
Regarding my other question about Recaptcha support, how should I embed and customize it in my custom view? Thanks very much!
Right, you don't need a body tag in the view either. In layout.html, there should be an {{include}} -- that gets replaced with the entire contents of the view that extends the layout.
<body class="my_css_class">
Cool. But is there way to configure the <body> tag of a specific view page that extends the 'layout.html'? For example, for my custom view, I want its body tag to be like:<body class="my_css_class">
Is it possible to configure such thing? Thanks!
<body class="{{=body_class}}">{{body_class = 'my_css_class'}}
{{extend 'layout.html'}} def register():
return dict(form=auth.register())<!DOCTYPE html><html class="no-js" lang="{{=T.accepted_language or 'en'}}"><head> <meta charset="utf-8" /> <title>{{=response.title or request.application}}</title> <meta name="application-name" content="{{=request.application}}" />
<!-- for Google --> <meta name="google-site-verification" content="my_code" /> <!-- Mobile Viewport Fix device-width: Occupy full width of the screen in its current orientation initial-scale = 1.0 retains dimensions instead of zooming out if page height > device height user-scalable = yes allows the user to zoom in --> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<!-- All JavaScript at the bottom, except for Modernizr which enables HTML5 elements & feature detects --> <script src="{{=URL('static','js/modernizr.custom.js')}}"></script>
<!-- include stylesheets --> {{ response.files.append(URL('static','css/bootstrap.min.css')) response.files.append(URL('static','css/bootstrap-responsive.min.css')) }}
{{include 'web2py_ajax.html'}}
</head><body class="{{=body_class}}"> {{include}} {{if response.google_analytics_id:}}<script type="text/javascript"> var _gaq = _gaq || []; _gaq.push(['_setAccount', '{{=response.google_analytics_id}}']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js'; var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })(); </script> {{pass}}</body></html>{{body_class = 'own'}}{{ response.files.append(URL('static', 'css/jquery.h5form-2.4.1.css')) response.files.append(URL('static', 'css/own.css')) }}{{extend 'layout.html'}}<div class="container own-container"> <h1>Sign up</h1> <h5>Create Your Account</h5> <div class="row"> <div class="span12"> <form action="" enctype="multipart/form-data" method="post" class="own-form h5form"> <div class="own-labels"> <label>First name<sup>*</sup></label> <input type="text" name="first_name" class="span3" placeholder="enter first name ..." required="required" tabindex="0"> <label>Last name<sup>*</sup></label> <input type="text" name="last_name" class="span3" placeholder="enter last name ..." required="required" tabindex="1"> <label>Email<sup>*</sup></label> <input type="email" name="email" class="span3" placeholder="enter email ..." required="required" tabindex="2"> <label>Password<sup>*</sup></label> <input type="password" name="password" class="span3" placeholder="enter password ..." required="required" tabindex="3"> <label>Re-password<sup>*</sup></label> <input type="password" name="password" class="span3" placeholder="enter password again ..." required="required" tabindex="4"> </div> <div class="pull-left"> <label class="checkbox"> <input type="checkbox" tabindex="5">I acknowledge that I have read and accept <a href="#">the Terms and Conditions</a> </label> <input type="submit" class="btn pull-right" style="margin-top: 15px;" value="Register"> </div> </form> </div> </div></div><script src="{{=URL('static', 'js/jquery-1.7.2_min.js')}}"></script><script src="{{=URL('static', 'js/jquery.h5form-2.4.1.min.js')}}"></script><script src="{{=URL('static', 'js/own.js')}}"></script><form action="" enctype="multipart/form-data" method="post" class="own-form h5form">
<div class="own-labels"><label>First name<sup>*</sup></label>
<input type="text" name="first_name" class="span3" placeholder="enter first name ..." required="required" tabindex="0">
<label>Last name<sup>*</sup></label>
<input type="text" name="last_name" class="span3" placeholder="enter last name ..." required="required" tabindex="1">
<label>Email<sup>*</sup></label>
<input type="email" name="email" class="span3" placeholder="enter email ..." required="required" tabindex="2"><label>Password<sup>*</sup></label><input type="password" name="password" class="span3" placeholder="enter password ..." required="required" tabindex="3"><label>Re-password<sup>*</sup></label><input type="password" name="password" class="span3" placeholder="enter password again ..." required="required" tabindex="4"></div><div class="pull-left"><label class="checkbox"><input type="checkbox" tabindex="5">I acknowledge that I have read and accept <a href="#">the Terms and Conditions</a></label>
<input type="submit" class="btn pull-right" style="margin-top: 15px;" value="Register"></div></form>
</div></div></div><script src="{{=URL('static', 'js/jquery-1.7.2_min.js')}}"></script><script src="{{=URL('static', 'js/jquery.h5form-2.4.1.min.js')}}"></script><script src="{{=URL('static', 'js/own.js')}}"></script>
Traceback (most recent call last): File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/restricted.py", line 205, in restricted
exec ccode in environment
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/applications/turklab/controllers/account.py", line 85, in <module>
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/globals.py", line 173, in <lambda>
self._caller = lambda f: f()
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/applications/turklab/controllers/account.py", line 24, in register
return dict(form=auth.register())
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/tools.py", line 1929, in register
onvalidation=onvalidation,hideerror=self.settings.hideerror):
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/sqlhtml.py", line 1089, in accepts
hideerror=hideerror,
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 1841, in accepts
status = self._traverse(status,hideerror)
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 781, in _traverse
newstatus = c._traverse(status,hideerror) and newstatus
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 781, in _traverse
newstatus = c._traverse(status,hideerror) and newstatus
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 781, in _traverse
newstatus = c._traverse(status,hideerror) and newstatus
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 781, in _traverse
newstatus = c._traverse(status,hideerror) and newstatus
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 788, in _traverse
newstatus = self._validate()
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/html.py", line 1606, in _validate
(value, errors) = validator(value)
File "/Users/chris/Package/envs/.virtualenvs/capp/web2py/gluon/validators.py", line 2590, in __call__
all_upper = re.findall("[A-Z]", value)
File "/Users/chris/Package/envs/.virtualenvs/capp/lib/python2.7/re.py", line 177, in findall
return _compile(pattern, flags).findall(string)
TypeError: expected string or buffer
return dict(form=auth.register())
which web2py version? Do you have a custom auth_user table? Looks like something wrong with the list of validators for a field containing the IS_UPPER validator.
IS_STRONG(min=7, special=0, upper=0, number=0)
I really need to see the models where you set IS_STRONG.
Somehow the value passed to the validator is not a string so the validator chokes. This can be fixed in IS_STRONG.__call__ by setting value = str(value) but I would like to understand why it is happening.
db.user_login.password.requires = [IS_NOT_EMPTY(error_message='Password needed!'), IS_STRONG(min=7, special=0, upper=0, number=0), CRYPT()]