Idea: "fake" model fields

3 views
Skip to first unread message

Simon Willison

unread,
Sep 16, 2005, 10:25:46 AM9/16/05
to django-d...@googlegroups.com
I'm trying to work out the best way to implement tagging in Django,
for a relaunch of my blog system.

The model seems natural enough:

class Tag(meta.Model):
tag = meta.SlugField()
...

class Entry(meta.Model):
pub_date = meta.DateTimeField()
headline = meta.CharField(maxlength=200)
body = meta.TextField()
tags = meta.ManyToManyField(Tag)
...

The problem is the interface. I want to have a single text input box
where I can enter a space separated list of tags - when the form is
submitted I want to run a bit of code that splits on spaces, checks
each tag to see if it exists, add it if it doesn't and then relate
the entry to that tag.

At the moment, the only way I can see of doing that is to write my
own admin from scratch. I'd rather not do that.

Here's the solution I'm thinking about: what if Django were to
support a concept of "fake" fields? These would be fields defined in
the model which have no direct relationship to the data model but
instead relate to code that defines how they should be processed.
Here's an example (the first syntax that came in to my head):

class Entry(meta.Model):
...
tags = meta.ManyToManyField(Tag)
tagfield = meta.FakeCharField()
def load_tagfield(self):
# Returns the contents of the field when it is displayed
return ' '.join([t.tag for t in self.get_tag_list()])
def save_tagfield(self, value):
tags = [t.strip() for t in value.split() if t.strip()]
self.delete_all_tags()
for t in tags:
try:
tag = tags.get_object(tag__exact = t)
except TagDoesNotExist:
tag = tags.Tag(None, t)
tag.save()
self.add_tag(tag)

This approach would solve my problem, and could be applied to all
sorts of other tricky situations as well.

Another extremely common problem is the need to have a field
automatically set to some value when an item is created or updated
(most commonly a field such as pub_date or last_modified). I wonder
if the above mechanism, or something similar, cousd be used to solve
that one as well.

Cheers,

Simon Willison

Jeremy Dunck

unread,
Sep 16, 2005, 10:47:37 AM9/16/05
to django-d...@googlegroups.com
On 9/16/05, Simon Willison <swil...@gmail.com> wrote:
> tagfield = meta.FakeCharField()
> def load_tagfield(self):
> # Returns the contents of the field when it is displayed
> def save_tagfield(self, value):
...

Instead of Fake*, I suggest Deferred, or Mapped*, or Extended*. This
idea is pretty close to the protocol of __getitem__ call when o[x] is
used.

Otherwise, neat.

> Another extremely common problem is the need to have a field
> automatically set to some value when an item is created or updated
> (most commonly a field such as pub_date or last_modified). I wonder
> if the above mechanism, or something similar, cousd be used to solve
> that one as well.

Hmm, that's muddying the waters. I like the focus this has on mapping
in and out of the persistence layer. What you're talking about on
this 2nd thing is eventing, right? Maybe:

class Entry(meta.Model):
pub_date = meta.DateTimeField()

def init_pub_date(self):
#when model is new (not from persistence)
pass
def resync_pub_date(self):
#when model is updated, but not necessarily pub_date.
pass
def modify_pub_date(self):
#when pub_date, specifically, is changed.

I'll shut up now, since I won't be supplying patches any time soon. :-/

Sune Kirkeby

unread,
Sep 16, 2005, 10:47:37 AM9/16/05
to django-d...@googlegroups.com
On 9/16/05, Simon Willison <swil...@gmail.com> wrote:
> Another extremely common problem is the need to have a field
> automatically set to some value when an item is created or updated
> (most commonly a field such as pub_date or last_modified). I wonder
> if the above mechanism, or something similar, cousd be used to solve
> that one as well.

_pre_save is your friend; and in the specific case of pub_date,
auto_now=True and/or auto_now_add=True would be your
very best friend ;)

I use _pre_save to create an immutable GUID for my blog posts,
when they are first saved. Works nicely.

/s

Adrian Holovaty

unread,
Sep 16, 2005, 12:14:36 PM9/16/05
to django-d...@googlegroups.com
On 9/16/05, Sune Kirkeby <sune.k...@gmail.com> wrote:
> On 9/16/05, Simon Willison <swil...@gmail.com> wrote:
> > Another extremely common problem is the need to have a field
> > automatically set to some value when an item is created or updated
> > (most commonly a field such as pub_date or last_modified). I wonder
> > if the above mechanism, or something similar, cousd be used to solve
> > that one as well.
>
> _pre_save is your friend; and in the specific case of pub_date,
> auto_now=True and/or auto_now_add=True would be your
> very best friend ;)

Yeah, _pre_save() is the appropriate hook, but I agree that there
should be a way of hooking into admin interface functionality. Here
are two ways of solving this:

* Add a "space_delimited=True" option to ManyToManyFields, which would
make the interface as Simon suggested. The precedent for this is
"filter_interface=True", which puts in the snazzy filter interface for
a ManyToManyField.

* Make an official API for creating custom subclasses of the
django.core.meta.fields.Field* classes. The subclasses could add
functionality to do things like splitting by spaces, and all that, in
the admin interface. These classes already have a number of hooks, but
we could add more if it's not too messy.

Adrian

--
Adrian Holovaty
holovaty.com | djangoproject.com | chicagocrime.org
Reply all
Reply to author
Forward
0 new messages