web/views/basetemplates.py
branchtls-sprint
changeset 641 ed668804af37
parent 609 08b82027edf8
child 646 8a9551089912
equal deleted inserted replaced
630:66ff0b2f7d03 641:ed668804af37
    17 
    17 
    18 from cubicweb.web.views.baseviews import vid_from_rset
    18 from cubicweb.web.views.baseviews import vid_from_rset
    19 
    19 
    20 # main templates ##############################################################
    20 # main templates ##############################################################
    21 
    21 
    22 
       
    23 class LogInOutTemplate(MainTemplate):
    22 class LogInOutTemplate(MainTemplate):
    24     
    23 
    25     def call(self):
    24     def call(self):
    26         self.set_request_content_type()
    25         self.set_request_content_type()
    27         w = self.w
    26         w = self.w
    28         self.write_doctype()
    27         self.write_doctype()
    29         lang = self.req.lang
    28         lang = self.req.lang
    41         w(NOINDEX)
    40         w(NOINDEX)
    42         w(NOFOLLOW)
    41         w(NOFOLLOW)
    43         w(u'\n'.join(additional_headers) + u'\n')
    42         w(u'\n'.join(additional_headers) + u'\n')
    44         self.template('htmlheader', rset=self.rset)
    43         self.template('htmlheader', rset=self.rset)
    45         w(u'<title>%s</title>\n' % html_escape(page_title))
    44         w(u'<title>%s</title>\n' % html_escape(page_title))
    46         
    45 
    47 
    46 
    48 class LogInTemplate(LogInOutTemplate):
    47 class LogInTemplate(LogInOutTemplate):
    49     id = 'login'
    48     id = 'login'
    50     title = 'log in'
    49     title = 'log in'
    51 
    50 
    52     def content(self, w):
    51     def content(self, w):
    53         self.template('logform', rset=self.rset, id='loginBox', klass='')
    52         self.template('logform', rset=self.rset, id='loginBox', klass='')
    54         
    53 
    55 
    54 
    56 class LoggedOutTemplate(LogInOutTemplate):
    55 class LoggedOutTemplate(LogInOutTemplate):
    57     id = 'loggedout'
    56     id = 'loggedout'
    58     title = 'logged out'
    57     title = 'logged out'
    59 
    58 
    64             indexurl = self.build_url('view', vid='index', __message=msg)
    63             indexurl = self.build_url('view', vid='index', __message=msg)
    65             w(u'<p><a href="%s">%s</a><p>' % (
    64             w(u'<p><a href="%s">%s</a><p>' % (
    66                 html_escape(indexurl),
    65                 html_escape(indexurl),
    67                 self.req._('go back to the index page')))
    66                 self.req._('go back to the index page')))
    68 
    67 
    69         
    68 
    70 class TheMainTemplate(MainTemplate):
    69 class TheMainTemplate(MainTemplate):
    71     """default main template :
    70     """default main template :
    72     
    71 
    73     - call header / footer templates
    72     - call header / footer templates
    74     - build result set
    73     - build result set
    75     - guess and call an appropriate view through the view manager
    74     - guess and call an appropriate view through the view manager
    76     """
    75     """
    77     id = 'main'
    76     id = 'main'
   110                 req.set_message(req._("You have no access to this view or it's not applyable to current data"))
   109                 req.set_message(req._("You have no access to this view or it's not applyable to current data"))
   111             self.warning("the view %s can not be applied to this query", vid)
   110             self.warning("the view %s can not be applied to this query", vid)
   112             vid = vid_from_rset(req, rset, self.schema)
   111             vid = vid_from_rset(req, rset, self.schema)
   113             view = self.vreg.select_view(vid, req, rset)
   112             view = self.vreg.select_view(vid, req, rset)
   114         return view, rset
   113         return view, rset
   115     
   114 
   116     def call(self):
   115     def call(self):
   117         view, rset = self._select_view_and_rset()
   116         view, rset = self._select_view_and_rset()
   118         req = self.req
   117         req = self.req
   119         # update breadcrumps **before** validating cache, unless the view
   118         # update breadcrumps **before** validating cache, unless the view
   120         # specifies explicitly it should not be added to breadcrumb or the
   119         # specifies explicitly it should not be added to breadcrumb or the
   121         # view is a binary view
   120         # view is a binary view
   122         if view.add_to_breadcrumbs and not view.binary:
   121         if view.add_to_breadcrumbs and not view.binary:
   123             req.update_breadcrumbs()
   122             req.update_breadcrumbs()
   124         view.set_http_cache_headers()
   123         view.set_http_cache_headers()
   125         req.validate_cache()
   124         req.validate_cache()
   126         with_templates = not view.binary and view.templatable and \
   125         with_templates = self.with_templates(view)
   127                          not req.form.has_key('__notemplate')
       
   128         if not with_templates:
   126         if not with_templates:
   129             view.set_request_content_type()
   127             view.set_request_content_type()
   130             self.set_stream(templatable=False)
   128             self.set_stream(templatable=False)
   131         else:
   129         else:
   132             self.set_request_content_type()
   130             self.set_request_content_type()
   133             content_type = self.content_type
   131             content_type = self.content_type
   134             self.template_header(content_type, view)
   132             self.template_header(content_type, view)
   135         if view.binary:
   133         self.template('page-content', view=view, rset=rset)
   136             # have to replace our unicode stream using view's binary stream
       
   137             view.dispatch()
       
   138             assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream
       
   139             self._stream = view._stream
       
   140         else:
       
   141             view.dispatch(w=self.w)
       
   142         if with_templates:
   134         if with_templates:
   143             self.template_footer(view)
   135             self.template_footer(view)
   144 
   136 
   145             
   137     def with_templates(self, view):
       
   138         return (not view.binary and view.templatable and
       
   139                 not self.req.form.has_key('__notemplate'))
       
   140 
   146     def process_rql(self, rql):
   141     def process_rql(self, rql):
   147         """execute rql if specified"""
   142         """execute rql if specified"""
   148         if rql:
   143         if rql:
   149             self.ensure_ro_rql(rql)
   144             self.ensure_ro_rql(rql)
   150             if not isinstance(rql, unicode):
   145             if not isinstance(rql, unicode):
   157     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   152     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   158         page_title = page_title or view.page_title()
   153         page_title = page_title or view.page_title()
   159         additional_headers = additional_headers or view.html_headers()
   154         additional_headers = additional_headers or view.html_headers()
   160         self.template_html_header(content_type, page_title, additional_headers)
   155         self.template_html_header(content_type, page_title, additional_headers)
   161         self.template_body_header(view)
   156         self.template_body_header(view)
   162         # display entity type restriction component
   157 
   163         etypefilter = self.vreg.select_component('etypenavigation',
       
   164                                                  self.req, self.rset)
       
   165         if etypefilter and etypefilter.propval('visible'):
       
   166             etypefilter.dispatch(w=self.w)
       
   167         self.nav_html = UStringIO()
       
   168         self.pagination(self.req, self.rset, self.nav_html.write,
       
   169                         not (view and view.need_navigation))
       
   170         self.w(_(self.nav_html.getvalue()))
       
   171         self.w(u'<div id="contentmain">\n')
       
   172     
       
   173     def template_html_header(self, content_type, page_title, additional_headers=()):
   158     def template_html_header(self, content_type, page_title, additional_headers=()):
   174         w = self.whead
   159         w = self.whead
   175         lang = self.req.lang
   160         lang = self.req.lang
   176         self.write_doctype()
   161         self.write_doctype()
   177         w(u'<base href="%s" />' % html_escape(self.req.base_url()))
   162         w(u'<base href="%s" />' % html_escape(self.req.base_url()))
   194             rqlcomp.dispatch(w=self.w, view=view)
   179             rqlcomp.dispatch(w=self.w, view=view)
   195         msgcomp = self.vreg.select_component('applmessages', self.req, self.rset)
   180         msgcomp = self.vreg.select_component('applmessages', self.req, self.rset)
   196         if msgcomp:
   181         if msgcomp:
   197             msgcomp.dispatch(w=self.w)
   182             msgcomp.dispatch(w=self.w)
   198         self.content_header(view)
   183         self.content_header(view)
   199         w(u'<div id="pageContent">\n')
   184 
   200         vtitle = self.req.form.get('vtitle')
       
   201         if vtitle:
       
   202             w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle))
       
   203             
       
   204     def template_footer(self, view=None):
   185     def template_footer(self, view=None):
   205         self.w(u'</div>\n') # close id=contentmain
       
   206         self.w(_(self.nav_html.getvalue()))
       
   207         self.w(u'</div>\n') # closes id=pageContent
       
   208         self.content_footer(view)
   186         self.content_footer(view)
   209         self.w(u'</td>\n')
   187         self.w(u'</td>\n')
   210         self.nav_column(view, 'right')
   188         self.nav_column(view, 'right')
   211         self.w(u'</tr></table></div>\n')
   189         self.w(u'</tr></table></div>\n')
   212         self.template('footer', rset=self.rset)
   190         self.template('footer', rset=self.rset)
   222             self.w(u'</div></td>\n')
   200             self.w(u'</div></td>\n')
   223 
   201 
   224     def content_header(self, view=None):
   202     def content_header(self, view=None):
   225         """by default, display informal messages in content header"""
   203         """by default, display informal messages in content header"""
   226         self.template('contentheader', rset=self.rset, view=view)
   204         self.template('contentheader', rset=self.rset, view=view)
   227             
   205 
   228     def content_footer(self, view=None):
   206     def content_footer(self, view=None):
   229         self.template('contentfooter', rset=self.rset, view=view)
   207         self.template('contentfooter', rset=self.rset, view=view)
       
   208 
       
   209 
       
   210 class PageContentTemplate(TheMainTemplate):
       
   211     id = 'page-content'
       
   212 
       
   213     def call(self, view=None, rset=None):
       
   214         self.req.set_header('x-cubicweb-css', 'a.css;b.css')
       
   215         if view is None:
       
   216             view, rset = self._select_view_and_rset()
       
   217         with_templates = self.with_templates(view)
       
   218         w = self.w
       
   219         if with_templates:
       
   220             w(u'<div id="pageContent">\n')
       
   221             vtitle = self.req.form.get('vtitle')
       
   222             if vtitle:
       
   223                 w(u'<h1 class="vtitle">%s</h1>\n' % html_escape(vtitle))
       
   224             # display entity type restriction component
       
   225             etypefilter = self.vreg.select_component('etypenavigation',
       
   226                                                      self.req, self.rset)
       
   227             if etypefilter and etypefilter.propval('visible'):
       
   228                 etypefilter.dispatch(w=w)
       
   229             self.nav_html = UStringIO()
       
   230             self.pagination(self.req, self.rset, self.nav_html.write,
       
   231                             not (view and view.need_navigation))
       
   232             w(_(self.nav_html.getvalue()))
       
   233             w(u'<div id="contentmain">\n')
       
   234         if view.binary:
       
   235             # have to replace our unicode stream using view's binary stream
       
   236             view.dispatch()
       
   237             assert self._stream, 'duh, template used as a sub-view ?? (%s)' % self._stream
       
   238             self._stream = view._stream
       
   239         else:
       
   240             view.dispatch(w=w)
       
   241         if with_templates:
       
   242             w(u'</div>\n') # close id=contentmain
       
   243             w(_(self.nav_html.getvalue()))
       
   244             w(u'</div>\n') # closes id=pageContent
   230 
   245 
   231 
   246 
   232 class ErrorTemplate(TheMainTemplate):
   247 class ErrorTemplate(TheMainTemplate):
   233     """fallback template if an internal error occured during displaying the
   248     """fallback template if an internal error occured during displaying the
   234     main template. This template may be called for authentication error,
   249     main template. This template may be called for authentication error,
   235     which means that req.cnx and req.user may not be set.
   250     which means that req.cnx and req.user may not be set.
   236     """
   251     """
   237     id = 'error'
   252     id = 'error'
   238     
   253 
   239     def call(self):
   254     def call(self):
   240         """display an unexpected error"""
   255         """display an unexpected error"""
   241         self.set_request_content_type()
   256         self.set_request_content_type()
   242         self.req.reset_headers()
   257         self.req.reset_headers()
   243         view = self.vreg.select_view('error', self.req, self.rset)
   258         view = self.vreg.select_view('error', self.req, self.rset)
   244         self.template_header(self.content_type, view, self.req._('an error occured'),
   259         self.template_header(self.content_type, view, self.req._('an error occured'),
   245                              [NOINDEX, NOFOLLOW])
   260                              [NOINDEX, NOFOLLOW])
   246         view.dispatch(w=self.w)
   261         view.dispatch(w=self.w)
   247         self.template_footer(view)
   262         self.template_footer(view)
   248     
   263 
   249     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   264     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   250         w = self.whead
   265         w = self.whead
   251         lang = self.req.lang
   266         lang = self.req.lang
   252         self.write_doctype()
   267         self.write_doctype()
   253         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   268         w(u'<meta http-equiv="content-type" content="%s; charset=%s"/>\n'
   262 
   277 
   263 
   278 
   264 class SimpleMainTemplate(TheMainTemplate):
   279 class SimpleMainTemplate(TheMainTemplate):
   265 
   280 
   266     id = 'main-no-top'
   281     id = 'main-no-top'
   267     
   282 
   268     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   283     def template_header(self, content_type, view=None, page_title='', additional_headers=()):
   269         page_title = page_title or view.page_title()
   284         page_title = page_title or view.page_title()
   270         additional_headers = additional_headers or view.html_headers()
   285         additional_headers = additional_headers or view.html_headers()
   271         whead = self.whead
   286         whead = self.whead
   272         lang = self.req.lang
   287         lang = self.req.lang
   293         w(u'<td id="contentcol" rowspan="2">')
   308         w(u'<td id="contentcol" rowspan="2">')
   294         w(u'<div id="pageContent">\n')
   309         w(u'<div id="pageContent">\n')
   295         vtitle = self.req.form.get('vtitle')
   310         vtitle = self.req.form.get('vtitle')
   296         if vtitle:
   311         if vtitle:
   297             w(u'<h1 class="vtitle">%s</h1>' % html_escape(vtitle))
   312             w(u'<h1 class="vtitle">%s</h1>' % html_escape(vtitle))
   298             
   313 
   299     def topleft_header(self):
   314     def topleft_header(self):
   300         self.w(u'<table id="header"><tr>\n')
   315         self.w(u'<table id="header"><tr>\n')
   301         self.w(u'<td>')
   316         self.w(u'<td>')
   302         self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w)
   317         self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w)
   303         self.w(u'</td>\n')
   318         self.w(u'</td>\n')
   306 # page parts templates ########################################################
   321 # page parts templates ########################################################
   307 
   322 
   308 class HTMLHeader(Template):
   323 class HTMLHeader(Template):
   309     """default html headers"""
   324     """default html headers"""
   310     id = 'htmlheader'
   325     id = 'htmlheader'
   311     
   326 
   312     def call(self, **kwargs):
   327     def call(self, **kwargs):
   313         self.favicon()
   328         self.favicon()
   314         self.stylesheets()
   329         self.stylesheets()
   315         self.javascripts()
   330         self.javascripts()
   316         self.alternates()
   331         self.alternates()
   318 
   333 
   319     def favicon(self):
   334     def favicon(self):
   320         favicon = self.req.external_resource('FAVICON', None)
   335         favicon = self.req.external_resource('FAVICON', None)
   321         if favicon:
   336         if favicon:
   322             self.whead(u'<link rel="shortcut icon" href="%s"/>\n' % favicon)
   337             self.whead(u'<link rel="shortcut icon" href="%s"/>\n' % favicon)
   323             
   338 
   324     def stylesheets(self):
   339     def stylesheets(self):
   325         req = self.req
   340         req = self.req
   326         add_css = req.add_css
   341         add_css = req.add_css
   327         for css in req.external_resource('STYLESHEETS'):
   342         for css in req.external_resource('STYLESHEETS'):
   328             add_css(css, localfile=False)
   343             add_css(css, localfile=False)
   329         for css in req.external_resource('STYLESHEETS_PRINT'):
   344         for css in req.external_resource('STYLESHEETS_PRINT'):
   330             add_css(css, u'print', localfile=False)
   345             add_css(css, u'print', localfile=False)
   331         for css in req.external_resource('IE_STYLESHEETS'):
   346         for css in req.external_resource('IE_STYLESHEETS'):
   332             add_css(css, localfile=False, ieonly=True)
   347             add_css(css, localfile=False, ieonly=True)
   333         
   348 
   334     def javascripts(self):
   349     def javascripts(self):
   335         for jscript in self.req.external_resource('JAVASCRIPTS'):
   350         for jscript in self.req.external_resource('JAVASCRIPTS'):
   336             self.req.add_js(jscript, localfile=False)
   351             self.req.add_js(jscript, localfile=False)
   337             
   352 
   338     def alternates(self):
   353     def alternates(self):
   339         urlgetter = self.vreg.select_component('rss_feed_url', self.req, self.rset)
   354         urlgetter = self.vreg.select_component('rss_feed_url', self.req, self.rset)
   340         if urlgetter is not None:
   355         if urlgetter is not None:
   341             url = urlgetter.feed_url()
   356             url = urlgetter.feed_url()
   342             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
   357             self.whead(u'<link rel="alternate" type="application/rss+xml" title="RSS feed" href="%s"/>\n'
   350 
   365 
   351 
   366 
   352 class HTMLPageHeader(Template):
   367 class HTMLPageHeader(Template):
   353     """default html page header"""
   368     """default html page header"""
   354     id = 'header'
   369     id = 'header'
   355     
   370 
   356     def call(self, view, **kwargs):
   371     def call(self, view, **kwargs):
   357         self.main_header(view)
   372         self.main_header(view)
   358         self.w(u'''
   373         self.w(u'''
   359   <div id="stateheader">''')
   374   <div id="stateheader">''')
   360         self.state_header()
   375         self.state_header()
   361         self.w(u'''
   376         self.w(u'''
   362   </div>
   377   </div>
   363   ''')
   378   ''')
   364         
   379 
   365     def main_header(self, view):
   380     def main_header(self, view):
   366         """build the top menu with authentification info and the rql box"""
   381         """build the top menu with authentification info and the rql box"""
   367         self.w(u'<table id="header"><tr>\n')
   382         self.w(u'<table id="header"><tr>\n')
   368         self.w(u'<td id="firstcolumn">')
   383         self.w(u'<td id="firstcolumn">')
   369         self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w)
   384         self.vreg.select_component('logo', self.req, self.rset).dispatch(w=self.w)
   390         self.w(u'<td id="lastcolumn">')
   405         self.w(u'<td id="lastcolumn">')
   391         self.w(u'</td>\n')
   406         self.w(u'</td>\n')
   392         self.w(u'</tr></table>\n')
   407         self.w(u'</tr></table>\n')
   393         self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden',
   408         self.template('logform', rset=self.rset, id='popupLoginBox', klass='hidden',
   394                       title=False, message=False)
   409                       title=False, message=False)
   395         
   410 
   396     def state_header(self):
   411     def state_header(self):
   397         state = self.req.search_state
   412         state = self.req.search_state
   398         if state[0] == 'normal':
   413         if state[0] == 'normal':
   399             return
   414             return
   400         _ = self.req._
   415         _ = self.req._
   401         value = self.view('oneline', self.req.eid_rset(state[1][1]))
   416         value = self.view('oneline', self.req.eid_rset(state[1][1]))
   402         msg = ' '.join((_("searching for"),
   417         msg = ' '.join((_("searching for"),
   403                         display_name(self.req, state[1][3]),
   418                         display_name(self.req, state[1][3]),
   404                         _("to associate with"), value,
   419                         _("to associate with"), value,
   405                         _("by relation"), '"', 
   420                         _("by relation"), '"',
   406                         display_name(self.req, state[1][2], state[1][0]),
   421                         display_name(self.req, state[1][2], state[1][0]),
   407                         '"'))
   422                         '"'))
   408         return self.w(u'<div class="stateMessage">%s</div>' % msg)
   423         return self.w(u'<div class="stateMessage">%s</div>' % msg)
   409 
   424 
   410 
   425 
   411 
   426 
   412 class HTMLPageFooter(Template):
   427 class HTMLPageFooter(Template):
   413     """default html page footer: include logo if any, and close the HTML body
   428     """default html page footer: include logo if any, and close the HTML body
   414     """
   429     """
   415     id = 'footer'
   430     id = 'footer'
   416     
   431 
   417     def call(self, **kwargs):
   432     def call(self, **kwargs):
   418         req = self.req
   433         req = self.req
   419         self.w(u'<div class="footer">')
   434         self.w(u'<div class="footer">')
   420         # XXX Take object from the registry if in there? would be
   435         # XXX Take object from the registry if in there? would be
   421         #     better anyway
   436         #     better anyway
   432     """default html page content header:
   447     """default html page content header:
   433     * include message component if selectable for this request
   448     * include message component if selectable for this request
   434     * include selectable content navigation components
   449     * include selectable content navigation components
   435     """
   450     """
   436     id = 'contentheader'
   451     id = 'contentheader'
   437     
   452 
   438     def call(self, view, **kwargs):
   453     def call(self, view, **kwargs):
   439         """by default, display informal messages in content header"""
   454         """by default, display informal messages in content header"""
   440         components = self.vreg.possible_vobjects('contentnavigation',
   455         components = self.vreg.possible_vobjects('contentnavigation',
   441                                                  self.req, self.rset,
   456                                                  self.req, self.rset,
   442                                                  view=view, context='navtop')
   457                                                  view=view, context='navtop')
   450 class HTMLContentFooter(Template):
   465 class HTMLContentFooter(Template):
   451     """default html page content footer: include selectable content navigation
   466     """default html page content footer: include selectable content navigation
   452     components
   467     components
   453     """
   468     """
   454     id = 'contentfooter'
   469     id = 'contentfooter'
   455     
   470 
   456     def call(self, view, **kwargs):
   471     def call(self, view, **kwargs):
   457         components = self.vreg.possible_vobjects('contentnavigation',
   472         components = self.vreg.possible_vobjects('contentnavigation',
   458                                                  self.req, self.rset,
   473                                                  self.req, self.rset,
   459                                                  view=view, context='navbottom')
   474                                                  view=view, context='navbottom')
   460         if components:
   475         if components:
   472         self.req.add_css('cubicweb.login.css')
   487         self.req.add_css('cubicweb.login.css')
   473         self.w(u'<div id="%s" class="%s">' % (id, klass))
   488         self.w(u'<div id="%s" class="%s">' % (id, klass))
   474         if title:
   489         if title:
   475             self.w(u'<div id="loginTitle">%s</div>'
   490             self.w(u'<div id="loginTitle">%s</div>'
   476                    % self.req.property_value('ui.site-title'))
   491                    % self.req.property_value('ui.site-title'))
   477         self.w(u'<div id="loginContent">\n')        
   492         self.w(u'<div id="loginContent">\n')
   478 
   493 
   479         if message:
   494         if message:
   480             self.display_message()
   495             self.display_message()
   481         if self.config['auth-mode'] == 'http':
   496         if self.config['auth-mode'] == 'http':
   482             # HTTP authentication
   497             # HTTP authentication
   488 
   503 
   489     def display_message(self):
   504     def display_message(self):
   490         message = self.req.message
   505         message = self.req.message
   491         if message:
   506         if message:
   492             self.w(u'<div class="simpleMessage">%s</div>\n' % message)
   507             self.w(u'<div class="simpleMessage">%s</div>\n' % message)
   493                      
   508 
   494     def login_form(self, id):
   509     def login_form(self, id):
   495         _ = self.req._
   510         _ = self.req._
   496         self.w(u'<form method="post" action="%s" id="login_form">\n'
   511         self.w(u'<form method="post" action="%s" id="login_form">\n'
   497                % html_escape(login_form_url(self.config, self.req)))
   512                % html_escape(login_form_url(self.config, self.req)))
   498         self.w(u'<table>\n')
   513         self.w(u'<table>\n')
   507         self.w(u'</tr>\n')
   522         self.w(u'</tr>\n')
   508         self.w(u'</table>\n')
   523         self.w(u'</table>\n')
   509         self.w(u'</form>\n')
   524         self.w(u'</form>\n')
   510         self.req.html_headers.add_onload('jQuery("#__login:visible").focus()')
   525         self.req.html_headers.add_onload('jQuery("#__login:visible").focus()')
   511 
   526 
   512     
   527 
   513 def login_form_url(config, req):
   528 def login_form_url(config, req):
   514     if req.https:
   529     if req.https:
   515         return req.url()
   530         return req.url()
   516     if config.get('https-url'):
   531     if config.get('https-url'):
   517         return req.url().replace(req.base_url(), config['https-url'])
   532         return req.url().replace(req.base_url(), config['https-url'])