0

I am part editor and part developer and not utterly advanced at either career. But I am carrying out only a small-scale project. I'm thinking that in the blog that I recently added to my Django site (as yet only on the development server), with Wagtail and Puput, I might want to upload, say, two ~50KB images per week for five years, after which I'll be doing something else. There will never be a huge number of readers or a need for vast storage. Those being the circumstances, I specifically want to know if what I'm doing to overcome the problems that I encountered with uploaded images not resizing to small screens in the Puput blog, non-responsive design, looks feasible. Or, did I make some stupid mistake and, say, just use the Puput/Wagtail editor incorrectly?

When you click into the "body" textbox in the Puput editor to insert an image, it's quite simple. You just browse for your file, give the image a name, and select whether you want full-width or aligned on the left or right. And upon doing that your image will be uploaded into your previously established "media" folder and the database will simply be updated to contain the location of your image in the "media" folder. The <img> tag in your text body will be given an ID attribute which is a link to the database entry.

Two troubling things then happen: (1) when you go into the browser's Responsive Design Mode the image is bigger than the small screen, no responsiveness; and, you actually don't now have an image stored in your media folder, you have three--- the original is in a subdirectory called "original_images" and there are two images in an "images" subdirectory. The two additional images may not have exactly the same pixel dimensions as the original, depending on your choice of full-width or not, the aspect ratio of the images perhaps, etc.

So this is rather intolerable, unless of course you can tell me what mistake I may have made. Otherwise, here's what I have done to get past this, and again, my question is would this work out in practice or do you have a better idea. I found this post on github, and in particular the comment by jerel concerning an insert_editor_js and wagtail_hooks.py hook. This overcomes the richtext limitations of standard hallo and permits opening a second editor window in which you can see and enter HTML.

But Wagtail has this Whitelister class that only permits certain attributes to be used with certain HTML tags. So the Wagtail people also have a hook for changing that, which is explained here. Here's my version of the wagtail_hooks.py file:

from wagtail.wagtailcore import hooks
from wagtail.wagtailcore.whitelist import attribute_rule, check_url, allow_without_attributes
from django.utils.html import format_html

# This one is from the esteemable jerel.
@hooks.register('insert_editor_js')
def enable_source():
    return format_html(
        """
        <script>
            registerHalloPlugin('hallohtml');
        </script>
        """
    )

# This is modified from the Wagtail docs example.
@hooks.register('construct_whitelister_element_rules')
def whitelister_element_rules():
    return {
        'blockquote': allow_without_attributes,
        'a': attribute_rule({'href': check_url, 'target': True}),
        'img': attribute_rule({'src': True, 'width': True, 'height': True, 'alt': True, 'style': True}),
        'p': attribute_rule({'style': True, 'class': True}),
    }

Note especially that for the img tag I have put 'src': True in place of 'src': check_url, which is the default (check_url is a function that would reject a data URI, as I discuss below). Other changes important to me are the inclusion of 'target': True for the a tag and also the 'style': True additions.

Puput natively uses Bootstrap3 which is "mobile first", or some such rallying cry. So to bring about responsiveness for images with Bootstap3 in Puput I had to do what I have had to do before, which is, in the img tag, to either set the attribute width="100%" or to do it with style="width:100%;" (which I could do thanks only to the hallohtml plugin).

So now, here comes the problem: I found that that only works if you remove the extra attributes that Puput or Wagtail gives to the img tag (otherwise your changes will be deleted). Here's what the img tag looks like straight from the Puput editor: <img data-embedtype="image" data-id="9" data-format="fullwidth" data-alt="junk" class="richtext-image full-width" src="/home/mike/myproject/public_html/djangoprojectdir/public/media/images/imagename.width-800.png" alt="junk" height="1115" width="596">.

So if I throw away height and change width to 100% that doesn't work unless I also remove data-format, etc. If I do all of that, I have responsive design... but, the database is no longer involved. I have thereby instead just manually linked the image file to the img tag.

So my solution to bring about responsive-design behavior kills the database linkage between pages and image files. I must say, I don't miss the absurd presence of three images in the media folder for every one that I upload. And I don't much like having to guard and backup without failure, for years, not only a database but also a folder of many images.

