Wednesday, June 1, 2011

Can the admin be configured to save generic content types with the id of the base model of an inherited model

Hi

I hope this question isn't too obscure.

I have a base model  (not abstract) called BasicPost. I have a model inheriting from it called PostWithImage. BasicPost has a couple of  generic relations.

In models.py:

class BasicPost(models.Model):
   ...
   authors = generic.GenericRelation(OrderedCredit, verbose_name=_('authors'),
                                      blank=True, null=True)
   ...
   tags = generic.GenericRelation(TaggedItem, verbose_name=_('tags'),
                                      blank=True, null=True)
   ...

class PostWithImage(BasicPost):
   ...

In admin.py:

class TaggedItemInline(generic.GenericTabularInline):
    ...
    model = TaggedItem
    ...

class OrderedCreditInline(generic.GenericTabularInline):
   ... # same concept as above

class BasicPostAdmin(admin.ModelAdmin):
    inlines = [OrderedCreditInline, TaggedItemInline]


class PostWithImageAdmin(BasicPostAdmin):
    ...

When I save an object on the PostWithImage admin screen, it sets the content_type of my generic fields equal to PostWithImage. However if I want to now retrieve all posts (irrespective of whether they're a BasicPost, PostWithImage or any other kind of post) with a particular tag, I run into problems. No simple query will do it, because the tags are pointing to a bunch of different models. I have found a workaround, but it's ugly and make expensive database hits. Is there a way I can coerce the admin interface into saving the tags with content_type pointing to the base class, i.e. BasicPost?

Thanks.

Regards
Nathan

PS: Here's the ugly workaround. Very difficult for a programmer to decipher and I suspect it generates very expensive database hits.


class BasicPost(models.Model)

    def get_related_posts(self):
        tags = self.tags.all()
       
        return BasicPost.objects.filter(
            pk__in=
                [t.object_id for t in
                    TaggedItem.objects.filter(tag__name__in=[t.tag.name for t in tags])
                        if isinstance(t.content_type.model_class()(), BasicPost)])\
                            .select_subclasses().order_by('-date_published')

# Note that I'm using model_utils, hence the select_subclasses method.

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment