Mercurial > p > roundup > code
comparison roundup/cgi/client.py @ 1002:1798d2fa9fec
Hack hack...
. Lots of cleanup in the classic html (stylesheet, search page, index page, ...)
. Reinstated searching, but not query saving yet
. Filtering only allows sorting and grouping by one property - all backends
now implement this behaviour.
. Nosy list journalling turned off by default, everything else is on.
. Added some convenience methods (reverse, propchanged, [item] accesses, ...)
. Did I mention the stylesheet is much cleaner now? :)
| author | Richard Jones <richard@users.sourceforge.net> |
|---|---|
| date | Sun, 01 Sep 2002 04:32:30 +0000 |
| parents | 55ab0c5b49f9 |
| children | f89b8d32291b |
comparison
equal
deleted
inserted
replaced
| 1001:7fea15e6cdfe | 1002:1798d2fa9fec |
|---|---|
| 1 # $Id: client.py,v 1.1 2002-08-30 08:28:44 richard Exp $ | 1 # $Id: client.py,v 1.2 2002-09-01 04:32:30 richard Exp $ |
| 2 | 2 |
| 3 __doc__ = """ | 3 __doc__ = """ |
| 4 WWW request handler (also used in the stand-alone server). | 4 WWW request handler (also used in the stand-alone server). |
| 5 """ | 5 """ |
| 6 | 6 |
| 294 'edit': 'edititem_action', | 294 'edit': 'edititem_action', |
| 295 'new': 'newitem_action', | 295 'new': 'newitem_action', |
| 296 'login': 'login_action', | 296 'login': 'login_action', |
| 297 'logout': 'logout_action', | 297 'logout': 'logout_action', |
| 298 'register': 'register_action', | 298 'register': 'register_action', |
| 299 'search': 'search_action', | |
| 299 } | 300 } |
| 300 def handle_action(self): | 301 def handle_action(self): |
| 301 ''' Determine whether there should be an _action called. | 302 ''' Determine whether there should be an _action called. |
| 302 | 303 |
| 303 The action is defined by the form variable :action which | 304 The action is defined by the form variable :action which |
| 306 "edit" -> self.edititem_action | 307 "edit" -> self.edititem_action |
| 307 "new" -> self.newitem_action | 308 "new" -> self.newitem_action |
| 308 "login" -> self.login_action | 309 "login" -> self.login_action |
| 309 "logout" -> self.logout_action | 310 "logout" -> self.logout_action |
| 310 "register" -> self.register_action | 311 "register" -> self.register_action |
| 312 "search" -> self.search_action | |
| 311 | 313 |
| 312 ''' | 314 ''' |
| 313 if not self.form.has_key(':action'): | 315 if not self.form.has_key(':action'): |
| 314 return None | 316 return None |
| 315 try: | 317 try: |
| 510 __file | 512 __file |
| 511 Create a file and attach it to the current node's | 513 Create a file and attach it to the current node's |
| 512 "files" property. Attach the file to the message created from | 514 "files" property. Attach the file to the message created from |
| 513 the __note if it's supplied. | 515 the __note if it's supplied. |
| 514 ''' | 516 ''' |
| 515 cn = self.classname | 517 cl = self.db.classes[self.classname] |
| 516 cl = self.db.classes[cn] | |
| 517 | 518 |
| 518 # check permission | 519 # check permission |
| 519 userid = self.db.user.lookup(self.user) | 520 userid = self.db.user.lookup(self.user) |
| 520 if not self.db.security.hasPermission('Edit', userid, cn): | 521 if not self.db.security.hasPermission('Edit', userid, self.classname): |
| 521 self.error_message.append( | 522 self.error_message.append( |
| 522 _('You do not have permission to edit %s' %cn)) | 523 _('You do not have permission to edit %(classname)s' % |
| 524 self.__dict__)) | |
| 525 return | |
| 523 | 526 |
| 524 # perform the edit | 527 # perform the edit |
| 525 props = parsePropsFromForm(self.db, cl, self.form, self.nodeid) | 528 try: |
| 526 | 529 props = parsePropsFromForm(self.db, cl, self.form, self.nodeid) |
| 527 # make changes to the node | 530 |
| 528 props = self._changenode(props) | 531 # make changes to the node |
| 529 | 532 props = self._changenode(props) |
| 530 # handle linked nodes | 533 |
| 531 self._post_editnode(self.nodeid) | 534 # handle linked nodes |
| 535 self._post_editnode(self.nodeid) | |
| 536 | |
| 537 except (ValueError, KeyError), message: | |
| 538 self.error_message.append(_('Error: ') + str(message)) | |
| 539 return | |
| 532 | 540 |
| 533 # commit now that all the tricky stuff is done | 541 # commit now that all the tricky stuff is done |
| 534 self.db.commit() | 542 self.db.commit() |
| 535 | 543 |
| 536 # and some nice feedback for the user | 544 # and some nice feedback for the user |
| 543 message = _('file added') | 551 message = _('file added') |
| 544 else: | 552 else: |
| 545 message = _('nothing changed') | 553 message = _('nothing changed') |
| 546 | 554 |
| 547 # redirect to the item's edit page | 555 # redirect to the item's edit page |
| 548 raise Redirect, '%s/%s%s?:ok_message=%s'%(self.base, cn, self.nodeid, | 556 raise Redirect, '%s/%s%s?:ok_message=%s'%(self.base, self.classname, |
| 549 urllib.quote(message)) | 557 self.nodeid, urllib.quote(message)) |
| 550 | 558 |
| 551 def newitem_action(self): | 559 def newitem_action(self): |
| 552 ''' Add a new item to the database. | 560 ''' Add a new item to the database. |
| 553 | 561 |
| 554 This follows the same form as the edititem_action | 562 This follows the same form as the edititem_action |
| 555 ''' | 563 ''' |
| 556 # check permission | 564 # check permission |
| 557 cn = self.classname | |
| 558 userid = self.db.user.lookup(self.user) | 565 userid = self.db.user.lookup(self.user) |
| 559 if not self.db.security.hasPermission('Edit', userid, cn): | 566 if not self.db.security.hasPermission('Edit', userid, self.classname): |
| 560 self.error_message.append( | 567 self.error_message.append( |
| 561 _('You do not have permission to create %s' %cn)) | 568 _('You do not have permission to create %s' %self.classname)) |
| 562 | 569 |
| 563 # XXX | 570 # XXX |
| 564 # cl = self.db.classes[cn] | 571 # cl = self.db.classes[cn] |
| 565 # if self.form.has_key(':multilink'): | 572 # if self.form.has_key(':multilink'): |
| 566 # link = self.form[':multilink'].value | 573 # link = self.form[':multilink'].value |
| 581 | 588 |
| 582 # render the newly created item | 589 # render the newly created item |
| 583 self.nodeid = nid | 590 self.nodeid = nid |
| 584 | 591 |
| 585 # and some nice feedback for the user | 592 # and some nice feedback for the user |
| 586 message = _('%(classname)s created ok')%{'classname': cn} | 593 message = _('%(classname)s created ok')%self.__dict__ |
| 594 except (ValueError, KeyError), message: | |
| 595 self.error_message.append(_('Error: ') + str(message)) | |
| 596 return | |
| 587 except: | 597 except: |
| 588 # oops | 598 # oops |
| 589 self.db.rollback() | 599 self.db.rollback() |
| 590 s = StringIO.StringIO() | 600 s = StringIO.StringIO() |
| 591 traceback.print_exc(None, s) | 601 traceback.print_exc(None, s) |
| 592 self.error_message.append('<pre>%s</pre>'%cgi.escape(s.getvalue())) | 602 self.error_message.append('<pre>%s</pre>'%cgi.escape(s.getvalue())) |
| 603 return | |
| 593 | 604 |
| 594 # redirect to the new item's page | 605 # redirect to the new item's page |
| 595 raise Redirect, '%s/%s%s?:ok_message=%s'%(self.base, cn, nid, | 606 raise Redirect, '%s/%s%s?:ok_message=%s'%(self.base, self.classname, |
| 596 urllib.quote(message)) | 607 nid, urllib.quote(message)) |
| 597 | 608 |
| 598 def genericedit_action(self): | 609 def genericedit_action(self): |
| 599 ''' Performs an edit of all of a class' items in one go. | 610 ''' Performs an edit of all of a class' items in one go. |
| 600 | 611 |
| 601 The "rows" CGI var defines the CSV-formatted entries for the | 612 The "rows" CGI var defines the CSV-formatted entries for the |
| 602 class. New nodes are identified by the ID 'X' (or any other | 613 class. New nodes are identified by the ID 'X' (or any other |
| 603 non-existent ID) and removed lines are retired. | 614 non-existent ID) and removed lines are retired. |
| 604 ''' | 615 ''' |
| 605 userid = self.db.user.lookup(self.user) | 616 userid = self.db.user.lookup(self.user) |
| 606 if not self.db.security.hasPermission('Edit', userid): | 617 if not self.db.security.hasPermission('Edit', userid, self.classname): |
| 607 raise Unauthorised, _("You do not have permission to access"\ | 618 raise Unauthorised, _("You do not have permission to access"\ |
| 608 " %(action)s.")%{'action': self.classname} | 619 " %(action)s.")%{'action': self.classname} |
| 609 w = self.write | 620 cl = self.db.classes[self.classname] |
| 610 cn = self.classname | |
| 611 cl = self.db.classes[cn] | |
| 612 idlessprops = cl.getprops(protected=0).keys() | 621 idlessprops = cl.getprops(protected=0).keys() |
| 613 props = ['id'] + idlessprops | 622 props = ['id'] + idlessprops |
| 614 | 623 |
| 615 # get the CSV module | 624 # get the CSV module |
| 616 try: | 625 try: |
| 636 nodeid, values = values[0], values[1:] | 645 nodeid, values = values[0], values[1:] |
| 637 found[nodeid] = 1 | 646 found[nodeid] = 1 |
| 638 | 647 |
| 639 # confirm correct weight | 648 # confirm correct weight |
| 640 if len(idlessprops) != len(values): | 649 if len(idlessprops) != len(values): |
| 641 w(_('Not enough values on line %(line)s'%{'line':line})) | 650 message=(_('Not enough values on line %(line)s'%{'line':line})) |
| 642 return | 651 return |
| 643 | 652 |
| 644 # extract the new values | 653 # extract the new values |
| 645 d = {} | 654 d = {} |
| 646 for name, value in zip(idlessprops, values): | 655 for name, value in zip(idlessprops, values): |
| 666 cl.retire(nodeid) | 675 cl.retire(nodeid) |
| 667 | 676 |
| 668 message = _('items edited OK') | 677 message = _('items edited OK') |
| 669 | 678 |
| 670 # redirect to the class' edit page | 679 # redirect to the class' edit page |
| 671 raise Redirect, '%s/%s?:ok_message=%s'%(self.base, cn, | 680 raise Redirect, '%s/%s?:ok_message=%s'%(self.base, self.classname, |
| 672 urllib.quote(message)) | 681 urllib.quote(message)) |
| 673 | 682 |
| 674 def _changenode(self, props): | 683 def _changenode(self, props): |
| 675 ''' change the node based on the contents of the form | 684 ''' change the node based on the contents of the form |
| 676 ''' | 685 ''' |
| 795 designator, property = value.split(':') | 804 designator, property = value.split(':') |
| 796 link, nodeid = hyperdb.splitDesignator(designator) | 805 link, nodeid = hyperdb.splitDesignator(designator) |
| 797 link = self.db.classes[link] | 806 link = self.db.classes[link] |
| 798 link.set(nodeid, **{property: nid}) | 807 link.set(nodeid, **{property: nid}) |
| 799 | 808 |
| 809 def search_action(self): | |
| 810 ''' Mangle some of the form variables. | |
| 811 | |
| 812 Set the form ":filter" variable based on the values of the | |
| 813 filter variables - if they're set to anything other than | |
| 814 "dontcare" then add them to :filter. | |
| 815 ''' | |
| 816 # add a faked :filter form variable for each filtering prop | |
| 817 props = self.db.classes[self.classname].getprops() | |
| 818 for key in self.form.keys(): | |
| 819 if not props.has_key(key): continue | |
| 820 if not self.form[key].value: continue | |
| 821 self.form.value.append(cgi.MiniFieldStorage(':filter', key)) | |
| 800 | 822 |
| 801 def remove_action(self, dre=re.compile(r'([^\d]+)(\d+)')): | 823 def remove_action(self, dre=re.compile(r'([^\d]+)(\d+)')): |
| 802 # XXX handle this ! | 824 # XXX handle this ! |
| 803 target = self.index_arg(':target')[0] | 825 target = self.index_arg(':target')[0] |
| 804 m = dre.match(target) | 826 m = dre.match(target) |
| 836 continue | 858 continue |
| 837 proptype = cl.properties[key] | 859 proptype = cl.properties[key] |
| 838 if isinstance(proptype, hyperdb.String): | 860 if isinstance(proptype, hyperdb.String): |
| 839 value = form[key].value.strip() | 861 value = form[key].value.strip() |
| 840 elif isinstance(proptype, hyperdb.Password): | 862 elif isinstance(proptype, hyperdb.Password): |
| 841 value = password.Password(form[key].value.strip()) | 863 value = form[key].value.strip() |
| 864 if not value: | |
| 865 # ignore empty password values | |
| 866 continue | |
| 867 value = password.Password(value) | |
| 842 elif isinstance(proptype, hyperdb.Date): | 868 elif isinstance(proptype, hyperdb.Date): |
| 843 value = form[key].value.strip() | 869 value = form[key].value.strip() |
| 844 if value: | 870 if value: |
| 845 value = date.Date(form[key].value.strip()) | 871 value = date.Date(form[key].value.strip()) |
| 846 else: | 872 else: |