So the second thing that I tried--- it too seems to work--- is the use of data URIs with Base64, which I read about here. It seems feasible because I won't be using many dense images. I made use of the hallohtml editor to cut and paste the Base64 encoding of the image to src in the img tag. It's not utterly unwieldy.

So again, the question is, do I have to do something like this (and is what I propose reasonable)... or, am I somehow just in the dark concerning how I should upload images or configure Puput and Wagtail for responsive design (I followed all of their instructions and everything else works)?

Community
  • 1
  • 1
Mike O'Connor
  • 2,494
  • 1
  • 15
  • 17
  • "do I have to do something like this" - if you so viscerally disagree with Wagtail's own approach to image handling, then yes, you pretty much will have to hack the framework to pieces to do what you want. Perhaps a more focused question ("why does Wagtail do Thing X" or "how do I disable Behaviour Y") would help us to suggest a more constructive approach? – gasman Feb 20 '17 at 14:07
  • I haven't read the wall of text here.. but the question title suggests part of it isn't related to the actual question... could you perhaps edit it to make it clear exactly what problem you're having or what you're trying to fix? – Sayse Feb 20 '17 at 14:29
  • I'm trying to make the normal Wagtail image insertion method produce a page that is responsively designed, thus fulfilling the promise of Bootstrap, which is part of Puput. I made it clear enough--- in my experience the image doesn't shrink appropriately when you go to a small screen (unless you do something like use the hook mechanism to permit setting `width="100%"`). So the question remains, if you prefer, @gasman, "why does Wagtail not produce a responsive design page when I use 'Wagtail's own approach to image handling'... so that I can avoid having to 'hack the framework to pieces'?" – Mike O'Connor Feb 20 '17 at 20:28
  • 1
    Wagtail itself deliberately stays out of all front-end styling decisions and doesn't provide any CSS of its own, leaving you (or in this case, Puput) to set that up as desired. As such, the lack of responsiveness is a Puput question rather than a Wagtail one... I've provided an answer, but please note that I don't have any Puput experience myself, so it should be regarded as untested and conjectural. – gasman Feb 20 '17 at 22:20
  • @gasman, a very clear and helpful comment. See also my comment to your answer. – Mike O'Connor Feb 22 '17 at 00:15

1 Answers1

2

The root of the issue is that you need a good way of applying the style width: 100% to all rich text images. Ideally you'd do that with a global CSS rule, which would avoid the need to hand-edit the HTML of the body field.

Puput doesn't seem to provide an "official" way to customise the base templates at present, although there are a few pointers here: https://github.com/APSL/puput/issues/63. The following steps should hopefully do the trick:

  • Create a blog app inside your project (run ./manage.py startapp blog, and add 'blog' to the INSTALLED_APPS list in your settings making sure it's above puput) - or if your project already has a suitable app, follow the remaining steps with that app name in place of blog;
  • Create a blog/templates/puput/ directory
  • Create a file blog/templates/puput/base.html containing:

    {% extends "puput/base.html" %}
    {% block content %}
        <style>
            img.full-width {
                width: 100%;
            }
        </style>
        {{ block.super }}
    {% endblock %}
    
gasman
  • 23,691
  • 1
  • 38
  • 56
  • Thank you so much. This will help and I'll pursue this. Last night I found [this previous answer](http://stackoverflow.com/questions/28745373/adding-bootstrap-img-responsive-class-to-wagtail-wysiwyg-editor) by you. An updated link to the doc reference that you provided then would be [here](http://docs.wagtail.io/en/v1.9/advanced_topics/customisation/page_editing_interface.html?highlight=wagtail.wagtailimages.formats#image-formats-in-the-rich-text-editor). The docs example doesn't show the `img-responsive'` class, but I should have thought of that. Might that not also work? – Mike O'Connor Feb 22 '17 at 00:12
  • I've had time to test this and it's working like a charm, provided that I add `height: 100%;` as well (otherwise the image is comically shrunken horizontally but not vertically). In addition to your tip page on puput template modifications, I can add [this one](http://stackoverflow.com/questions/42049697/puput-wagtail-based-blog-where-are-the-files), which is not contradictory. I did not put the `img.full-width` css in the content block, but instead in the head of my own base.html file. Again, thanks much. – Mike O'Connor Feb 22 '17 at 04:23