![]() ![]() | ![]() |
fixed problems with project editing preview
1: """This contains the class MPIWG Projects 2: for organizing and maintaining the different project pages 3: 4: $author dwinter - last change 26.06.2008 5: 6: """ 7: from Products.PageTemplates.PageTemplateFile import PageTemplateFile 8: from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate 9: from Products.ZCatalog.CatalogPathAwareness import CatalogAware 10: from Products.MPIWGBibliography.BibliographyManager import BibliographyManager 11: from OFS.Image import Image 12: from Globals import package_home 13: import urllib 14: import re 15: import os 16: import email 17: from types import * 18: import logging 19: import xmlhelper # Methoden zur Verwaltung der projekt xml 20: from OFS.SimpleItem import SimpleItem 21: from OFS.Folder import Folder 22: from OFS.Image import Image 23: from AccessControl import ClassSecurityInfo 24: from AccessControl import getSecurityManager 25: from bibliography import * 26: import time 27: from OFS.Cache import Cacheable 28: #import xml.dom.minidom 29: import sys 30: #from Ft.Xml.XPath import Evaluate 31: #from Ft.Xml.XPath.Context import Context 32: #from Ft.Xml.Domlette import NonvalidatingReader,PrettyPrint, Print 33: #from Ft.Xml import EMPTY_NAMESPACE 34: #import copy 35: #import updatePersonalWWW 36: 37: #import MPIWGStaff 38: 39: from MPIWGHelper import * 40: 41: import MPIWGRoot 42: import MPIWGLink 43: import MPIWGTemplate 44: 45: # die folgenden Klassen sind jetzt in einzelne Files ausgelagert aus Kompatibilitaetsgruenden, bleiben die Klassen hier noch drin. 46: # Sonst funktionieren die alten Webseiten nicht mehr. 47: 48: class MPIWGRoot(MPIWGRoot.MPIWGRoot): 49: """depricated""" 50: 51: class MPIWGLink(MPIWGLink.MPIWGLink): 52: """depricated""" 53: 54: class MPIWGTemplate(MPIWGTemplate.MPIWGTemplate): 55: """depricated""" 56: 57: class MPIWGProject_publication(Folder): 58: """publications object fuer project""" 59: 60: meta_type="MPIWGProject_publication" 61: def redirect(self,RESPONSE,url): 62: """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen""" 63: 64: timeStamp=time.time() 65: 66: if url.find("?")>-1: #giebt es schon parameter 67: addStr="&time=%s" 68: else: 69: addStr="?time=%s" 70: 71: RESPONSE.setHeader('Last-Modified',email.Utils.formatdate().split("-")[0]+'GMT') 72: logging.debug(email.Utils.formatdate()+' GMT') 73: RESPONSE.redirect(url+addStr%timeStamp) 74: 75: def editPublication(self,text=None,image1=None,image2=None,description=None,RESPONSE=None): 76: """edit a publication""" 77: 78: if (not text) and (not description): 79: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_publicationForm.zpt')).__of__(self) 80: return pt() 81: 82: 83: self.text=text[0:] 84: self.description=description 85: 86: if image1: 87: if hasattr(self,'publicationImage1'): 88: self.publicationImage1.manage_upload(image1) 89: else: 90: nO = Image('publicationImage1','',image1) 91: self._setObject('publicationImage1',nO) 92: 93: if image2: 94: if hasattr(self,'publicationImage2'): 95: self.publicationImage2.manage_upload(image2) 96: else: 97: nO = Image('publicationImage2','',image2) 98: self._setObject('publicationImage2',nO) 99: 100: 101: if RESPONSE: 102: self.redirect(RESPONSE,"../managePublications") 103: 104: class MPIWGProject_image(Image): 105: """Images for Projects""" 106: 107: meta_type="MPIWGProject_image" 108: 109: def showImage(self,imageUrl=None): 110: """show Images at an extra page""" 111: self.getContent('WEB_project_description',filter='yes') #get the content and store image infos into session 112: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','projectImageView.zpt')).__of__(self) 113: return pt() 114: 115: def editImage(self,file=None,caption=None,RESPONSE=None): 116: """edit the Image""" 117: if (not file) and (not caption): 118: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_imageForm.zpt')).__of__(self) 119: return pt() 120: 121: if file and (not file.filename.lstrip().rstrip()==""): 122: self.manage_upload(file) 123: 124: if caption: 125: self.caption=caption[0:] 126: 127: if RESPONSE: 128: self.redirect(RESPONSE,"../manageImages") 129: 130: class MPIWGProject(CatalogAware,Folder,Cacheable): 131: """Class for Projects""" 132: 133: def _p_resolveConflict(self, oldState, savedState, newState): 134: return newState 135: 136: security=ClassSecurityInfo() 137: meta_type='MPIWGProject' 138: default_catalog='ProjectCatalog' 139: def redirect(self,RESPONSE,url): 140: """mache ein redirect mit einem angehaengten time stamp um ein reload zu erzwingen""" 141: 142: timeStamp=time.time() 143: 144: if url.find("?")>-1: #giebt es schon parameter 145: addStr="&time=%s" 146: else: 147: addStr="?time=%s" 148: 149: RESPONSE.setHeader('Last-Modified',email.Utils.formatdate().split("-")[0]+'GMT') 150: logging.debug(email.Utils.formatdate()+' GMT') 151: RESPONSE.redirect(url+addStr%timeStamp) 152: 153: def decode(self,str): 154: """return unicode object""" 155: return unicodify(str) 156: 157: def sortedByPlace(self,metatype): 158: """find metatype and sort by place""" 159: def sort(x,y): 160: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0)) 161: 162: founds=self.ZopeFind(self,obj_metatypes=[metatype]); 163: 164: founds.sort(sort) 165: 166: return founds 167: 168: 169: def copyPublicationsToList(self,RESPONSE=None): 170: """copy publications in to list""" 171: 172: publicationTxt=self.getContent('WEB_related_pub') 173: 174: pubSplits=publicationTxt.split("<p>") 175: 176: for pubSplit in pubSplits: 177: pubSplit=pubSplit.replace("</p>","") 178: self.addPublication(pubSplit) 179: 180: if RESPONSE: 181: 182: self.redirect(RESPONSE,'managePublications') 183: 184: 185: def copyImageToMargin(self,RESPONSE=None): 186: """copy inline images to marginal images""" 187: 188: 189: #getImages from WEB_project_description 190: description=self.getContent('WEB_project_description') 191: 192: text2=description 193: splitted=text2.split("""<p class="picture">""") 194: 195: imageURLs=[] 196: imageCaptions=[] 197: for split in splitted[1:]: 198: tmp=split.split("</p>") 199: #return repr(splitted[1]) 200: 201: try: 202: imageURLs.append(tmp[0].split("\"")[1].encode('utf-8')) 203: except: 204: 205: try: 206: imageURLs.append(tmp[0].split("src=")[1].split(" ")[0].encode('utf-8')) 207: except: 208: imageURLs.append("") 209: 210: split2="</p>".join(tmp[1:]) 211: 212: 213: splitted=split2.split("""<p class="picturetitle">""") 214: if len(splitted)>1: 215: tmp=splitted[1].split("</p>") 216: imageCaptions.append(tmp[0].encode('utf-8')) 217: 218: 219: else: 220: #keine caption 221: 222: imageCaptions.append("") 223: 224: 225: #eintragen: 226: for imageURL in imageURLs: 227: filename=imageURL.split("/")[-1] 228: #lege neues images object an, mit leerem bild 229: 230: if self.ZopeFind(self,obj_ids=[filename]): 231: #existiert das bild schon, dann neuen filenamen 232: filename="project_image_"+filename 233: 234: self.addImage(None,imageCaptions[imageURLs.index(imageURL)],filename=filename) 235: #hole die bilddaten aus der url 236: url=self.absolute_url()+"/"+imageURL 237: #url=self.absolute_url()+"/"+filename 238: 239: try:#relative url 240: data=urllib.urlopen(url).read() 241: except: 242: try:#absolute 243: data=urllib.urlopen(self.imageURL).read() 244: except: 245: logger("MPIWG Project",logging.ERROR,"can't open: %s"%url) 246: 247: obj=getattr(self,filename) 248: obj.update_data(data) 249: 250: if RESPONSE: 251: 252: self.redirect(RESPONSE,'manageImages') 253: 254: def manageImages(self,imageName=None,op=None): 255: """managage images""" 256: 257: 258: if imageName and op: 259: if op=='up': 260: images=self.getImages() 261: for image in images: 262: if image[0]==imageName: 263: nr=images.index(image) 264: if not nr==0: 265: images[nr-1][1].place+=1 266: images[nr][1].place-=1 267: pass 268: elif op=='down': 269: images=self.getImages() 270: for image in images: 271: if image[0]==imageName: 272: nr=images.index(image) 273: if not (nr==len(images)-1): 274: images[nr+1][1].place-=1 275: images[nr][1].place+=1 276: pass 277: 278: 279: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_manageImagesForm.zpt')).__of__(self) 280: return pt() 281: 282: def managePublications(self,pubName=None,op=None): 283: """managage images""" 284: 285: 286: if pubName and op: 287: if op=='up': 288: publications=self.getPublications() 289: for publication in publications: 290: if publication[0]==pubName: 291: nr=publications.index(publication) 292: if not nr==0: 293: publications[nr-1][1].place+=1 294: publications[nr][1].place-=1 295: pass 296: elif op=='down': 297: publications=self.getPublications() 298: for publication in publications: 299: if publication[0]==pubName: 300: nr=publications.index(publication) 301: if not (nr==len(publications)-1): 302: publications[nr+1][1].place-=1 303: publications[nr][1].place+=1 304: pass 305: 306: 307: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_managePublicationsForm.zpt')).__of__(self) 308: return pt() 309: def hasExtendedPublicationList(self): 310: """test if extended publication list exists""" 311: if not hasattr(self,"publicationList"): 312: return False 313: else: 314: return True 315: 316: def createExtendedPublicationList(self,RESPONSE=None): 317: """erzeuge erweiterte publications liste""" 318: pl = BibliographyManager("publicationList","","institutsbiblio",self.connection_id) 319: self._setObject("publicationList", pl) 320: 321: 322: zt=ZopePageTemplate('index.html') 323: pl._setObject('index.html',zt) 324: default_content_fn = os.path.join(package_home(globals()), 325: 'zpt/showExtendedProjectBibliography.zpt') 326: text = open(default_content_fn).read() 327: zt.pt_edit(text, 'text/html') 328: 329: 330: if RESPONSE: 331: self.redirect(RESPONSE,"managePublications") 332: 333: 334: def getPublications(self): 335: """get all Publications""" 336: def sort_images(x,y): 337: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0)) 338: 339: publications=self.ZopeFind(self,obj_metatypes=['MPIWGProject_publication']) 340: 341: publications.sort(sort_images) 342: return publications 343: 344: def addPublication(self,text,RESPONSE=None): 345: """add an MPIWG_Publication""" 346: 347: name="publication_"+str(self.getLastPublicationNumber()+1) 348: 349: newPublication=MPIWGProject_publication(name) 350: 351: self._setObject(name,newPublication) 352: obj=getattr(self,name) 353: obj.text=text[0:] 354: obj.enabled=True; 355: obj.place=self.getLastPublicationNumber()+1 356: obj.id=name 357: 358: if RESPONSE is not None: 359: 360: self.redirect(RESPONSE,'managePublications') 361: 362: 363: def getLastPublicationNumber(self): 364: publications=self.getPublications() 365: 366: if not publications: 367: return 0 368: else: 369: return getattr(publications[-1][1],'place',0) 370: 371: def deletePublication(self,id,RESPONSE=None): 372: """delete Publication id""" 373: self.manage_delObjects([id]) 374: if RESPONSE: 375: 376: self.redirect(RESPONSE,'managePublications') 377: 378: def getImages(self): 379: """get all Images""" 380: 381: def sort_images(x,y): 382: return cmp(getattr(x[1],'place',0),getattr(y[1],'place',0)) 383: 384: 385: if (getattr(self,'imageURL','')!='') or (getattr(self,'imagecap','')!='') : 386: try: 387: self.addImage(None,getattr(self,'imagecap',''),RESPONSE=None,filename=getattr(self,'imageURL','')) 388: except: 389: pass 390: self.imageURL='' 391: self.imagecap='' 392: 393: images=self.ZopeFind(self,obj_metatypes=['MPIWGProject_image']) 394: 395: images.sort(sort_images) 396: return images 397: 398: def getLastImageNumber(self): 399: images=self.getImages() 400: 401: if not images: 402: return 0 403: else: 404: return getattr(images[-1][1],'place',0) 405: 406: def deleteImage(self,id,RESPONSE=None): 407: """delete Image id""" 408: try: 409: self.manage_delObjects([id]) 410: except: 411: logging.error("ERROR MPIWG: %s %s"%sys.exc_info()[0:2]) 412: if RESPONSE: 413: self.redirect(RESPONSE,'manageImages') 414: 415: 416: 417: def hasChildren(self,date=None,onlyActive=1,onlyArchived=1): 418: """check if project has children""" 419: 420: ct=self.getContexts(childs=self.getContent('xdata_05'), 421: depth=1,date=date,onlyActive=onlyActive) 422: 423: if ct and len(ct)>0: 424: return True 425: else: 426: return False 427: 428: 429: def addImage(self,fileHd,caption,RESPONSE=None,filename=None): 430: """add an MPIWG_Project_image""" 431: 432: if not filename: 433: filename=fileHd.filename 434: 435: if not fileHd: 436: fileHd=file(os.path.join(package_home(globals()),'blank.gif')) 437: 438: newImage=MPIWGProject_image(filename,filename,fileHd) 439: 440: self._setObject(filename,newImage) 441: obj=getattr(self,filename) 442: obj.caption=caption[0:] 443: obj.enabled=True; 444: obj.place=self.getLastImageNumber()+1 445: obj.id=filename 446: 447: if RESPONSE is not None: 448: 449: self.redirect(RESPONSE,'manageImages') 450: 451: def PrincipiaSearchSource(self): 452: """Return cataloguable key for ourselves.""" 453: return str(self) 454: 455: def versionHeader(self): 456: """version Header, gibt header text entsprechend der aktuellen version aus""" 457: 458: actualTime=time.localtime() 459: retTXT="""<h2>This is an outdated version, for the actual version please refer to <a href="%s">%s</a></h2>""" 460: s=self.aq_parent.absolute_url() 461: #print getattr(self,'archiveTime',actualTime) 462: if getattr(self,'archiveTime',actualTime)< actualTime: 463: return retTXT%(s,s) 464: else: 465: return "" 466: 467: def getActualVersion(self,date=None): 468: """actuelle version""" 469: def sortProjectsByTime(x,y): 470: return cmp(x[1].archiveTime,y[1].archiveTime) 471: 472: if not date: 473: if self.isActual(): 474: return self 475: else: 476: return None 477: 478: #suche ob aeltere versionen vorhanden sind 479: 480: finds=self.ZopeFind(self,obj_metatypes=['MPIWGProject']) 481: if not finds: #wenn nicht dann teste ob die aktuelle version schon existiert hat. 482: ad=getattr(self,'creationTime','20050101000000') 483: if int(date)>int(ad): 484: return self 485: else: 486: return None 487: 488: 489: else: 490: finds.sort(sortProjectsByTime) 491: 492: for find in finds: 493: #gehe durch die alten Projekte und finde das entprechende 494: if (int(find[1].archiveTime) > int(date)) and (int(date)>int(getattr(find[1],'creationTime','20050101000000'))): 495: return find[1] 496: 497: #kein passendes gefunden, dann teste ob das aktuelle in frage kommt 498: ad=getattr(self,'creationTime','20050101000000') 499: 500: if int(date)>int(ad): 501: 502: return self 503: else: 504: return None 505: 506: 507: def isActual(self): 508: """gibt 1 zurueck wenn aktuell, 0 sonst""" 509: actualTime=time.localtime() 510: 511: 512: #print getattr(self,'archiveTime',actualTime) 513: if getattr(self,'archiveTime',actualTime)< actualTime: 514: return 0 515: else: 516: return 1 517: 518: def copyObjectToArchive(self): 519: """kopiere aktuelles objekt ins archiv""" 520: logging.info("copytoarchive 1") 521: cb=self.aq_parent.manage_copyObjects(self.getId()) 522: logging.info("copytoarchive 2") 523: self.manage_pasteObjects(cb) 524: logging.info("copytoarchive 3") 525: actualTime=time.localtime() 526: 527: self.manage_renameObject(self.getId(),self.getId()+"_"+time.strftime("%Y%m%d%H%M%S",actualTime)) 528: logging.info("copytoarchive 4") 529: obj=getattr(self,self.getId()+"_"+time.strftime("%Y%m%d%H%M%S",actualTime)) 530: obj.setArchiveTime(time.strftime("%Y%m%d%H%M%S",actualTime)) 531: logging.info("copytoarchive 5") 532: ids=[x[0] for x in self.ZopeFind(obj,obj_metatypes=['MPIWGProject'])] 533: logging.info("copytoarchive 6") 534: obj.manage_delObjects(ids) 535: logging.info("copytoarchive 7") 536: 537: def setArchiveTime(self,time): 538: """set Archive Time""" 539: self.archiveTime=time[0:] 540: 541: def delArchiveTime(self): 542: """delete archive time""" 543: del self.archiveTime 544: 545: def versionManageForm(self): 546: """version Manage form:currently only set to invisible""" 547: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_versionManageForm.zpt')).__of__(self) 548: return pt() 549: 550: def versionManage(self,invisible=None,RESPONSE=None): 551: """version Manage form:currently only set to invisible""" 552: self.invisible=invisible 553: 554: if RESPONSE is not None: 555: 556: self.redirect(RESPONSE,'manage_main') 557: 558: 559: def crossLinker(self): 560: """experimental crosslinker""" 561: splitted=self.WEB_project_description[0].split() 562: new=[] 563: for split in splitted: 564: try: 565: found=self.DescriptionCatalog({'fulltext':split}) 566: 567: if len(found)>1: 568: 569: new.append("<a href=%s>%s</a>"%(split,split)) 570: else: 571: new.append(split) 572: except: 573: new.append(split) 574: return " ".join(new) 575: 576: 577: 578: 579: def generateTemplate(self,RESPONSE=None): 580: """Erzeuge Template fuer defined fields not_used""" 581: 582: id="index_html" 583: title=id 584: if self._getOb('index_html'): 585: self._delObject('index_html') 586: 587: 588: newObj=ZopePageTemplate(id,'TEXT') 589: self._setObject(id,newObj) 590: #self.manage_addPageTemplate(id,title) 591: if RESPONSE is not None: 592: self.redirect(RESPONSE,'manage_main') 593: 594: def __init__(self, id, argv=None): 595: """initiere classe""" 596: 597: self.creationTime=time.strftime("%Y%m%d%H%M%S",time.localtime())[0:] 598: self.id=id 599: self.title=id 600: self.isActiveFlag=True #Flag is true is the project is still active, False if accomplished 601: self.responsibleScientistsList=[] # enthaelt die Lister der verantwortlichen Wissenschaftler in der Form (NAME, KEY), key ist "" flass Wissenschaftler nicht an unserem Haus 602: 603: if argv: 604: for arg in definedFields: 605: try: 606: setattr(self,arg,argv[arg]) 607: except: 608: setattr(self,arg,"") 609: else: 610: for arg in definedFields: 611: setattr(self,arg,'') 612: 613: manage_options = Folder.manage_options+( 614: {'label':'Load New File','action':'loadNewFileForm'}, 615: {'label':'Edit ProjectInfo','action':'editMPIWGProjectForm'}, 616: {'label':'Edit BasisInfo','action':'editMPIWGBasisForm'}, 617: {'label':'Edit Publications','action':'editMPIWGRelatedPublicationsForm'}, 618: {'label':'Edit Themes & Disciplines','action':'editMPIWGDisciplinesThemesForm'}, 619: {'label':'Versionmanager','action':'versionManageForm'}, 620: ) 621: 622: 623: def isActiveProject(self): 624: """check if the project is still active, default is true, set to false is the project is accomplished""" 625: return getattr(self,'isActiveFlag',True) 626: 627: def isArchivedProject(self): 628: """check if the project is archived""" 629: 630: completed=self.getCompletedAt() 631: 632: #completed leer 633: if completed=="" : 634: return False; 635: if completed == 0: 636: return False; 637: 638: 639: return True 640: 641: 642: def setActiveFlag(self,status=True): 643: """set the active flag""" 644: self.isActiveFlag=status 645: 646: def setCompletedAt(self,date): 647: """set the date of completion, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY""" 648: #logging.info("DATE:"+repr(date)) 649: transformedDate=self.transformDate(date); 650: #logging.info("transformed"+repr(transformedDate)) 651: if transformedDate is not None: 652: setattr(self,"completedAt",transformedDate) 653: return True; 654: else: 655: return False; 656: 657: def setStartedAt(self,date): 658: """set the date of start, date should be in the form DD.MM.YYYY or MM.YYYY or YYYY""" 659: #logging.info("DATE:"+repr(date)) 660: transformedDate=self.transformDate(date); 661: #logging.info("transformed"+repr(transformedDate)) 662: if transformedDate is not None: 663: setattr(self,"startedAt",transformedDate) 664: return True; 665: else: 666: return False; 667: 668: def getCompletedAt(self): 669: """gibt das transformierte Datum zurueck, an dem das Projekt beendet wurde.""" 670: date=getattr(self,'completedAt','') 671: 672: if date: 673: return self.reTransformDate(date); 674: else: 675: return "" 676: # test ob parent abgeschlossen ist 677: try: #TODO: ersetzte try except durch vernuenftige abfrage 678: ct=self.getContexts(parents=self.getContent('xdata_05'),depth=1) 679: if (len(ct)>0): #is there are parent 680: return ct[0][0].getCompletedAt() 681: return ''; 682: except: 683: return ''; 684: 685: def getStartedAt(self): 686: """gibt das transformierte Datum zurueck, an dem Projekt begonnen wurde.""" 687: date=getattr(self,'startedAt','') 688: if date: 689: return self.reTransformDate(date); 690: else: 691: return ''; 692: 693: def reTransformDate(self,date): 694: """transformiert , transformdate zurueck""" 695: year=int(date/10000) 696: month=int((date-year*10000)/100) 697: day=int((date-year*10000-month*100)) 698: if (day==0) and (month==0): 699: return """%s"""%year; 700: if day==0 : 701: return """%s.%s"""%(month,year); 702: 703: return """%s.%s.%s"""%(day,month,year); 704: 705: 706: def transformDate(self,date): 707: """transformiert ein Datum von DD.MM.YYYY, MM.YYYY,YYYY nach YYYYMMDD, alle nicht angebenen Werte 708: werden auf 0 gesetzt, es wird null zurueckgegeben falls das Datum ungueltig ist""" 709: 710: if (date==None): 711: return None; 712: 713: 714: if (date.lstrip().rstrip()=="" ) : 715: return ""; 716: 717: splitted=date.split(".") 718: length=len(splitted) 719: year=0 720: month=0 721: day=0 722: if length > 3: 723: return ""; 724: if length==3: 725: day = int(splitted[0]) 726: if length>1: 727: month=int(splitted[length-2]) 728: 729: if length > 0: 730: try: 731: year = int(splitted[length-1]) 732: except: 733: pass 734: 735: ## logging.info("month:"+(month)) 736: if not (0<=month<13): 737: return None; 738: 739: if not(0<=day<32): 740: return None; 741: 742: if (year>0) and (year<1900): #jahr nicht vierstellig eingegeben 743: year=2000+year; 744: return year*10000+month*100+day 745: 746: 747: 748: def checkDate(self,date): 749: """teste ob zum Zeitpunkt date eine andere version existierte""" 750: 751: 752: def sortProjectsByTime(x,y): 753: return cmp(x[1].archiveTime,y[1].archiveTime) 754: 755: #suche ob aeltere versionen vorhanden sind 756: 757: finds=self.ZopeFind(self,obj_metatypes=['MPIWGProject']) 758: if not finds: #wenn nicht dann teste ob die aktuelle version schon existiert hat. 759: ad=getattr(self,'creationTime','20050101000000') 760: if int(date)>int(ad): 761: return self.REQUEST['URL1']+"/"+self.getId() 762: else: 763: return self.REQUEST['URL1']+"/no_project" 764: 765: 766: else: 767: finds.sort(sortProjectsByTime) 768: 769: for find in finds: 770: #gehe durch die alten Projekte und finde das entprechende 771: if (int(find[1].archiveTime) > int(date)) and (int(date)>int(getattr(find[1],'creationTime','20050101000000'))): 772: return self.REQUEST['URL1']+"/"+find[1].getId() 773: 774: #kein passendes gefunden, dann teste ob das aktuelle in frage kommt 775: ad=getattr(self,'creationTime','20050101000000') 776: 777: if int(date)>int(ad): 778: 779: return self.REQUEST['URL1']+"/"+self.getId() 780: else: 781: return self.REQUEST['URL1']+"/no_project" 782: 783: 784: def no_project(self): 785: """warnung: project noch nicht existent""" 786: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','no_project')).__of__(self) 787: return pt() 788: 789: 790: def harvest_page(self,context=None): 791: """seite fuer harvesting fuer die Projektsuche""" 792: if not context: 793: context=self 794: 795: if self.isActiveProject() and self.isActual(): 796: ext=getattr(self,"harvest_main",None) 797: if ext: 798: return getattr(self,ext.getId())() 799: 800: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','harvest_main')).__of__(context) 801: 802: 803: return pt() 804: 805: def index_html(self,request=True,context=None): 806: """show homepage""" 807: 808: bound_names={} 809: 810: if not context: 811: context=self 812: if request: 813: if self.REQUEST.has_key('date') and self.REQUEST.SESSION.get('MPI_redirected',None)==None: 814: self.REQUEST.SESSION['MPI_redirected']=1 815: self.REQUEST.RESPONSE.redirect(self.checkDate(self.REQUEST['date'])+"?date="+self.REQUEST['date']) 816: else: 817: self.REQUEST.SESSION['MPI_redirected']=None 818: 819: #ext=self.ZopeFind(self.aq_parent,obj_ids=["project_main"]) 820: 821: 822: request2=getattr(self,'REQUEST',None) 823: 824: if request2 is not None: 825: response = request2.response 826: if not response.headers.has_key('content-type'): 827: response.setHeader('content-type', 'text/html') 828: 829: security = getSecurityManager() 830: bound_names['user'] = security.getUser() 831: 832: # Retrieve the value from the cache. 833: keyset = None 834: if self.ZCacheable_isCachingEnabled(): 835: 836: # Prepare a cache key. 837: keyset = {'here': self, 'params':request2['QUERY_STRING']} 838: 839: result = self.ZCacheable_get(keywords=keyset) 840: 841: if result is not None: 842: # Got a cached value. 843: return result 844: 845: pt = getTemplate(self, "project_main") 846: # Execute the template in a new security context. 847: security.addContext(self) 848: 849: try: 850: #logging.debug("index_html pt=%s"%repr(pt)) 851: result = pt.pt_render(extra_context=bound_names) 852: #logging.debug("index_html result=%s"%repr(result)) 853: if keyset is not None: 854: # Store the result in the cache. 855: self.ZCacheable_set(result, keywords=keyset) 856: 857: return result 858: finally: 859: security.removeContext(self) 860: 861: 862: 863: def index_html_old(self,request=True,context=None): 864: """show homepage""" 865: if not context: 866: context=self 867: if request: 868: if self.REQUEST.has_key('date') and self.REQUEST.SESSION.get('MPI_redirected',None)==None: 869: self.REQUEST.SESSION['MPI_redirected']=1 870: self.REQUEST.RESPONSE.redirect(self.checkDate(self.REQUEST['date'])+"?date="+self.REQUEST['date']) 871: else: 872: self.REQUEST.SESSION['MPI_redirected']=None 873: 874: #ext=self.ZopeFind(self.aq_parent,obj_ids=["project_main"]) 875: 876: ext=getattr(self,"project_main",None) 877: if ext: 878: return getattr(self,ext.getId())() 879: 880: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','project_main')).__of__(context) 881: 882: return pt() 883: 884: 885: def getDataFields(self): 886: """giveListofDatafields""" 887: ret=[] 888: for x in range(1,14): 889: if not x in [6,10,9]: # not used fields 890: ret.append('xdata_%02i'%x) 891: return ret 892: 893: def getDefinedFields(self): 894: """show all defined fields""" 895: 896: return definedFields 897: 898: def getAttribute(self,field): 899: """get attrbiute""" 900: return getattr(self,field) 901: 902: def getContent(self,field,filter=None): 903: """Inhalt des Feldes""" 904: #logging.debug("getContent field=%s filter=%s"%(field,filter)) 905: 906: if field=="short_title": 907: text = self.getContent("xdata_07") 908: if text=="": 909: text = self.getContent("WEB_title") 910: return text 911: 912: text=u'' 913: 914: for x in getattr(self,field): 915: 916: try: 917: text +=x 918: except: 919: text = x 920: 921: 922: 923: try: 924: if text[len(text)-1]==";": 925: text=text[0:len(text)-1] 926: 927: 928: except: 929: pass 930: 931: if text=='': ## wozu die folgenden Zeilen?? 932: text2=text 933: else: 934: text2=re.sub(r';([^\s])','; \g<1>',text) 935: 936: if field=="WEB_project_description":##Jedenfalls darf letzteres nicht gemacht werden, falls normaler text 937: text2=text 938: 939: #teste ob ergebnis leer und header dann nehme title 940: 941: if (text2=='') and (field=='WEB_project_header'): 942: return self.getContent('WEB_title') 943: 944: if filter: 945: splitted=text2.split("""<p class="picture">""") 946: if len(splitted)>1: 947: tmp=splitted[1].split("</p>") 948: #return repr(splitted[1]) 949: try: 950: self.imageURL=tmp[0].split("\"")[1].encode('utf-8') 951: except: 952: try: 953: self.imageURL=tmp[0].split("src=")[1].split(" ")[0].encode('utf-8') 954: except: 955: self.imageURL="" 956: 957: split2="</p>".join(tmp[1:]) 958: 959: text3=splitted[0]+split2 960: 961: splitted=text3.split("""<p class="picturetitle">""") 962: if len(splitted)>1: 963: tmp=splitted[1].split("</p>") 964: self.imagecap=tmp[0].encode('utf-8') 965: 966: split4="".join(tmp[1:]) 967: 968: text5=splitted[0]+split4 969: else: 970: #keine caption 971: text5=text3 972: else: 973: #kein bild 974: text5=text2 975: else: 976: text5=text2 977: 978: #teste ob WEB_project_description und keine fuehrenden p tags 979: if (len(text5)>4) and (not text5[0:3]=='<p>') and (field=='WEB_project_description'): 980: text5= "<p>"+text5+"</p>" 981: 982: 983: #filter image 984: 985: text5=text5.lstrip().rstrip() #loescher leerzeichen und einzelndes br 986: if (text5=="<br>") or (text5=="<br/>"): 987: text5="" 988: 989: #logging.debug("getcontent: field=%s filter=%s -> %s"%(field,filter,repr(text5))) 990: return unicodify(text5) 991: #return utf8ify(text5) # return as utf-8 byte string 992: 993: 994: def showImagesOfPage(self,imageUrl=None): 995: """show Images of project""" 996: self.getContent('WEB_project_description',filter='yes') #get the content and store image infos into session 997: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','projectImageView.zpt')).__of__(self) 998: return pt() 999: 1000: 1001: def show_html(self): 1002: """simple index""" 1003: #return "HI" 1004: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_index.zpt')).__of__(self) 1005: return pt() 1006: 1007: def saveFromPreview(self): 1008: """save content aus preview""" 1009: self.WEB_project_description=self.previewTemplate.WEB_project_description[0:] 1010: self.REQUEST.RESPONSE.redirect("./index.html") 1011: 1012: def saveEditedContent(self,kupu=None,preview=None): 1013: """save Edited content""" 1014: #logging.debug("saveEditedContent kupu=%s preview=%s"%(kupu,preview)) 1015: 1016: if preview: 1017: kupu=preview 1018: #find content of body tags 1019: start=kupu.find("<body>") 1020: end=kupu.find("</body>") 1021: newcontent= kupu[start+6:end] 1022: 1023: if preview: 1024: return self.preview(newcontent) 1025: 1026: self.copyObjectToArchive() 1027: self.ZCacheable_invalidate() 1028: self.WEB_project_description=newcontent[0:] 1029: 1030: self.REQUEST.RESPONSE.redirect("./index.html") 1031: 1032: return True 1033: 1034: security.declareProtected('View management screens','edit') 1035: def edit(self,western=None): 1036: """Edit pages""" 1037: if western: 1038: self.REQUEST.RESPONSE.setCookie("MP_debug_code","western",path="/") 1039: 1040: 1041: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGProjectNeu.zpt')).__of__(self) 1042: return pt() 1043: 1044: edit_MPIWGProject_main = PageTemplateFile('zpt/edit_MPIWGProject_main', globals()) 1045: 1046: def getPathStyle(self, path, selected, style=""): 1047: """returns a string with the given style + 'sel' if path == selected.""" 1048: 1049: if path == selected: 1050: return style + 'sel' 1051: else: 1052: return style 1053: 1054: def getLabel(self): 1055: """returns label (or title) of this project""" 1056: l = self.getContent('xdata_07') 1057: if l: 1058: return l 1059: l = self.getContent('WEB_title') 1060: if l: 1061: return l 1062: return self.title 1063: 1064: def getBreadcrumbs(self): 1065: """return list of breadcrumbs from here to the root""" 1066: crumbs = [] 1067: # skip direct parent Folder /projects/ 1068: parent = self.aq_parent.aq_parent 1069: # get parents breadcrumbs 1070: if hasattr(parent, 'getBreadcrumbs'): 1071: crumbs = parent.getBreadcrumbs() 1072: 1073: # try to get acquisition URL from parent 1074: if hasattr(parent, 'absolute_url'): 1075: baseUrl = "%s/%s/"%(parent.absolute_url(), 'projects') 1076: else: 1077: baseUrl = "/en/research/projects/" 1078: 1079: # add in the internal project hierarchy 1080: 1081: ct=self.getContexts(parents=self.getContent('xdata_05')) 1082: # start with grandparents 1083: ct.reverse() 1084: for c in ct: 1085: label = shortenString(c[0].getLabel(), 13) 1086: crumbs.append((label, baseUrl+c[0].getId(), c[0])) 1087: 1088: # add this project 1089: crumbs.append((self.getLabel(), baseUrl+self.getId(), self)) 1090: 1091: return crumbs 1092: 1093: def getRootProject(self): 1094: """returns the root (=top level) project of the current project""" 1095: 1096: ct=self.getContexts(parents=self.getContent('xdata_05')) 1097: if len(ct) > 0: 1098: return ct[-1][0] 1099: else: 1100: return self 1101: 1102: 1103: def preview(self,description): 1104: """preview""" 1105: #logging.debug("preview description=%s"%description) 1106: tmpPro=getattr(self,"previewTemplate",None) 1107: if not tmpPro: 1108: tmpPro=MPIWGProject("previewTemplate") 1109: self._setObject("previewTemplate",tmpPro) 1110: for field in definedFields: 1111: setattr(tmpPro,field,getattr(self,field)) 1112: tmpPro.WEB_project_description=description[0:] 1113: tmpPro.invisible=True 1114: pt=PageTemplateFile('zpt/previewFrame.zpt',globals()).__of__(self) 1115: return pt() 1116: 1117: #return self.REQUEST.RESPONSE.redirect(self.REQUEST['URL1']+"/previewTemplate") 1118: 1119: 1120: def getWebProject_description(self): 1121: """get description""" 1122: debug = self.REQUEST.cookies.get("MP_debug_code",None) 1123: 1124: if debug and debug=="western": 1125: return """ 1126: <html> 1127: <head> 1128: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 1129: </head> 1130: <body>%s</body> 1131: </html> 1132: """%self.WEB_project_description[0] 1133: 1134: return """ 1135: <html> 1136: <head> 1137: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 1138: </head> 1139: <body>%s</body> 1140: </html> 1141: """%self.getContent('WEB_project_description') 1142: 1143: 1144: 1145: def editMPIWGProjectForm(self): 1146: """editform""" 1147: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGProject.zpt')).__of__(self) 1148: return pt() 1149: 1150: def isResponsibleScientist(self,key): 1151: """teste ob eine Person in der Liste der respl. scientists auftaucht""" 1152: #logging.info("XXXXXXXXXXXXX"+repr(self.responsibleScientistsList)) 1153: 1154: 1155: keys = [unicodify(x[1]) for x in getattr(self,"responsibleScientistsList",[])] 1156: #logging.error("RESP. SCIEN:%s"%getattr(self,"responsibleScientistsList",[])) 1157: #logging.error("RESP. SCIEN:%s"%unicodify(key)) 1158: 1159: if unicodify(key) in keys: 1160: return True 1161: else: 1162: return False 1163: 1164: def getPersonKeyList(self): 1165: """gibt die key Liste der beteiligten Personen zurueck (utf8 codiert)""" 1166: #logging.error("getPersonKeyList:%s"%getattr(self,'responsibleScientistsList',[])) 1167: try: 1168: return [utf8ify(x[1]) for x in getattr(self,'responsibleScientistsList',[])] 1169: except: 1170: return[] 1171: 1172: 1173: def myCapitalize(self,txt): 1174: """kapitalisiere auch Namen mit -""" 1175: splitted=[x.capitalize() for x in txt.split("-")] 1176: return "-".join(splitted) 1177: 1178: def getNamesOrdered(self,list): 1179: """Sortiert die Liste nach der Reihenfolge in xdata_01""" 1180: 1181: nameList=self.getContent('xdata_01') 1182: if nameList.find(";")>-1: # rate Trenner ist ; 1183: names=nameList.split(";") 1184: else: 1185: names=nameList.split(",") 1186: 1187: self._v_names=[] 1188: for name in names: 1189: self._v_names.append(name.rstrip().lstrip()) 1190: 1191: 1192: def sort(x,y): 1193: try: 1194: return cmp(self._v_names.index(x[0]),self._v_names.index(y[0])) 1195: except: 1196: return 0 1197: 1198: list.sort(sort) 1199: 1200: return list 1201: 1202: ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze 1203: 1204: 1205: 1206: 1207: def identifyNames(self,nameList): 1208: """Bekommt eine Komma oder Semikolon getrennte Liste mit Name der Form Vorname MittelName(n) Nachname 1209: und ordnet diese dann Mitarbeiter IDs zu falls es schone eine Liste gibt wird im Projekte gibt wird diese Upgedated. 1210: @param nameList 1211: """ 1212: 1213: if nameList.find(";")>-1: # rate Trenner ist ; 1214: names=nameList.split(";") 1215: 1216: else: 1217: names=nameList.split(",") 1218: 1219: ##nameList=nameList.replace(";",",") # falls ; als Trenner ersetze 1220: returnNamesDict={} 1221: 1222: 1223: for name in names: 1224: name=name.lstrip().rstrip() 1225: nameSplitted = name.split(" ") 1226: if len(nameSplitted)>1: #vor und nachname angegeben) 1227: 1228: lastname=nameSplitted[-1] 1229: firstname=nameSplitted[0] 1230: else: 1231: firstname ="" 1232: lastname=nameSplitted[0] 1233: 1234: #finde Mitarbeiter mit den entsprechenden Name 1235: 1236: firstname=self.myCapitalize(firstname).encode('utf-8') 1237: lastname=self.myCapitalize(lastname).encode('utf-8') 1238: logging.info("Search: %s %s %s"%(name,repr(firstname),repr(lastname))) 1239: try: 1240: cataloggedNames=self.MembersCatalog(firstName=firstname,lastName=lastname) 1241: except: 1242: cataloggedNames=[] 1243: logging.error("ERROR: identifyNames %s %s"%sys.exc_info()[0:2]) 1244: 1245: #Teste ob die ensprechenden Namen schon der Liste zu geordnet sind 1246: #if not hasattr(self,'responsibleScientistsList'): 1247: # self.responsibleScientistsList={} 1248: # 1249: # if name in self.responsibleScientistsList.values() 1250: 1251: if len(cataloggedNames)>0: 1252: returnNamesDict[name]=cataloggedNames 1253: else: 1254: returnNamesDict[name]=[] 1255: 1256: logging.error("id: %s"%repr(returnNamesDict)) 1257: return returnNamesDict 1258: 1259: def editMPIWGProject(self,RESPONSE=None,fromEdit=None): 1260: """edit the project and archive the old version""" 1261: 1262: self.copyObjectToArchive() # archive the object 1263: self.ZCacheable_invalidate() 1264: 1265: for x in definedFields: 1266: if self.REQUEST.has_key(x): 1267: 1268: setattr(self,x,[self.REQUEST[x].decode('utf-8')]) 1269: 1270: 1271: 1272: 1273: completedAt = self.REQUEST.get('completedAt') 1274: if not self.setCompletedAt(completedAt): 1275: RESPONSE.redirect('./editMPIWGBasisEditor?error="dateWrong') 1276: 1277: startedAt = self.REQUEST.get('startedAt') 1278: if not self.setStartedAt(startedAt): 1279: RESPONSE.redirect('./editMPIWGBasisEditor?error="dateWrong') 1280: 1281: if self.REQUEST.has_key('historicalNames'): 1282: self.en.changeHistoricalNames(self.getId(),self.REQUEST['historicalNames'].split("\n")) 1283: 1284: if self.REQUEST.has_key('active'): 1285: self.setActiveFlag(True) 1286: else: 1287: self.setActiveFlag(False) 1288: 1289: self.responsibleScientistsList=[] # setze die Liste der verantwortlichen Wissenschaftler zurueck 1290: 1291: names={} 1292: keys={} 1293: tmpList=[] 1294: for key in self.REQUEST.keys(): #gehe durch das Formular 1295: splitted=key.split("_") 1296: if splitted[0]=="responsibleScientist": #wenn es ein Feld der Form reponsibleScientist_nr_KEY gibt 1297: nr=splitted[2] 1298: if splitted[1]=="name": 1299: names[nr]=self.REQUEST[key] 1300: elif splitted[1]=="key": 1301: keys[nr]=self.REQUEST[key] 1302: 1303: 1304: for nr in names.keys():#schreibe keys und namen in die Liste, stelle ausserdem sicher, dass name unicode 1305: tmpList.append((unicodify(names[nr]),unicodify(keys.get(nr,"")))) 1306: 1307: self.responsibleScientistsList=tmpList 1308: if fromEdit and (RESPONSE is not None): 1309: #RESPONSE.redirect('./editMPIWGBasisEditor') 1310: return self.editMPIWGBasisEditor(identifiedNames=self.identifyNames(self.decode(self.REQUEST.get('xdata_01','')))) 1311: 1312: else: 1313: if RESPONSE is not None: 1314: RESPONSE.redirect('manage_main') 1315: 1316: 1317: 1318: security.declareProtected('View managment screens','editMPIWGDisciplinesThemesEditor') 1319: def editMPIWGDisciplinesThemesEditor(self): 1320: """edit from edit""" 1321: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemesNeu.zpt')).__of__(self) 1322: return pt() 1323: 1324: 1325: def editMPIWGDisciplinesThemesForm(self): 1326: """edit the disciplines and themes Form""" 1327: 1328: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGDisciplinesThemes.zpt')).__of__(self) 1329: return pt() 1330: 1331: def editMPIWGDisciplinesThemes(self,disciplines=None,themes=None,RESPONSE=None,fromEdit=None): 1332: """edit disciplin and form""" 1333: if disciplines: 1334: if type(disciplines) is StringType: 1335: self.xdata_09=disciplines 1336: else: 1337: self.xdata_09=";".join(disciplines) 1338: else: 1339: self.xdata_09="" 1340: if themes: 1341: if type(themes) is StringType: 1342: self.xdata_10=themes 1343: else: 1344: self.xdata_10=";".join(themes) 1345: else: 1346: self.xdata_10="" 1347: 1348: if fromEdit and (RESPONSE is not None): 1349: self.redirect(RESPONSE,'./editMPIWGDisciplinesThemesEditor') 1350: 1351: else: 1352: if RESPONSE is not None: 1353: RESPONSE.redirect('manage_main') 1354: 1355: 1356: def isChecked(self,wert,list): 1357: """check if wert is in ; seperated list""" 1358: 1359: #felder sind manchmnal als liste mit einem element definiert 1360: if type(list) is StringType or UnicodeType: 1361: splitted=list.split(";") 1362: else: 1363: splitted=list[0].split(";") 1364: 1365: splitted=[y.rstrip().lstrip() for y in splitted] 1366: 1367: for x in splitted: 1368: x=re.sub(r"[^A-z ]","",x) 1369: if (not x==u'') and x in wert: 1370: return 1 1371: return 0 1372: 1373: security.declareProtected('View management screens','editMPIWGBasisEditor') 1374: def editMPIWGBasisEditor(self, identifiedNames=None): 1375: 1376: """editform""" 1377: if not identifiedNames: 1378: identifiedNames=self.identifyNames(self.getContent('xdata_01')) 1379: # identifiedNames=self.getFullNameEntries() 1380: 1381: logging.error("IdentifiedNames: %s"% repr(identifiedNames)) 1382: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGBasisNeu.zpt')).__of__(self) 1383: return pt(identifiedNames=identifiedNames) 1384: 1385: security.declareProtected('View management screens','editMPIWGBasisForm') 1386: def editMPIWGBasisForm(self): 1387: """editform""" 1388: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGBasis.zpt')).__of__(self) 1389: return pt() 1390: 1391: security.declareProtected('View management screens','editMPIWGRelatedPublicationsForm') 1392: def editMPIWGRelatedPublicationsForm(self): 1393: """Edit related Publications""" 1394: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','edit_MPIWGRelatedPublications.zpt')).__of__(self) 1395: return pt() 1396: 1397: 1398: def loadNewFileForm(self): 1399: """Neues XML-File einlesen""" 1400: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','MPIWGProject_newfile.zpt')).__of__(self) 1401: return pt() 1402: 1403: def loadNewFile(self,RESPONSE=None): 1404: """einlesen des neuen files""" 1405: fileupload=self.REQUEST['fileupload'] 1406: if fileupload: 1407: file_name=fileupload.filename 1408: filedata=fileupload.read() 1409: 1410: argv=xmlhelper.proj2hash(filedata) 1411: #print argv.keys() 1412: for arg in definedFields: 1413: 1414: #print arg,argv[arg],getattr(self,arg) 1415: try: 1416: temp=argv[arg][0:] 1417: #old=getattr(self,arg) 1418: setattr(self,arg,temp) 1419: #print old,getattr(self,arg) 1420: except: 1421: """nothing""" 1422: 1423: if RESPONSE is not None: 1424: RESPONSE.redirect('manage_main') 1425: 1426: def manage_addMPIWGProjectForm(self): 1427: """form for adding the project""" 1428: pt=PageTemplateFile(os.path.join(package_home(globals()),'zpt','addMPIWGProjectForm.zpt')).__of__(self) 1429: return pt() 1430: 1431: def manage_addMPIWGProject(self,id,RESPONSE=None): 1432: """method to add a project""" 1433: #print argv 1434: fileupload=self.REQUEST.get('fileupload',None) 1435: if fileupload: 1436: 1437: file_name=fileupload.filename 1438: filedata=fileupload.read() 1439: 1440: argv=xmlhelper.proj2hash(filedata) 1441: 1442: #print argv 1443: newObj=MPIWGProject(id,argv) 1444: else: 1445: newObj=MPIWGProject(id) 1446: 1447: self._setObject(id,newObj) 1448: 1449: 1450: if RESPONSE is not None: 1451: RESPONSE.redirect('manage_main')