Add Custom Fields to Django Flatpages

I was attempting to build a sort of self-building website, where one could add new pages with custom URLs right from the admin interface. This would allow non-tech users to easily expand their website. After asking a few questions, I got pointed to some nice Django functionality that basically already does this: the Django flatpages app.

I got it up and running pretty painlessly, and it works for simple pages. However, it only has three fields built-in: URL, title, and content. I need a little more control than that- meta description, for example. After bugging plenty of people on the #django IRC channel, I've cobbled together this solution:

models.py

  1. from django.contrib.flatpages.models import FlatPage
  2.  
  3. class FlatPageExtra(models.Model):
  4. flatpage = models.ForeignKey(FlatPage,
  5. edit_inline=models.STACKED,
  6. max_num_in_admin=1,
  7. num_in_admin=1)
  8. description = models.CharField(max_length=255,
  9. core=True)
  10. headline = models.CharField(max_length=255,
  11. core=True)
  12.  
  13. class Admin:
  14. pass

Here we are creating a new model (call it whatever you want). Make a field (also named anything, I chose flatpage) that is a Foreign key to the FlatPage model- don't forget to import! This allows you to associate your custom fields with their respective flatpages. I specified edit_inline=models.STACKED, max_num_in_admin=1, num_in_admin=1 because it pretty much only makes sense to edit your custom fields on the same page as the built-in fields, and there's only going to be one of each (at least in this case). Database enthusiasts would probably also specify unique=True, but I don't care either way. Add whatever other fields you want associated with your flatpages.

Run syncdb, fire up your admin page, and take a look! Note: I included TinyMCE for my content box, but that's better covered in the Django wiki.

In your template, you can grab these values like any other ForeignKey field: {{flatpage.flatpageextra_set.all.0.description}}. Note the .0. because it's actually a collection, even though we know there's always just one item.

Preformatted Text with Line Numbers

I was trying to figure out how to add line numbers to preformatted text for another entry. I couldn't find a satisfactory solution, so I ended up creating my own. I'm happy with it so far, so I'm posting about that instead.

Here's the markup. Basically, I used an ordered list (ol) to get the line numbers, since it's built-in and will save me from having to count. Pretty self-explanatory.

  1. <div class="numbered">
  2. <ol>
  3. <li>This is line one</li>
  4. <li> This is line two</li>
  5. <li> This is line three</li>
  6. <li> This is line four</li>
  7. <li class="last">This is line five</li>
  8. </ol>
  9. </div>

CSS is below. The only important piece of css is the white-space: pre;. This tells the list items (li) to act like pre tags and pay attention to spaces. This of course allows you to indent your lines.

  1. div.numbered {
  2. background-color: #EDC850;
  3. border: 2px solid #900701;
  4. color: #f7f2de;
  5. font-family: "courier new", monospace;
  6. margin: 2em;
  7. font-size: .8em;
  8. overflow: auto;
  9. }
  10.  
  11. div.numbered ol li {
  12. background-color: #fdf3f3;
  13. border: 1px solid #EDC850;
  14. border-style: none none solid solid;
  15. color: black;
  16. padding: 3px 10px;
  17. white-space: pre;
  18. }
  19.  
  20. /* Prevent a double border */
  21. div.numbered ol li.last {
  22. border-bottom-style: none;
  23. }

Works in all sensible browsers and IE6+. However, IE needed me to remove whitespace between my list items because of the whitespace bug. 456 Berea St. presents another option.

I'll probably see if I can whip up some JavaScript to handle this with less markup later.

TIP: An easy way to mark up lists quick, which works in most advanced text editors, is to hold alt and select text in a column. This allows you to type into many rows at once (useful for repetitive opening and closing tags)

That's it, enjoy!

Fraktur mon Amour

I didn't even know I was a typography fan until I started reading Smashing Magazine. After a couple of link hops, I ended up at Inspiredology where I spotted these photos:

Fraktur Mon Amour 1 Fraktur Mon Amour 2 Fraktur Mon Amour 3

It was love at first sight. I imagine started googling phrases such as "hot pink typography book" and eventually got lucky and found it. It's called Fraktur Mon Amour by Judith Schalansky.

