Django Class-Based Generic Views: tips for beginners (or things I wish I’d known when I was starting out)

Django is renowned for being a powerful web framework with a relatively shallow learning curve, making it easy to get into as a beginner and hard to put down as an expert. However, when class-based generic views arrived on the scene, they were met with a lukewarm reception from the community: some said they were too difficult, while others bemoaned a lack of decent documentation. But if you can power through the steep learning curve, you will see they are also incredibly powerful and produce clean, reusable code with minimal boilerplate in your views.py.

So to help you on your journey with CBVs, here are some handy tips I wish I had known when I first started learning all about them. This isn’t a tutorial, but more a set of side notes to refer to as you are learning; information which isn’t necessarily available or obvious in the official docs.

Starting out

If you are just getting to grips with CBVs, the only view you need to worry about is TemplateView. Don’t try anything else until you can make a ‘hello world’ template and view it on your dev instance. This is covered in the docs. Once you can handle that, keep reading the docs and make sure you understand how to subclass a ListView and DetailView to render model data into a template.

OK, now we’re ready for the tricky stuff!

Customising CBVs

Once you have the basics down, you will find that most of your work revolves around subclassing the built-in class-based generic views and overriding one or two methods. At the start of your journey, it is not very obvious what to override to achieve your goals, so remember:

  • If you need to get some extra variables into a template, use get_context_data()
  • If it is a low-level permissions check on the user, you probably want dispatch()
  • If you need to do a complicated database query on a DetailView, ListView etc, try get_queryset()
  • If you need to pass some extra parameters to a form when constructing it via a FormView, UpdateView etc, try get_form() or get_form_kwargs()

ccbv.co.uk

If you haven’t heard of ccbv.co.uk, go there and bookmark it now. It is possibly the most useful reference out there for working with class-based generic views. When you are subclassing views and trying to work out which methods to override, and the official docs just don’t seem to cut it, ccbv.co.uk has your back. If it wasn’t for that site, I think we would all be that little bit grumpier about using CBVs.

Forms

CBVs cut a LOT of boilerplate code out of the process of writing forms. You should already be using ModelForms wherever you can to save effort, and there are generic class-based views available (CreateView/UpdateView) that allow you to plug in your ModelForms and reduce your boilerplate code even further. Always use this approach if you can. If your form does not map to a particular model in the database, use FormView.

Permissions

If you want to put some guards on your view e.g. check if the user is logged in, check they have a certain permission etc, you will usually want to do it on the dispatch() method of the view. This is the very first method that is called in your view, so if a user shouldn’t have access then this is the place to intercept them:

1
2
3
4
5
6
7
8
9
10
from django.core.exceptions import PermissionDenied
from django.views.generic import TemplateView
 
class NoJimsView(TemplateView):
    template_name = 'secret.html'
 
    def dispatch(self, request, *args, **kwargs):
        if request.user.username == 'jim':
            raise PermissionDenied # HTTP 403
        return super(NoJimsView, self).dispatch(request, *args, **kwargs)

Note: If you just want to restrict access to logged-in users, there is a @require_login decorator you can add around the dispatch() method. This is covered in the docs, and it may be sufficient for your purposes, but I usually end up having to modify it to handle AJAX requests nicely as well.

Multiple inheritance

Once you start subclassing and overriding generic views, you will probably find yourself needing multiple inheritance. For example, perhaps you want to extend your “No Jims” policy (see above) to several other views. The best way to achieve this is to write a small Mixin and inherit from it along with the generic view. For example:

1
2
3
4
5
6
7
8
9
10
11
class NoJimsMixin(object):
    def dispatch(self, request, *args, **kwargs):
        if request.user.username == 'jim':
            raise PermissionDenied # HTTP 403
        return super(NoJimsMixin, self).dispatch(request, *args, **kwargs)
 
class NoJimsView(NoJimsMixin, TemplateView):
    template_name = 'secret.html'
 
class OtherNoJimsView(NoJimsMixin, TemplateView):
    template_name = 'other_secret.html'

Now you have entered the world of python’s multiple inheritance and Method Resolution Order. Long story short: order is important. If you inherit from two classes that both define a foo() method, your new class will use the one from the parent class that was first in the list. So in the above example, in your NoJimsView class, if you listed TemplateView before NoJimsMixin, django would use TemplateView’s dispatch() method instead of NoJimsMixin’s. But in the above example, not only will your NoJimsMixin’s dispatch() get called first, but when you call super(NoJimsMixin, self).dispatch(), it will call TemplateView’s dispatch() method. How I wish I had known this when I was learning about CBVs!

View/BaseView/Mixin

As you browse around the docs, code and ccbv.co.uk, you will see references to Views, BaseViews and Mixins. They are largely a naming convention in the django code: a BaseView is like a View except it doesn’t have a render_to_response() method so it won’t render a template. Almost all Views inherit from a corresponding BaseView and add a render_to_response() method e.g. DetailView/BaseDetailView, UpdateView/BaseUpdateView etc. This is useful if you are subclassing from two Views, because it means you can choose which one renders the final output. It is also useful if you want to render to JSON, say in an AJAX response, and don’t need HTML rendering at all (in this case you’d need to provide your own render_to_response() method that returns a HttpResponse).

Mixin classes provide a few helper methods, but can’t be used on their own, as they are not full Views.

So in short, if you are just subclassing one thing, you will usually subclass a View. If you want to manually render a non-HTML response, you probably need a BaseView. If you are inheriting from multiple classes, you will need a combination of some or all of View, BaseView and Mixin.

A final note on AJAX

Django is not particularly good at serving AJAX requests out of the box, and once you start trying to use CBVs to do AJAX form submissions, things get quite complicated.

The docs offer some help with this in the form of a Mixin you can copy and paste into your code, which gives you JSON responses instead of HTML. You will also need to pass CSRF tokens in your POST requests, and again there is an example of how to do this in the docs.

This should be enough to get you started, but I often find myself having to write some extra Mixins, and that is before even considering the javascript code on the front end to send requests and parse responses, complete with handling of validation and transport errors. Here at Isotoma, we are working on some tools to address this, which we hope to open-source in the near future. So watch this space!

Conclusion

In case you hadn’t worked it out, we at Isotoma are fans of Django’s class-based generic views. They are definitely not straightforward for newcomers, but hopefully with the help of this article and other resources (did I mention ccbv.co.uk?), it’ll be plain sailing before you know it. And once you get what they’re all about, you won’t look back.

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Thinking about wireframes

Last week Des Traynor provoked a lot of conversation by saying Some things can’t be wireframed

Many people reacted defensively. I suspect most of us in UX roles still spend a significant amount of our time wireframing.

Couple of things are worth bearing in mind: Des works in-house at a product design company. This means many differences from the agency model – they are their own client, for one. And design is a continuous, on-going process, rather than a time-boxed engagement. There is also a world of difference between product design and web design, and the weaknesses of wireframes are far more apparent with the former.

Problems with wireframes

But yes: wireframes can be limiting. Des’s main point is that they “[discourage] emotive design, eschewing it for hierarchy, structure, and logic”. I often feel they risk the “local maximum” problem, where “logical” improvements don’t necessarily get you to somewhere radically better. And I completely agree that wireframe tools and templates drastically limit the possibility space, at far too early a stage.

The other problem is of course where interaction is concerned. I’ve long stopped attempting to wireframe or otherwise document all “interesting moments” in an application. While wireframing, you often don’t know exactly how something will work, or whether it will “feel” right. Often you just have to prototype it (with the help of jQuery and some plugins), and refine it in the browser. Sometimes this process changes the interface from what you originally had in mind. I would also mention responsiveness and scrolling under this topic – wireframes do a poor job of conveying the experience of different screen sizes, or long scrolling pages. Again, early prototyping will often inform the designs.

Emotive design – careful

Some of examples in the article made me a bit uncomfortable. I remember what it’s like to work with visual designers whose no.1 technique on every project was to slap a big beautiful stock image behind the page. It may impress some clients, but often it betrays the designer’s lack of understanding of the page content, user goals, and interaction, or a fundamental disrespect for text-based information. That’s the kind of mindset that seeks to sweep unsightly navigation menus under a hamburger icon, or use low-contrast grey body text. And I’ve been in loads of user tests where people expressed irritation at irrelevant mood imagery while they’re looking for the information relevant to them. Emotive design is not necessarily audiovisual. I understand that’s not the point Des was making, but glancing at the screenshots it’s easy to misconstrue “emotive design” as “big background images and zero navigation”

Lessons

Here are some of the things I (indirectly) took away from the article for mitigating the weaknesses of wireframes:

  • Spend more time sketching, before reaching for the pattern libraries and templates.
  • Involve visual designers and developers in idea generation and generally, collaborate more. Too often they are involved too late to fundamentally influence the design direction.
  • Never use Lorem Ipsum filler text in wireframes. How a site communicates, what it says, and in how many words – that should all be considered at the wireframing stage.
  • Stop pretending wireframes are wholly un-aesthetic. Many visual ideas come up during wireframing, from the use of imagery to the information design. Tabular information doesn’t have to look like a table. A percentage doesn’t have to be a number. If you have a certain style of photography in mind, include examples. Don’t rely on all the “magic” happening at the visual design stage. (Des offers some very important advice on this point in another article on wireframing.)
  • Discourage the mindset that a wireframed specification is set in stone. Sometimes things change during visual design and implementation. In fact, depending on the project, sometimes it’s OK for wireframes to remain unfinished, as a stepping stone towards a design that is refined further in Photoshop or in the browser.

Ultimately, us at digital agencies can’t wholly get away from wireframes, even for product / application design. Within a fixed amount of time, we need to produce an artifact that gives a sufficiently complete overview of a product for client acceptance, and that allows developers to make a realistic cost estimation. Wireframes remain the best tool for the job in the great majority of our cases.

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

API First

Recently, we were faced with the task of writing an API-first web application in order to support future mobile platform development. Here’s a summary of the project from the point of view of one of the developers.

Agile API

For the first couple of iterations, we had problems demonstrating the project progress to the customer at the end of iteration meetings. The customer on this project was extremely understanding and reasonably tech-savvy but despite that, he remained uninterested in the progress of the API and became quite concerned by the lack of UI progress. Although we were busy writing and testing the API code sitting just beneath the surface, letting the customer watch our test suite run would have achieved nothing. It was frustrating to find that, when there was nothing for the customer to click around on, we couldn’t get the level of engagement and collaboration we would typically achieve. In the end, we had to rely on the wireframes from the design process which the customer had signed off on to inform our technical decisions and, to allay the customer’s fears, we ended up throwing together some user interfaces which lacked any functionality purely to give the illusion of progress.

On the plus side, once we had written enough of our API to know that it was fit for purpose, development on the front-end began and progressed very rapidly; most of the back-end validation was already in place, end-points were well defined, and the comprehensive integration tests we’d written served as a decent how-to-use manual for our API.

Extra Work

Developing the application API-first took more work and more lines of code than it would have required if implemented as a typical post-back website.

Each interface had to be judged by its general usefulness rather than by its suitability for one particular bit of functionality alluded to by our wireframes or specification. Any view that called upon a complex or esoteric query had to instead be implemented using querystring filters or a peculiar non-generic endpoint.

In a typical postback project with private, application-specific endpoints, we’d be able to pick and choose the HTTP verbs relevant to the template we’re implementing however our generic API required considerably more thought. For each resource and collection, we had to carefully think about the permissions structure for each HTTP method, and the various circumstances in which the endpoint might be used.

We wrote around 4000 lines of integration test code just to pin down the huge combination of HTTP methods and user permissions however I sincerely doubt that all of those combinations are required by the web application. Had we not put in the extra effort however, we’d have risked making our API too restrictive to future potential consumers.

In terms of future maintainability, I’d say that each new generic endpoint will require a comparable amount of otherwise-unnecessary consideration and testing of permissions and HTTP methods.

Decoupling

Having such an explicitly documented split between the front and back end was actually very beneficial. The front end and back-end were developed and tested based on the API we’d designed and documented. For over a month, I worked solely on the back-end and my colleague worked solely on the front and we found this division of labour was an incredibly efficient way to work. By adhering to the HTTP 1.1 specification, using the full range of available HTTP verbs and response codes, and to our endpoint specification, we required far less interpersonal coordination than would typically be the case.

Beyond CRUD

The two major issues we found with generic CRUD endpoints were (1) when we needed to perform a complex data query, and (2) update multiple resources in a single transaction.

To a certain extent we managed to solve the first problem using querystrings, with keys representing fields on the resource. For all other cases, and also to solve the second problem, we used an underused yet still perfectly valid REST resource archetype: the controller, used to model a procedural concept.

