How to resolve uids in Archetypes content (technical)

Back in the day the normal way to create stable hyperlinks in Plone (which do not break should you move the target page or rename it) was by using UIDs. A UID is the unique identifier of an Archetypes based object in Plone. Those links were automatically created by the WYSIWYG editor kupu and looked like this: /resolveuid/UID_HERE. The resolveuid script would then lookup the object with that UID and redirect to the correct page (this also works with images).

This was a good solution but had it’s drawback in the redirect because it was an additional hit on the server and does not play too well with caching. A better solution would be to „compile“ those links when saving a page and updating it should a linked page change (which should be possible with today’s events) but unfortunately to make this work like this is a lot of work.

So in order to get rid of these resolveuid-Links in the HTML source I wrote a little method which resolves them when creating the HTML content. This takes more time on read but this time is needed anyway later on in the subsequent call of the redirect. It even does not have the HTTP overhead.

So here is how it looks:

First we need a regular expression to find those links in the source:

import re

Next I created an additional method in that Archetype object which resolves these URLs in the "content" field (this depends on your type, it could also be done inside a view of course):

    def getContent2(self):
        """returnt he content"""
        from Products.CMFCore.utils import getToolByNameTechnorati Tags: <a class="performancingtags" href="" rel="tag">plone</a>, <a class="performancingtags" href="" rel="tag">uid</a>, <a class="performancingtags" href="" rel="tag">kupu</a>, <a class="performancingtags" href="" rel="tag">links</a>
        reference_tool = getToolByName(self, 'reference_catalog')
        map = []
        content = self.getContent()
        uuids = expr.findall(content)
        for uuid in uuids:
                obj = reference_tool.lookupObject(uuid)
                if not obj:
                        return ""
                target = obj.absolute_url()
                source = 'resolveuid/'+uuid
                content = content.replace(source,target)
        return content

In this case I created a second accessor method called getContent2() which I call in my skin.

This should help you then with unneeded redirects. Of course there are better solutions esp. if you think about this issue from the beginning but this quick fix should help.

These days btw. there’s the Redirect Tool which automatically remembers renamed/moved page locations and redirects from the old to the new location. This should be better in case you don’t move things but for moved pages you still have redirects then. So to me the best solution would still be a notification of the source object to update itself.

Teile diesen Beitrag