views:

42

answers:

2

Hi,

I have an application to count the number of access to an object for each website in a same database.

class SimpleHit(models.Model):
    """
    Hit is the hit counter of a given object
    """
    content_type = models.ForeignKey(ContentType)
    object_id = models.PositiveIntegerField()
    content_object = generic.GenericForeignKey('content_type', 'object_id')

    site = models.ForeignKey(Site)

    hits_total = models.PositiveIntegerField(default=0, blank=True)

    [...]

class SimpleHitManager(models.Manager):
    def get_query_set(self):
        print self.model._meta.fields
        qset = super(SimpleHitManager, self).get_query_set()
        qset = qset.filter(hits__site=settings.SITE_ID)
        return qset

class SimpleHitBase(models.Model):
    hits = generic.GenericRelation(SimpleHit)

    objects = SimpleHitManager()

    _hits = None

    def _db_get_hits(self, only=None):
        if self._hits == None:
            try:
                self._hits = self.hits.get(site=settings.SITE_ID)
            except SimpleHit.DoesNotExist:
                self._hits = SimpleHit()
        return self._hits

    @property
    def hits_total(self):
        return self._db_get_hits().hits_total

    [...]

    class Meta:
        abstract = True

And I have a model like:

class Model(SimpleHitBase):
    name = models.CharField(max_length=255)
    url = models.CharField(max_length=255)
    rss = models.CharField(max_length=255)
    creation = AutoNowAddDateTimeField()
    update = AutoNowDateTimeField()

So, my problem is this one: when I call Model.objects.all(), I would like to have one request for the SQL (not two). In this case: one for Model in order to have information and one for the hits in order to have the counter (hits_total). This is because I cannot call directly hits.hits_total (due to SITE_ID?). I have tried select_related, but it seems to do not work...

Question: - How can I add column automatically like (SELECT hits.hits_total, model.* FROM [...]) to the queryset? - Or use a functional select_related with my models?

I want this model could be plugable on all other existing model.

Thank you,

Best regards.

A: 

Have you considered the performance impact of doing even a single database hit per object?

If you have a small amount of Objects, keep the whole table in memory and send off disk-writes as an asynchronous (background) task.

Simon B.
A: 

I have finaly find the answer, I have changed my manager and now the columns will be add to the db request.

    select = {
        'hits': 'hits_simplehit.hits_total',
    }
    qset = super(SimpleHitManager, self).get_query_set()
    qset = qset.extra(select=select)
    qset = qset.filter(hits_rel__site=settings.SITE_ID)
    return qset

Thank you :)

Acti67