We used controller endpoints on a number of occasions to accommodate things like /invitations/3/accept (“accept” represents the controller) which would update the invitation instance and other related user instances, as well as sending email notifications.

Where we needed to support searching, we added procedures to collections, of the form /applicants/search, to which we returned members of the collection (in this example “applicants”) which passed a case-insensitive containment test based on the given key.

Conclusion

API-first required extra implementation effort and a carefully-considered design. We found it was far easier and more efficient to implement as a generic, decoupled back-end component than in the typical creation process (model -> unit test -> url -> view -> template -> integration test), with the front-end being created completely independently.

In the end, we wrote more lines of code and far more lines of integration tests. The need to stringently adhere to the HTTP specification for our public API really drove home the benefits to using methods and status codes.

In case you’re curious, we used Marionette to build the front-end, and Django REST Framework to build the back end.

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Hold the hamburger

Hamburger iconI’ve noticed a worrying trend in web navigation lately. More and more websites are hiding their navigation – at desktop resolutions – under a single button, often the 3-bar “hamburger” icon.

They are doing this because it makes the website look “clean” – simple and uncluttered. Who wouldn’t want that? Or perhaps they are following the lead of some powerful role models, such as Google, or Medium. Or they are influenced by design for mobile devices, where small screens often require navigation to be hidden initially, and the hamburger icon has become ubiquitous. But they are usually wrong.

Hyperisland, Xoxo festival and Squarespace all hide their navigation under an icon even at desktop resolutions.

Hyperisland, XOXO festival and Squarespace are just 3 examples of sites that hide their navigation under an icon even at desktop resolutions.

Just a quick recap of the purposes1 of navigation menus on websites:

  1. It tells you what’s here and what you can do
  2. It gets you to where you want to go
  3. It tells you where you are

Hiding the navigation under an icon does a slightly worse job at no.2 (one extra click), but a terrible job at nos.1 and 3. And a clean-looking design does not compensate for this loss, for most websites at least.

So when is it OK to hide the navigation under an icon?

Well, I’ve already mentioned devices with small screens, where there simply is no room to spare for a menu. Responsive web design (RWD) is often used to transform the navigation menu into an icon at small screen sizes, like the popular Bootstrap framework. This is an ergonomic, not aesthetic decision.

The other case where hiding the navigation is understandable is on sites where random browsing is the dominant navigation pattern. This can describe journalism sites such as Medium, Upworthy, blogs in general, or social networks like Google+, Pinterest, Instagram, etc. These are sites where you typically don’t start at the homepage, and you typically navigate via related content. They may have navigation behind the scenes (such as content categories or account tools) but these are not needed in the vast majority of user journeys.

For most other websites and web applications, where users need to be guided to the information or tool they need with as little fuss as possible, visible navigation menus or toolbars are necessary2.

Yes, it’s easier for a designer to make a site without navigation menus look attractive, at first glance. But as any UX expert knows, visual simplicity does not necessarily equal ease of use. The best website designs are those that look beautiful while also providing the information and tools most users need. You do not solve a design problem by sweeping it under the carpet.

Hold the mystery meat, too

Which brings me to another form of the same problem – sweeping “surplus” navigation underneath a cryptic icon like the hamburger or “…” Software developers have known for decades that menu labels like “Other”, “Misc” or “More” are design failures – yet somehow giving them a trendy icon has given this form of mystery meat navigation new respectability. Google is a prime offender. Submenus are OK when the label clearly suggests what’s inside, such as the now-ubiquitous Account menu (or just avatar) at the top right. If not, it may as well be labeled “Stuff”.

Google has become an arch-offender in making invisible navigation seem respectable again. Even on wide screens with plenty of real estate, Gmail hides commonly-used functions under cryptic menus. (1) I curse every time I have to click here to go to Contacts. Without looking, I challenge you to guess what's in the "More" menu. (3) What would you find in here? (4) Or here?

Google has become a chief offender in making invisible navigation seem respectable again. Even on wide screens with plenty of real estate, Gmail hides commonly-used functions under cryptic menus. (1) I curse every time I have to click here to go to Contacts. (2) Without looking, I challenge you to guess what’s in the “More” menu. (3) What would you find in here? (4) Or here?

Flickr’s May 2013 redesign swept most of the user-related navigation under the obscure ellipsis icon, which may seem neater to anyone who doesn’t actually use the site, but is a major, on-going frustration to regular users.

