I wanted to make the objects of a particular model approvable and store the timestamp of when that happened. In other frameworks/languages, I used to combined those in one "approved_at" field, which would be NULL if an object was currently unapproved.
I tried different approaches to implement this in django, and this is the best I came up with so far. Basically, the code in __setattr__ makes sure that the field, once set, will not be updated again.
Overriding setattr__() could also be a solution to determining if a field value has changed in save(), a question that seems come up from time to time in #django.
- newforms
- models
- fields
- forms
- save
A simple macro system that makes it possible to reuse previously defined
blocks, optionally with a custom context, similar to the macro
functionality in Jinja.
It requires some workarounds/hacks because we cannot reach
all the data from inside the django template system that we need, but it
seems to work pretty well so far. It is, however, also pretty untested at this point, so use at your own risk.
Examples:
base.html:
<!--
This is mandatory if you want to use the repeat-tag in
a template. It should as placed as earily as possible.
See below for how to mix with template inheritance.
-->
{% enablemacros %}
<!-- Note that {{ param }} does not exist. -->
{% block foo %}
A standard django block that will be written to the output.
{% if param %}{{ param }}{% endif %}
{% endblock %}
{% macro bar %}
Pretty much the same thing as a django block (can even be
overridden via template inheritance), but it's content
will NOT be rendered per default. Please note that it
ends with ENDBLOCK!
{% if param %}{{ param }}{% endif %}
{% endblock %}
<!-- Render foo for the second time -->
{% repeat foo %}
<!-- Render foo bar the first time -->
{% repeat bar %}
<!-- Render both blocks again, and pass a parameter -->
{% repeat foo with "Hello World" as param %}
{% repeat bar with "Hello World" as param %}
{% macro form %}do stuff with: {{ form }}{% endblock %}
{% for form in all_forms %}
{% repeat display %} <!-- will have access to {{ form }}
{% endfor %}
extend.html:
<!--
{% extends %} requires that it be the first thing in a template,
and if it is, everything except for block tags is ignored, so
{% enablemacros %} won't work. Instead, use:
-->
{% extends_with_macros 'base.html' %}
{% block foo %}
Will override "foo" in base.html
{% endblock %}
{% block bar %}
Will override the macro block "bar" in base.html. Whether
this is defined as block or macro doesn't matter.
{% endblock %}
Todo:
* This (both tags used) results in infinite recursion:
{% extends_with_macros "somefile" %}{% enablemacros %}
- templates
- macro
- jinja
- repeat
- reuse
- variables
One of the things about Django that has always irked me is that there seems to be no standard facility for just loading a page and displaying it, simply. Yes, there is the flatpages module, but it is primarily designed for loading content from a DB. While you specify a custom template and put in junk values for the DB content, it just feels like extra, unnecessary work.
Thinking about the problem some more, I borrowed from the idea of flatpages and implemented a view that will load an otherwise unmapped template off the filesystem and render it. This is very useful when converting an existing site over. Just copy your files over. No need to map anything in the URL conf or use the admin to add any flatpage entries. Since it'll render the template, too, you can even use tags and what not, so it need not be a static page.