1

lets say I have a model named User, and other models representing actions done by the a user, like "User_clicked", "User_left", "User_ate_cookie" etc. etc.

the User_* models have different fields and inherit from a single abstract class (User_do_something)

my question is this:

what's the django-way of querying ALL the models, from all the relevant tables, that point on a specific user?

eg. I want to do User.get_all_actions() and get a list with mixed type of models in them, containing all the objects that inherit from User_do_something and point on the specific user.

Note: performance is critical. I don't want to make multiple db queries and combine the list, if possible, I want to do it with a single sql select.

some code to be clear:

class User(models.Model):
    uuid = models.UUIDField(unique=True, default=uuid.uuid4)
    creation_time = models.DateTimeField(auto_now_add=True)

    def get_all_actions(self):
        '''
        return a list with ALL the actions this player did.
        '''
        ??????? how do I do this query ???????

class User_do_action(models.Model):
    user = models.ForeignKey(User)
    creation_time = models.DateTimeField(auto_now_add=True)

    class Meta:
        abstract = True

class User_click(User_do_action):
    ... some fields

class User_left(User_do_action):
    ... some fields

class User_ate_cookie(User_do_action):
    ... some fields

etc. etc.

thanks!

Ronen Ness
  • 9,923
  • 4
  • 33
  • 50
  • 1
    Is every action different? Can't they be put in the same table? The method you are using will probably require one query per model using prefetch_related. – cdvv7788 Oct 04 '15 at 11:14
  • @cdvv7788 they are very different I can't combine them. from reading the docs it looks like prefetch_related is not exactly for my use case and I don't think it will give any performance boost. in my case I check all actions for a specific user, and every action will only point to a single user and will only appear once. even if I check another user, they won't have any actions in common. so caching them, like prefetch_related does, won't help. or maybe I misunderstood it? thanks – Ronen Ness Oct 04 '15 at 11:43
  • Maybe using multitable inheritance you could get them all at once, but that would require a big join that will grow with every new action you add. – cdvv7788 Oct 04 '15 at 11:48
  • @cdvv7788 "using multitable inheritance" - how will a multitable inheritance help? maybe I'm missing something could you explain further? thanks :) – Ronen Ness Oct 04 '15 at 11:50
  • https://docs.djangoproject.com/en/1.8/topics/db/models/#abstract-base-classes – cdvv7788 Oct 04 '15 at 11:53
  • @cdvv7788 your link is about abstract inheritance, which as you can see I'm already using. I think you meant this https://docs.djangoproject.com/en/1.8/topics/db/models/#multi-table-inheritance. anyway that's not what I asked. in multitable inheritance I can do filter on the base class and then access the inherited class (like in the Place / Restaurant example), but this does multiple queries too, so it doesn't help in performance. or am I wrong here? – Ronen Ness Oct 04 '15 at 12:13
  • 1
    @Ness, you are not wrong. If you need elegant code and short development time you can use [django-model-utils inheritance manager](http://django-model-utils.readthedocs.org/en/latest/managers.html). If you need performance, the way is to create a single model `User_do_action` with a 'type' indexed field (user_id + action_type) and fill properties according to kind of action. Related info: http://stackoverflow.com/questions/23466577/should-i-avoid-multi-table-concrete-inheritance-in-django-by-any-means – dani herrera Oct 04 '15 at 13:16
  • Please avoid the use of the '_' character in model names. You would have noticed that it's used in connecting relationships so having your models with underscores in them will lead to inevitable confusion and nasty bugs. UserAction is far far better than User_do_action – e4c5 Oct 04 '15 at 14:50

0 Answers0