tln devlog [2.2/3] – Apprehending CSS & Updating web content

This series of articles loosely documents design choices and implementation issues I met during the making of the tln website. I learnt a few lessons along my improvised 9-week schedule, and I thought I could share them with fellow first-timers. I guess some technical points might also be of interest to more experimented developers.

Apprehending CSS

I'd done very little frontend before this website, so this may not come as a surprise to full-stack developers, but I'm appalled at how much CSS is a mess. I don't know where to begin. Several vital features are not supported by browsers from just five years ago. Sometimes you have to make up for the lack of certain basic features (e.g. line clamping) all by yourself. Priorities computation, or as CSS likes to call them, 'specificites' (wat), frequently leads to unwanted behaviour. CSS files have a flat, arbitrary, unreadable structure. The whole affair makes for a perfectionist's hell.

It's more important getting a grip on the box model, and then the sizing and positioning main options, than trying to memorize CSS properties. The MDN Web Docs tutorials and key concepts could have been a good checkpoint, had I not plunged head-on into applying properties by trial and error... Note that MDN resources are usually better than W3Schools ones, even though they usually get outranked on Google. Browsers developer tools and the right-click-to-inspect-element cannot be overused here. Also, a lot of more complex issues have already been addressed on Stack Overflow.

Modifying content through a web interface

Aside from CSS, adding content creation, update & deletion features to the web interface took 2-3 days. Mainly it enables me to keep a culture diary, to register movies or albums I'd like to discover, and to write down movie screenings I attended. Appropriate forms are made available to the admin only. Django comes with out-of-the-box authentication and permission tools, and the official documentation made it unexpectedly easy to set up.

You can see the interface below for adding an oeuvre object, it's a bit crude but it does the job well. Forms show up in response to specific key combinations, which are monitored by some JavaScript. Typing addo displays the form for adding a new oeuvre, editc enables to edit the comment displayed on the current page, etc. Obviously it won't work unless you're logged in. :)

a form appears over the web page, asking for information (title, artist names, year...) in order to register a new film

Validating data forms

Recent browsers validate simple conditions like mandatory fields (i.e. they will block form submission if required fields are left void), but this is constrained to HTML input form attributes. Because I wanted finer client-side validation (e.g. for the IMDb identifier field), I wrote some more JS around regexes. Then comes server-side validation, courtesy of Django according to Form classes (which were already used for HTML form generation). Usually client-side and server-side validation are not redundant, as malicious users can easily circumvent client-side validation.

Drawing shallow relations between MongoDB collections

As I was implementing this, I realized I'd made a mistake when first defining models with django-mongoengine fields. I needed to simulate relations between MongoDB collections, like in the TopTextes class for referring to the oeuvre objects which held my favorite reviews. Do not try drawing a relation with an EmbeddedDocumentField, as this field is not bound to the original object. It holds values which won't be updated when the original object gets modified. Use a StringField to map to the original object's identifier instead.

Choosing licenses

Around that time I also informed myself about licenses. I put my reviews and such under CC BY 4.0, while I put the website code under GPLv3. The Critique application is so niche I can't believe anyone would be interested in deploying it, but hey, I'd be ready to help whoever proves me wrong.

Cleaning up the database

Ultimately I spent several hours doing something even more tedious than fiddling with CSS properties: I cleaned up the media database through the CRUD interface I'd just built. This meant spotting and resolving movies and series conflicts which arose from the previous Google crawling, finding and adding covers to the albums displayed on the envies page, etc.