Flickr’s May 2013 redesign (bottom) swept most of the user-related navigation under the obscure ellipsis icon, which may seem neater to anyone who doesn’t actually use the site, but is a major, on-going frustration to regular users.

[Update 10 Feb: Killing Off the Global Navigation: One Trend to Avoid by the Nielsen Norman Group makes much the same argument, but provides more background, examples and suggestions. Their article correctly targets any single menu item hiding the global navigation inside a drop-down menu, rather than hiding it under an icon as I focused on. They point to online retailers starting the trend, possibly copying Amazon. They suggest using click tracking, observation and analytics to decide whether it makes sense to hide your global navigation, and what impact it’s having.]


(1) Those who’ve read Steve Krug’s 2001 classic Don’t Make Me Think may recall his slightly different list of the purposes of navigation:

  • It gives us something to hold on to.
  • It tells us what’s here.
  • It tells us how to use the site.
  • It gives us confidence in the people who build it.

(2) Search can help, but most usability studies show that Search is typically only used after navigation has already failed and should not be considered a replacement for navigation. Search on the vast majority of websites falls far, far short of Google’s magic.

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Backbone history and IE9

This bit me the other day, so I thought I’d share the pain.

IE9 doesn’t support pushState as you probably know which meant everything was routing to root (as it were).

The following snippet checks and resorts to hash based routing if it can’t cut the mustard:

app.on('initialize:after', function() {
    if(Backbone.history && !Backbone.History.started) {
        if(!(window.history && history.pushState)) {
            Backbone.history.start({ pushState: false, silent: true });
            var fragment = window.location.pathname.substr(
                Backbone.history.options.root.length);
            Backbone.history.navigate(fragment, { trigger: true });
        }
        else {
            Backbone.history.start({ pushState: true });
        }
    }
});

Add it wherever you would initialize Backbone history – often the entry point of the app. Mine for instance has an app.js that is initialised by main.js

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Content types and Django CMS

Screenshot of the new ENB website

The new ENB website

One of our latest projects to go live is a new website for the English National Ballet. Part of a major rebrand, we completely replaced their old PHP site with a new content-managed site powered by Django CMS.

Django CMS is very flexible, largely due to its minimalistic approach. It provides no page templates out of the box, so you can construct your HTML from the ground up. This is great if you want to make a CMS with a really strong design, because there is very little interference from the framework. However, its minimalistic approach also means that you sometimes have to write extra code to tie all the content together.

A good example of this is content types. In Django CMS, there is only one content type: Page. It has certain fields associated with it e.g. title, slug, published. Any other information that appears on a page comes courtesy of plugins. The default Django CMS plugins give you everything you need to add arbitrary text, images and video to a page. But what if you want more fields for your page? Let’s say, for example, you are representing a ballet production and you want category, thumbnail and summary text fields, which don’t appear on the page itself but are needed for listings elsewhere on the site?

We decided to create a special “metadata” plugin to be added to the production pages, that would only be visible to content editors and not end users. This was seen as the best solution that achieved our goal while maintaining a decent user experience for the editors.

The plugin model looks something like this:

1
2
3
4
class ProductionDetails(CMSPlugin):
    summary = models.CharField(max_length=200) # Short summary, shown in listings
    image = FilerImageField() # Thumbnail image, shown in listings
    audiences = models.ManyToManyField(Audience) # Categorisation

Note the use of django-filer for the image field. This is simply the best add-on I have encountered for dealing with image uploads and the inevitable cropping and resizing of said images. You can also use cmsplugin-filer (by the same author) to replace the standard image plugin that comes with Django CMS.

Now querying the database for, say, the first 10 productions for a family audience (audience id 3) is as simple as:

ProductionDetails.objects.filter(audiences=3, placeholder__page__published=True)[:10]

So now we have a plugin model that we can query, and we don’t need a template as we don’t want it to appear on the actual page, right? Wrong. We still want to provide a good user experience for the editors, and this includes looking at a page in edit mode and being able to tell whether the page already has the plugin or not. So we use request.toolbar.edit_mode in the template to decide whether to render the plugin:

1
2
3
4
5
6
7
8
9
{% load thumbnail %}
 
{% if request.toolbar.edit_mode %}
<div id="production-details">
 <img src="{% thumbnail instance.image 100x100 crop upscale subject_location=instance.image.subject_location %}" />
 <p>Summary: {{ instance.summary }}</p>
 <p>Audiences: {{ instance.audiences.all|join:', ' }}</p>
</div>
{% endif %}

Now this information will only appear if an editor has activated the inline editing mode while looking at the page. If they look at the page and the information is missing, they know they need to add the plugin!

This solution works quite well for us, although it is still fairly easy to create a page and forget to give it any metadata. Ideally it would be mandatory to add a metadata plugin. Perhaps the subject of a future blog post!

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Polite user interfaces know when to wait a little

Web page elements that appear or disappear on hover should almost always do so with a slight delay. Why?

  • To prevent distracting elements leaping out at you while your mouse is simply traversing the page.
  • To prevent you from accidentally clicking something that popped into view just as you were moving your cursor towards the target.
  • To prevent elements such as menus from unexpectedly disappearing when you just stray a pixel off, forcing you to re-invoke them.

Building in a small delay (say, 100ms) before elements appear or disappear is a hallmark of polite user interfaces, but is woefully rare. If you do a Google search for JavaScript plugins for menus, dropdowns, etc., you’ll find almost none that do this. This is also the biggest problem I have with using CSS :hover to show or hide elements (and why I think pure CSS dropdown menus are useless.)

On pretty much all projects with interactive JavaScript elements I’ve worked on in the past, I’ve specified this behaviour, which added considerable complexity for the developer. In most cases, they developed their solution from scratch.

So I was very happy to discover Brian Cherne’s hoverIntent jQuery plugin, a lightweight (4KB unminified) script which makes this effortless to do:

HoverIntent is similar to jQuery’s hover. However, instead of calling onMouseOver and onMouseOut functions immediately, this plugin tracks the user’s mouse onMouseOver and waits until it slows down before calling the onMouseOver function… and it will only call the onMouseOut function after an onMouseOver is called.

Please consider using it on your next project!

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Running a Django (or any other) dev instance over HTTPS

Being able to run your dev instance over HTTPS is really useful: you might spot some weird bug that would have bitten you in production, and if you do find one, you can debug it much more easily. Googling for this subject resulted in several different tutorials using stunnel, but all of them broke in some way on my machine running Ubuntu Maverick. So here is how I got stunnel working – perhaps it will help someone else too:

sudo aptitude install stunnel
sudo su -
cd /etc
mkdir stunnel
cd stunnel
openssl req -new -x509 -days 365 -nodes -out stunnel.pem -keyout stunnel.pem
openssl gendh 2048 >> stunnel.pem
chmod 600 stunnel.pem
logout
cd

Now create a file called dev_https with the following text:

pid=
foreground=yes
debug = 7

[https]
accept=8443
connect=8000
TIMEOUTclose=1

Note: this assumes your web server is running on port 8000. If it’s not, change the value of “connect” to the appropriate port.

Finally, run:

sudo stunnel4 dev_https

Now if you go to https://localhost:8443/, you should see your HTTPS-enabled dev instance!

Note: To properly simulate a HTTPS connection in Django, you should also set an environment variable HTTPS=on. Without this, request.is_secure() will return False. You could set it at the same time as starting your dev instance e.g:

HTTPS=on python manage.py runserver

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

Photoshop guidelines for web designers

