[SOLVED] Lead image from html

I am (still) migrating a 'super old' html site to Plone.
I have about 18.000 'pages' containing one or more images. Usually, the images also have a Caption.

I want to have first image as lead-image (example skipshistorie )

What would be the best approach to show the lead image (in listings etc)

  1. Use BeautifulSoap to search for first image and somehow add it (to (Lead) Image field) and remove it from (body) text field

  2. use first image as lead image

If I use approach 1, I assume I will have 'double up with blob files', if I could avoid that it would be good

What is the question?

An interesting extension of the imagefield could be to use the related pattern to refer to an existing image.

With 1, you can avoid to duplicate the image referring the lead image in the page template. If you want to refer to the lead image as an image in TinyMce, adding your type to image types to TinyMCE control panel (Resource Types -> Image objects) and you should be able to pick up the lead image from the page itself. I've done a litte demo (you can then customize the template to show just the title and richtext):

Some two years ago, I whipped this together for Plone 5.2. Feel free to try it out...

Edit: you just add the behavior to a content type, select an image to appear as a lead image, and it shows it...

In action: PNZ: Manufaktur, 50 Jahre PNZ — Deutsch or PNZ: Manufactory, 50 years of PNZ — English

Thanks.
Does it show the same scale as the "normal" Lead image (I can not test, collective.imagecropping has messed up my local site). I assume I can set the value programically by searching for first image and then find its UUID or something similar (?)

this is similar

Yes, this is the html it generates with barceloneta. It also adds a marker interface.

<div id="viewlet-above-content-title">
<div class="leadImage">
  <figure class="newsImageContainer">
    <a class="pat-plone-modal" data-pat-plone-modal="image: true" href="https://www.pnz.de/de/assets/images-uncategorized/jeremy-bishop-ewkxn5capa4-unsplash.jpg/@@images/image-768-dca21dad427b5b6668e68a84899beb9b.jpeg" data-modal-srcset="">
      <img src="https://www.pnz.de/de/assets/images-uncategorized/jeremy-bishop-ewkxn5capa4-unsplash.jpg/@@images/image-700-d2d234a0203c3e847a0363b68e20fd5f.jpeg" alt="old_tree" title="old_tree" class="newsImage" width="700" height="450">
    </a>
  </figure>
</div>
</div>

see also the discussion referenced by @yurj https://community.plone.org/t/leadimage-from-internal-images-or-first-image-in-text-body

I got an 'rendering error testing it'.
Do you know how I can set the related image programically?

If it should be of any interest to anyone, I paste wom3 basic the 'find first image code here'.

#python 3
#bin/instance run  set_alt_leadimage.py  

from zope.lifecycleevent import modified
import plone.api
from zope.component.hooks import setSite
from plone.app.textfield import RichText
from plone.app.textfield.value import RichTextValue
#from plone.rfc822.interfaces import IPrimaryFieldInfo
from zope.lifecycleevent import modified
import transaction
from bs4 import BeautifulSoup

brains = app.testsite.portal_catalog(portal_type="Document")


if brains:
	print('Total  objects counted: ')
	print(len(brains))
	ant = 0

	for brain in  brains:
			obj = None
			obj = brain.getObject()
		
			oldtext = obj.text.raw
			soup = BeautifulSoup(oldtext, 'html.parser')
			images = soup.find('img')
			print(obj.Title())
			if images:
				img_link = images['src']
		 
				if img_link:
					import pdb; pdb.set_trace()
					#find 'resloveuid" in url
					image_uid=img_link.split("/")[2]
					#find catalog object
					image_brain  = app.testsite.portal_catalog(UID=image_uid)[0]
				
					obj.related_image = RelationValue(???)
				
					#ant += 1

transaction.commit()
print(ant)

Please post a full traceback.

Looking at the code above: you would have to extract the "first image" and create an image object with it, then in the related_image attribute you would store the relationvalue - ergo, whatever the you get from the RelatedItemsFieldWidget in plone.app.z3cform.widget.

I have never tried doing this programmatically.

Edit: ah, looks like you already have the images as separate content objects.

storing the relation value is not the problem, but generating it .

(was too late yesterday, so I did not look into why it errors, and I am not sure if it has something with me pinning versions to get collective.imagecropping to work)

The error comes from here:

  <!-- does not work -->
  <!--img tal:replace="structure python: scaled_image.tag(css_class='newsImage')" /-->

  <!-- works -->
  <img src="${large_image/url}">