Presents over 300 Blackletter fonts (capitals, lowercase, numbers, accented characters along with a brief text setting ). Covers rotunda, batarde, textura, schwabacher, fraktur, modern, initials/decoratives, and contemporary fonts. For each font, date, designer and original foundry along with digital foundry/web address where applicable. Facing each font page is a decorative page using characters from the font. Printed in black and pink.

It needs to live on my coffee table, but the only place I can find in English that ships to Canada is John Neal Bookseller at $75. Ouch. Might have to hold off on this one until I have a house to put a coffee table in- then put books on it. We'll see how the late night impulse buys treat me.

IE6: Making Development Miserable

Despite Internet Explorer 7 being out for 1.5 years, w3schools reports that 30.7% of it's users are still using Internet Explorer 6. Considering w3schools is likely biased towards alternative browsers, this stat is depressing. Maybe it's ignorance, maybe it's interface issues, but probably the general public just doesn't care.

As a professional web developer, this is a major hang-up. In building this layout, I did not have a single problem with any other browser, but had a list of ~10 issues that I needed to implement silly fixes to keep IE6 from wrecking my layout.

Here are just some of the things I, like many a developer before me, has to deal with because this browser still exists:

Double margin bug

IE6 Double margin bug

A floated element with a left-margin gets double the margin. In this shot, you can see that my content is indented twice as much as my logo, despite having the same margin-left. Solved by applying "display: inline;" to the container div. Found the solution on Position is Everything.

PNG transparency issues

IE6 png transparency bug

IE6 screws up transparency in png images. It just shows an ugly grey block instead of the pretty, soft edges. Solved using Supersleight, a JavaScript fix by Drew McLellan that pulls all kinds of strings to get PNG transparency working (even for background-images, as is the case in my todo list).

Disappearing/flickering list background

IE6 list background disappear/flicker

I hadn't even heard of this one before, but apparently meeting a certain set of circumstances can make the background image on list items disappear or flicker. I can't recall where I found the solution, but after trying a few others, I settled on setting my list items to "display: inline-block;".

IE6 strange box behaviour

IE6 hasLayout

"hasLayout" seems to be responsible for most IE6 layout nonsense. Many people have heard of it but don't quite understand what it means. hasLayout is an attribute that elements have in IE (you can see it using the IE Developer Toolbar), sort of like CSS attributes (like, width). It determines how IE renders certain elements, but for whatever reason, needs to be manually triggered to cause some elements to behave. It can't be set directly through CSS, however certain attributes do trigger it. My favorite way is to assign the problem element (usually a div or ul) a "height: 1%;". This is called the Holly Hack, from Holly Bergevin. Whenever I can't figure out what's going on in IE6, I give this hack a try. More often than not, it works. I'm not even certain what that screenshot depicts. Elements were flying all over the place.

Rounded corners

IE6 Rounded corners

Rounded corners are so common, yet so difficult because of IE6. Until better CSS adoption kicks in, most methods involve lots of extra markup. In my case, I've got one image and four divs, absolutely positioned to my corners with negative margins. I use background-position to show only the quadrant of the image I need. This works great in every browser but IE6. Because this design is fluid and IE6 isn't good at math, if the window was an odd number of pixels wide, the border would show up PAST the image, putting a nice hard edge just outside my rounded corners, ruining the illusion. I tried to get a screenshot, but IE6 is having even more trouble rendering them now. Fantastic.

I tried many solutions, but they all relied on too many elements, too much JavaScript, or were very image dependent. In the end, I decided IE6 users don't deserve rounded corners, so I set them to "display: none;" for IE6.

Conditional comments

How did I implement these fixes without bloating other browsers? I used conditional comments. Quick, clean, valid, and only slight abuse of the comment tag.

Needless to say, I wasted way too much time fixing IE6. I know IE8 is supposed to be trying pretty hard, but I get sick just thinking about how long it's going to take for people to stop using IE6. Please stop.

Drumroll - I am live!

Weeks of learning, coding, photoshopping, and yelling at IE6 are finally over. Welcome to Typh.com, home of web developer Jason Peddle. I will be writing about CSS, development, design, typography, Django, and whatever else floats through my head.

One thing I want to concentrate on is writing up any solutions I find, because I've been noticing lately that the tech community is terrible at getting simple answers out there. I waste far too much time googling to find things that could have easily been documented in plain English. Save future googlers! Write the answers!

I'm thinking step one is to do a write-up of the obstacles I hit building this site.