We often work with external design agencies. Sometimes they work with wireframes we produce, and sometimes not. These are my standard guidelines (or wishlist, if you will) that I try to send to designers before they start. I don’t think I’ve ever received any that meets all these criteria, but it’s always good to aim for. Perhaps it’ll be a useful checklist for other designers out there.

  1. Final deliverables are layered Photoshop files (.psd), with flat file snapshots of each.
  2. When providing flat files (incl. work-in-progress snapshots), use 24-bit PNG format (not JPG).
  3. Use separate files for each distinct layout template.
  4. Photoshop Layers should be given meaningful names. Multiple identically-named layers are unnacceptable. As far as possible, remove obsolete layers. Use layer groups to organise layers
  5. Photoshop Guides should be used, matching the page layout grid. Remove obsolete guides. Guides should be snapped to pixel edges Photoshop lets you position guides at sub-pixel level, which causes confusion when working with pixel-level artwork for screen-based media. To snap guides to pixel edges, first create a marquee selection in the right place, and then snap the guide against the marquee edge..
  6. Consistency between Photoshop files is required, regarding measurements, fonts and colours.
  7. Use a meaningful and consistent file naming policy. Related files should be named in such a way that they are alphabetically adjacent (e.g. content-normal.psd, content-wide.psd
  8. Versioning: for updated versions of files, use a consistent and sensible versioning system in the file names. E.g. homepage-v01.psd. Files with version numbers should stay in order when sorted A-Z. Avoid file name suffixes like -final.psd, -updated.psd, -new.psd etc.
  9. Bear in mind CSS capabilities and work with them wherever possible. For example, horizontal and vertical lines should follow pixel edges exactly (not anti-aliased) in order to be implemented as CSS borders.
  10. When drawing vector shapes, remember to check the “Snap to Pixels” box in the shape options.
  11. Remember to specify hover (mouseover) and active (on click) states for links and buttons.
  12. Accessibility: Minimum font size is 11px. Body text should ideally be 12px or 13px.
  13. Accessibility: Test for adequate colour contrast and colour blindness
  14. Text in Photoshop should be sized in px units (not pt), and in integer sizes (not fractions)
  15. Specify the actual leading in the Character palette, and, for multi-paragraph text areas, spaces above and below paragraphs in the Paragraph palette, that should be implemented using CSS. Do not use double linebreaks or font sizing to set paragraph spacing
  16. Use web fonts as far as possible (core web fonts or from a commercial web font service). Only use non-web fonts (e.g. corporate fonts) where absolutely necessary (they’ll be implemented using images). This is extra important for text that will be content-managed or translated.
  17. Embedded images such as logos should be production quality, as the Photoshop file will be used to cut out final images. (Tip: embed logos as ‘smart objects’, or avoid resizing them multiple times.)
  18. If working from wireframes, try to avoid a “wireframe aesthetic” (monochrome, everything in boxes). If a wireframe puts something in a box, it just means that information should visually stick together. Use gestalt principles to group information visually.
    Edit 3 Mar 2014: Good series on gestalt by Andy Rutledge: 1, 2, 3, 4, and 5.

Edit Feb 2014: Here are 2 excellent resources for designers producing website mockups in Photoshop:

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.

HTML5 input type=number and decimals/floats in Chrome

As you may already know, HTML5 has introduced a number of new input types, one of which is the “number” type. As you might expect, this is a form field which accepts numeric input. So what happens in Chrome with the following HTML when we try to enter a decimal (floating point) number and submit the form?

<input type="number" />

Answer: Chrome pops up a validation error:

Decimal number failing validation

So what’s going on here? Is it a bug? It doesn’t fail in Firefox.

Well actually it’s not a bug; the form field is behaving as defined by the W3C. Numeric input fields can take additional attributes “min” and “step”, which constrain the range of values allowed in your input. The “min” attribute is fairly obvious: it’s the minimum value your number can be. The “step” attribute is less intuitive: by playing with different values, you would most likely work out that it controls the increase/decrease when clicking the up/down buttons on the field. If you input the number 1 and click the up arrow, it will increase to 2. This is because the default step is 1. So far, so obvious. However, the step attribute also determines which values are valid, so a step of 1 means you can enter 1, 2, 3 etc. and a step of 2 means you can enter 2, 4, 6 etc, and when you click the up/down buttons the number will increase/decrease by 2 each time, but entering 3 or 5 in the box will cause a validation error. You can also use a decimal value: for example, a step of 0.3 will allow values such as 0.3, 0.6, 0.9 etc, but not 1 or 2.

But what if you want all the numbers to be valid, integers and decimals alike? In this case, set step to “any”:

<input type="number" step="any" />

Now you don’t get a validation error. Yay! Also note that if you only want to accept positive numbers, you’ll want to add min=”0″.

So the lesson here is that the “step” attribute is linked to both the up/down buttons and the range of values allowed in the field. When step=”any”, the up/down buttons will increase/decrease the number by 1. As far as I can tell, there is no way to have step=”any” and an increase/decrease of more (or less) than 1 when clicking the up/down buttons. Feel free to enlighten me in the comments though!

About us: Isotoma is a bespoke software development company based in York and London specialising in web apps, mobile apps and product design. If you’d like to know more you can review our work or get in touch.