023-04-09 12:56:52,024 ERROR   [plone.app.viewletmanager:114][waitress-2] Error while rendering viewlet-manager=plone.abovecontenttitle, viewlet=collective.behavior.relatedteaserimage.viewlet_related_teaser_image
Traceback (most recent call last):
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Chameleon-3.9.1-py3.8.egg/chameleon/template.py", line 192, in render
	self._render(stream, econtext, rcontext)
  File "/home/some_user/vol3/my_site9996/zinstance/var/cache/d1ffa82e4b8654af11743eae16586069.py", line 240, in render
	__cache_139629739476880 = _static_139629853714080('python', " scaled_image.tag(css_class='newsImage')", econtext=econtext)(_static_139629853713888(econtext, __zt_tmp))
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/zope.tales-5.1-py3.8.egg/zope/tales/pythonexpr.py", line 73, in __call__
	return eval(self._code, vars)
  File "<string>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'tag'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/plone.app.viewletmanager-3.1.3-py3.8.egg/plone/app/viewletmanager/manager.py", line 110, in render
	html.append(viewlet.render())
  File "/home/some_user/vol3/my_site9996/zinstance/src/collective.behavior.relatedteaserimage/src/collective/behavior/relatedteaserimage/browser/viewlets.py", line 23, in render
	return self.index()
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Zope-4.8.2-py3.8.egg/Products/Five/browser/pagetemplatefile.py", line 126, in __call__
	return self.__func__(__self__, *args, **kw)
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Zope-4.8.2-py3.8.egg/Products/Five/browser/pagetemplatefile.py", line 58, in __call__
	s = self.pt_render(
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/zope.pagetemplate-4.6.0-py3.8.egg/zope/pagetemplate/pagetemplate.py", line 133, in pt_render
	return self._v_program(
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Zope-4.8.2-py3.8.egg/Products/PageTemplates/engine.py", line 378, in __call__
	return template.render(**kwargs)
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/z3c.pt-3.3.1-py3.8.egg/z3c/pt/pagetemplate.py", line 176, in render
	return base_renderer(**context)
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Chameleon-3.9.1-py3.8.egg/chameleon/zpt/template.py", line 302, in render
	return super(PageTemplate, self).render(**_kw)
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Chameleon-3.9.1-py3.8.egg/chameleon/template.py", line 215, in render
	raise_with_traceback(exc, tb)
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Chameleon-3.9.1-py3.8.egg/chameleon/utils.py", line 53, in raise_with_traceback
	raise exc
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/Chameleon-3.9.1-py3.8.egg/chameleon/template.py", line 192, in render
	self._render(stream, econtext, rcontext)
  File "/home/some_user/vol3/my_site9996/zinstance/var/cache/d1ffa82e4b8654af11743eae16586069.py", line 240, in render
	__cache_139629739476880 = _static_139629853714080('python', " scaled_image.tag(css_class='newsImage')", econtext=econtext)(_static_139629853713888(econtext, __zt_tmp))
  File "/home/some_user/vol3/my_site9996/buildout-cache/eggs/cp38/zope.tales-5.1-py3.8.egg/zope/tales/pythonexpr.py", line 73, in __call__
	return eval(self._code, vars)
  File "<string>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'tag'

 - Expression: "python: scaled_image.tag(css_class='newsImage')"
 - Filename:   ... rimage/browser/templates/viewlet_related_teaser_image.pt
 - Location:   (line 12: col 34)
 - Source:     ... tructure python: scaled_image.tag(css_class='newsImage')" />
							^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 - Arguments:  template: <Products.Five.browser.pagetemplatefile.ViewPageTemplateFile object at 0x7f7049848fa0>
			   options: {}
			   args: ()
			   nothing: None
			   modules: <Products.PageTemplates.ZRPythonExpr._SecureModuleImporter object at 0x7f704ebb52e0>
			   request: <WSGIRequest, URL=http://xweb14d.plana.dk:9996/testsite/some-thing/something-image/document_view>
			   view: <Products.Five.viewlet.viewlet.SimpleViewletClass from /home/some_user/vol3/my_site9996/zinstance/src/collective.behavior.relatedteaserimage/src/collective/behavior/relatedteaserimage/browser/templates/viewlet_related_teaser_image.pt object at 0x7f70443b9340>
			   context: <Document at /testsite/some-thing/something-image>
			   views: <Products.Five.browser.pagetemplatefile.ViewMapper object at 0x7f70443b93a0>
			   here: <Document at /testsite/some-thing/something-image>
			   container: <Document at /testsite/some-thing/something-image>
			   root: <Application at >
			   traverse_subpath: []
			   user: <PropertiedUser 'some_user'>
			   default: <DEFAULT>
			   repeat: <Products.PageTemplates.engine.RepeatDictWrapper object at 0x7f70464787c0>
			   loop: {}
			   target_language: None
			   translate: <function BaseTemplate.render.<locals>.translate at 0x7f70443a1940>
			   attrs: {}
			   teaser_image: <Image at /testsite/mon10119800120001-sirenia.jpg>
			   scale_func: <Products.Five.browser.metaconfigure.ImageScaling object at 0x7f70443b9b80>
			   scaled_image: None
			   here_url: 'http://xweb14d.plana.dk:9996/testsite/some-thing/something-image'
			   large_image: <plone.namedfile.scaling.ImageScale object at 0x7f70443a6dc0>

You're trying to create the html tag (using .tag) of a scaled image. That image scale does not exist yet. In the template, I see: scale='tile_highlight' hardcoded. Possibly a shortcut/oversight on my part? edit: try replacing that scale with one that exists on your system.

for later reference, it looks like related image can be set like this:

		if images:
			img_link = images['src']
         
			if img_link:
				#import pdb; pdb.set_trace()
				#find 'resloveuid" in url, since all images has unique ids here, they can be found without 'finding them by path' (api.content.get(path='/some/path/image.jpg'). 
				image_uid=img_link.split("/")[-1]
				
				#find catalog object
				image_brain  = app.testsite.portal_catalog(UID=image_uid)[0]
				
				initids = getUtility(IIntIds)
				braini = initids.getId(image_brain.getObject())
				
				obj.related_image = RelationValue( braini )

Did not see that it was hardcoded, will fix (or move to some setting)

In fact, I will probably not need this viewlet, but I will try to look into it later anyway.

Also, I will try to show this image in listings etc. If you already have some code/templates doing this, please let me know.

I will update the scripts and put them here:

  1. Make images with relative links into resolveuids
  1. Set related lead image
1 Like

I am trying to make your image show up everywhere (that the lead image does).

I am a bit confused by the following code, what is it supposed to 'do' ?

        elif not has_image:
             noLongerProvides(context, ILeadImage)

This will conflict with 'the other lead image' if you happen to have them both enabled

Is the lead image (alread6) supposed to show in folder listings etc? (in my setup Plone5.2.11/12, it is not)

Yeah, looks like you're right. In our case we have only 'related 'LeadImages.