Generic relationships between existing entities, many2many

14 views
Skip to first unread message

arka...@gmail.com

unread,
Feb 7, 2012, 2:11:01 PM2/7/12
to django...@googlegroups.com

Hi,

So, I have the 4 entities represented below which are strong and independent entities on my application, now the problem is that each Article or Picture could be "tagged" with a Presenter or an Event, being as they are the 4 of them independent entities that could become more complex It doesn't look right to add Event and Presenter field to both Article and Picture or the contrary, specially because they could be tagged with none.
In the long run as well other entities might need to be tagged and other taggable entities might appear.

class Article(models.Model):
   
#Fields
class Picture(models.Model):
   
#Fields
class Presenter(models.Model):
   
# Fields
class Event(models.Model):
   
# Fields

The closer I am getting is to some kind of double-headed Generic contenttype based intermediate model like this(haven't tested yet as it is a bit more complex than that), but I am looking for ideas:

class GenericTag(models.Model):
   
# Event,Presenter instance..
    tagcontent_type
= models.ForeignKey(ContentType)
    tagobject_id
= models.PositiveIntegerField()
    tagcontent_object
= generic.GenericForeignKey('tagcontent_type', 'tagobject_id')
   
# Picture,Article instance
    objcontent_type
= models.ForeignKey(ContentType)
    objobject_id
= models.PositiveIntegerField()
    objcontent_object
= generic.GenericForeignKey('objcontent_type', 'objobject_id')

And with that just do queries based on the information I have, I think there have to be more elegant ways to do this without stuffing all tagmodels as fields into taggablemodels.

So, basically, there are several "taggable" objects and "tag" objects which will never overlap and I would like a way of relating them with django without touching the models themselves as they are entities of their own apps.

I was looking into a proxy model with a many2many field, but cannot add fields to proxy models.

Thanks

--
Arkaitz

akaariai

unread,
Feb 7, 2012, 3:39:46 PM2/7/12
to Django users
A pretty good way to do this is using custom hand-written generic
foreign key. You basically need fields "type" (which can be just a
string) and the related object's id. And then implement everything
needed by yourself.

Whatever you do you will have problems. There is no way to get all the
different Tags in a single query (or well, there is always a way but
that query is going to be ugly). So, if you have multiple different
tag types for single object, you are going to need to run multiple
queries to actually fetch the tags. I guess what I am saying here is
that consider once again if you could change your requirements to
something that fits SQL databases better.

Having multiple m2m tables for the relations isn't a bad choice
either. You will need to run multiple queries in any case, and it
seems you will also need to handle the tags differently in your code.
This will most likely perform much better than using generic relations
based approach. Even if you can't touch the models, you can fake this
by a model which has just two foreign keys.

Anyways, using Django's generic foreign keys isn't always the best
solution. It usually doesn't work well if you need to travel the
foreign key in the wrong direction: if you need to get all the log
entries for an object, then using foreign key works. If you need to
fetch all objects having a given log entry (m2m reverse relation), it
just doesn't work well.

- Anssi
Message has been deleted

arka...@gmail.com

unread,
Feb 8, 2012, 11:48:46 AM2/8/12
to django...@googlegroups.com
Hi,
Maybe I focused too much on the type of solution I was looking for and not on the problem itself.

Let's try with music:

I have a Bands application with a Band model that can be used for CRUD of band entity and for voting bands, commenting on them etc..
I have a Venue application  with a Venue model that can be used for CRUD of venue entity and "" "" ....

I have a Media application that contains a Picture model that is used for storing pics, commenting etc...
I have an Articles application that contains an Article model that people use to write post-like articles writing about bands or venues or whateveer.
I have an Events application that conains an Event model that people use to describe when and how an event will happen.

Now, as a side note, almost all of those models have comments through django.contrib.comments plugged in by their own application, model untouched.

What I would like to do is to be able of tagging Pictures,Articles and Events with Bands, Venues, a combination of several of each or none at all.
Plus to the Band and Venue model types I will be adding soon other models as Promoter etc.. that could be tagged as well in any of the others.

The kind of information I am going to read is like:
  • For this Article give me bands
  • For this Picture give me venues and bands
  • For this Event give me venues
  • For this Band how many entities are tagged(Pictures,Articles...), retrieve them
  • For this Venue give me pictures

To me it is the same pattern over and over with different entities on both sides, so I was looking for a generic way of handling it.

Following the external approach of django.contrib.comments, something like this:

Example:
{%gettags currentband Article as articles_for_currentband%}
{%gettags Bands currentarticle as bandtags_for_this_article%}
{%tagcount currentband %}
 

--
Arkaitz
Reply all
Reply to author
Forward
0 new messages