Making Umbraco life easier with a little help of Python
I needed to copy all properties from one document type to another. The web site structure is not made with parent document types from the beginning since I had problems with that approach (mostly because of different standard values and descriptions on different document types).
Also – I like to be able to do structure by code and not only by UI. So I went for the approach creating documenttype properties by code.
C# might of course be the language of most peoples choice but I prefer the possibility for immediate response that I have with Python. I have created a “PyPad for Umbraco” which I’m using sometimes. Its an instant code window for Python in the Umbraco dev section, the only thing it does is to provide a multi line textbox and a button which executes the code in the textbox with the umbraco IronPython Engine.
So with my script in place I just want to write this code in PyPad:
dtSource = web.DocumentType.GetByAlias("oneDocTypeAlias") dtTarget = web.DocumentType.GetByAlias("anotherDocTypeAlias") copyDocumentTypeProperties(dtSource,dtTarget)
and the result given would be:
Added tab "Content" Added property "Header" Existing property "Introduction" Added property "BodyText"
In Umbraco 4.5 code is actually being run on save in Umbraco UI code editor, so there the need of a “PyPad” there is not obvious, but my current site is running 4.0x and PyPad also gives me a possibility to print results.
Copy document content
I also need to copy document content occassionally, I want to copy all existing properties from one document to another. (With an boolean option makeChanges to make changes+save or just check for changes)
docSource = web.Document(2764) docTarget = web.Document(19213) copyAllPropertyValues(docSource,docTarget,True)
and the result given would be:
Changed property with alias "Header" from "Nnnno" to "Yyyyes"
Here’s the complete Python scripts
Copy document type properties
Use it at your own risk, and not on a live site until you are 100% sure it works as you’d expect!:
from umbraco.cms.businesslogic import web def findTabCaptionById(dt, id): for t in dt.getVirtualTabs: if t.Id == id: return t.Caption return "" def findTabByCaption(dt, caption): for tab in dt.getVirtualTabs: if tab.Caption == caption: return tab.Id return -1 def findOrAddTabByCaption(dt,caption): id = findTabByCaption(dt,caption) if id ==-1: print "Added tab : " + caption + "<br/>" return dt.AddVirtualTab(caption) else: return id def containsPropertyTypeByAlias(dt, alias): for c in dt.PropertyTypes: if c.Alias == alias: return True return False def copyDocumentTypeProperties(dtSource, dtTarget): for ptSource in dtSource.PropertyTypes: if not containsPropertyTypeByAlias(dtTarget,ptSource.Alias): dtTarget.AddPropertyType(ptSource.DataTypeDefinition, ptSource.Alias, ptSource.Name) ptTarget = dtTarget.getPropertyType(ptSource.Alias) ptTarget.Description = ptSource.Description ptTarget.Mandatory = ptSource.Mandatory ptTarget.ValidationRegExp = ptSource.ValidationRegExp tabIdSource = ptSource.TabId tabDescriptionSource = findTabCaptionById(dtSource,tabIdSource) tabIdTarget = findOrAddTabByCaption(dtTarget,tabDescriptionSource) dtTarget.SetTabOnPropertyType(ptTarget, tabIdTarget) dtTarget.Save() print "Added property : " + ptSource.Alias + "<br/>" else: print "existing : " + ptSource.Name + "<br/>" dtSource = web.DocumentType.GetByAlias("oneDocTypeAlias") dtTarget = web.DocumentType.GetByAlias("anotherDocTypeAlias") copyDocumentTypeProperties(dtSource,dtTarget)
Copy document property values
Use on your own risk:
from umbraco.cms.businesslogic import web from umbraco.cms.businesslogic import property from umbraco import library ''' Copies an individual property value from one document to another with the exact same Alias and Datatypedefinition for safety : first run with parameter printLog set to True and parameter makeChanges set to False ''' def changePropertyIf(docTarget, alias, dataTypeDefinitionId, newValue, printLog, makeChanges): if printLog: print "Looking for property alias: " + alias + "<br/>" for p in docTarget.getProperties: if p.PropertyType.Alias==alias and p.PropertyType.DataTypeDefinition.Id == dataTypeDefinitionId: if p.Value != newValue: if printLog: print "change from " + p.Value.ToString() + " to " + newValue.ToString() + "<br/>" if makeChanges: p.Value = newValue return True else: if printLog: print "unchanged<br/>" return False if printLog: print "Not found <br/>" return False ''' Copies all property values from one document to another with the exact same Alias and Datatypedefinition for safety first run with parameter makeChanges set to False ''' def copyAllPropertyValues(docSource, docTarget, makeChanges): hasChanges = False for p in docSource.getProperties: if changePropertyIf(docTarget, p.PropertyType.Alias, p.PropertyType.DataTypeDefinition.Id, p.Value, not(makeChanges), makeChanges): hasChanges = True if makeChanges and hasChanges: docTarget.Save docTarget.Publish(docTarget.User) library.UpdateDocumentCache(docTarget.Id) return hasChanges # Example docSource = web.Document(2764) docTarget = web.Document(19213) hasChanges = copyAllPropertyValues(docSource,docTarget,True) if hasChanges: print "Target document has/had differences" else: print "No changes found"
List all document types
from umbraco.cms.businesslogic import web def printAllDocumentTypes(): for d in web.DocumentType.GetAll: i = d.MasterContentType if i==0: master = "" else: master = ", Master : " + web.DocumentType(i).Alias print d.Text + "," + d.Alias + master