

Django 1.2 released - twampss
http://www.djangoproject.com/weblog/2010/may/17/12/

======
igorgue
Django advent is a very good series of articles about 1.2
<http://djangoadvent.com/>

~~~
metamemetics
My favorite quote on that is:

> _"One of Django's core design philosophies is that template languages
> shouldn't try to be programming languages. To that end, we've kept the
> template language deliberately simplisitic so that you'd be more or less
> forced to push advanced logic up into the view."_

Very view people seem to understand this at first unfortunately and try to do
crazy things like swap out the template language for something else or add on
a bunch of hacks. Why create additional custom template logic and the parsing
instructions for converting it to python when you can just write the
functionality in probably one line of standard python in your view fuction and
have it run faster.

~~~
stevenwei
I disagree with this philosophy entirely and think it leads to a poor
separation of concerns. There is plenty of template specific logic that has no
business being in the view, and being forced to put it into your view because
your template system is crippled ends up mixing concerns and causing more
maintenance headaches than it needs to.

As a very simplistic (and somewhat contrived) example:

    
    
      % for label in ('Home','Features','Pricing','Contact'):
        <li>{{ label }}</li>
      % endfor
    

I'd much rather write that than repeat myself 5x, especially if what I'm doing
is more complicated than a simple list tag.

In my mind, the view should be responsible for dealing with application logic
and business logic. E.g. stuff like pulling things out of the database,
dealing with GET/POST request data, validating forms, verifying user
authentication and permissions, and whatever application specific logic is
necessary.

The views should pass their data to the template, but not assume anything
about how the template is being rendered, and not be doing things _for_ the
template. E.g. if you're doing something that renders a HTML snippet to pass
into the template, you've done something wrong.

Once you start going down that road you make it much more difficult to render
alternate versions of your templates (for mobile users for example).

Another case where the crippled templating system ends up pushing concerns
into the wrong layer is rendering hierarchical data: e.g. a nested comments
tree. Deciding how to render that data should be entirely within the scope of
the template. But because of the lack of simple recursion support, the
'recommended practice' is to unravel the tree in your view code, and pass the
unraveled version into the template. Or write your own template tag, but that
is even more complicated.

It's also a bit silly that Django calls controllers 'views' and calls views
'templates', but perhaps it explains why they think it's okay to do view
specific rendering at the controller level.

~~~
zeemonkee
Absolutely agree. Writing template tags in Django involves a lot of
boilerplate. Compare for example Mako or Jinja2 where you can easily write a
macro to handle something like nested comments.

~~~
erlanger
The included simple_tag and filter decorators should be used for simple tags
and filters. More sophisticated tags can specify a separate renderer class,
which must be what you mean by "boilerplate."

    
    
      from django.core.urlresolvers import reverse
      from django.template import Library
      
      register = Library()
      
      @register.simple_tag
      def menu_item(req, viewname, label):
        url = reverse(viewname)
        cls = ''
        if url == req.path:
          cls += 'active'
        return '<li class="%s"><a href="%s">%s</a></li>' % (cls, url, label)
    

Using the tag:

    
    
      {% menu_item request 'accounts.views.profile' 'Your Account' %}
    

The only part of that I don't like is passing the request, but I'm willing to
bet there's a simpler way to access the request object from the function.

A simple filter:

    
    
      @register.filter
      def subtract(x, y):
        """Subtracts the arg from the value"""
        return int(x) - int(y)
    

And maybe in a for loop for overlapping elements:

    
    
      <li style="z-index: {{ 100|subtract:forloop.counter }}">
    

Yes, I use two spaces in my Python code too.

~~~
zeemonkee
The above solution is just plain ugly, HTML in Python.

Another PITA, where Django templates just fall down, is forms. Suppose you
have a form:

    
    
       class MyForm(forms.Form):
            name = forms.CharField()
    

You then add that in the template:

    
    
        {{ form.name }}
    

All well and good; but what if you want to change the size, maxlength, or add
a class ? These things clearly belong in the template, but no, you have to
either add them in the form declaration:

    
    
        name = forms.CharField(widget=forms.TextInput(attrs={'class' : 'foo'}))
    

or in the view:

    
    
         form.fields['name'].widget.attrs = {'class' : 'foo'}
    

Both of which clearly break the separation of concerns. yes, you could write a
template tag to get around this; but it's not in standard Django.

Contrast the following in Jinja2 (using WTForms, but you get the idea):

    
    
         {{ form.name(class_="foo") }}

~~~
metamemetics
> _All well and good; but what if you want to change the size, maxlength, or
> add a class ?_

Adding a class: Django gives every element of the form id values for easy
styling in CSS. Just do {{form.as_p}} and see what it outputs.

size and max length: I'm fine with these in python as they correspond to the
max-length that would be validated into a data member. If you mean pixel size
on screen, this belongs neither in HTML or your template but in CSS, since
browsers render forms completely differently regardless of their HTML
attributes, you have to style their width\height in CSS to get anything
consistent.

~~~
erlanger
Unfortunately, the defaults stink. 1.2 remedies this for error messages at
least.

as_p and co. should include some class describing the field type in the outer
<p> tag so that a developer can style the label and error messages in a way
specific to the field type.

------
lindsayrgwatt
Great to see further integrated support for geoDjango:
<http://docs.djangoproject.com/en/dev/releases/1.2/#geodjango>

------
matclayton
Release notes can be found here

<http://docs.djangoproject.com/en/dev/releases/1.2/>

~~~
holdenk
I strongly encourage people to read the release notes before upgrading, there
are backwards incompatible changes from 1.1

------
mclin
Yay! No more {% ifnotequal %}{% endifnotequal %}

------
adamilardi
How bout adding composite primary key support....ARRRGHHH!!!

~~~
run4yourlives
What major benefit (aside from legacy support) would this achieve that would
be worth the effort?

~~~
jpeterson
... Situations where use of a composite key is the correct design decision,
maybe? Like the very common case of join tables, for example. Surrogate keys
in these situations are wasteful and unnecessary.

I find it seriously irritating when silly limitations like this in a framework
corner you into bad data design.

~~~
ubernostrum
So... next time a feature-proposal window rolls around, go sign yourself up to
work on composite-key support. That's pretty much how things get done :)

------
alrex021

      "Object-level permissions"
    
      get_all_permissions(obj=None)
    
      New in Django 1.2
    
      If obj is passed in, only returns the permissions for this specific object.
    

I wander if this has, or rather can have, very positive impact on the admin
site app? (Neatly applying row-level permissions that is.)

~~~
matclayton
It just puts the plumbing in place to allow row level perms to built later on

------
igorgue
Is this new? <http://skitch.com/igorgue/dd7ym>

It might be related to this?
[http://docs.djangoproject.com/en/dev/releases/1.2/#customiza...](http://docs.djangoproject.com/en/dev/releases/1.2/#customizable-
syntax-highlighting)

~~~
mikexstudios
Yes to both!

------
lecha
Thank you and congratulations to the team!

------
adamilardi
Great work guys. I do love django and everything it's doing. We can't let
these ruby guys nab all the credit

~~~
mdg
whoa, easy there

------
rbanffy
When will settings.py be replaced by a YAML file?

just kidding

/me ducks

~~~
simonw
I worked somewhere a while ago that requested YAML configuration files, since
that was how the sysadmin team administered other existing pieces of software.
Since settings.py is executable Python code, adding support for reading
settings from /conf/django-app.yaml took just a few lines of Python in the
settings file itself.

------
samratjp
Anyone running 1.2 on Google App Engine? Smooth sail?

