开发者

How do I populate related Django models when using custom SQL in a custom manager?

I have some things I need to use custom SQL for. Just to start, I don't want to get into the discussion of why we're using custom SQL. That's old and irrelevant here.

Anyway, with this custom SQL, I'm populating the model and attempting to populate a related/sub model. That all seems to go fine, until that related model is accessed within a view or template. If I do that, django initiates another SQL query, which is totally unnecess开发者_如何学JAVAary as I already got that data out with the first query.

Here are example, trimmed up models:

class Preferredname(models.Model):
    preferredname_id = models.CharField(primary_key=True, max_length=1)
    name = models.CharField(max_length=255)

class PersonCustom(models.Manager):
    def getSpecial(self):
        from django.db import connection, transaction
        curse = DictCursor(connection.cursor())

        curse.execute("SELECT * FROM person WHERE special = 't'")
        result_list = []
        for row in curse.fetchall():

            i = self.model(
                firstname = row['firstname'],
                middlename = row['middlename'],
                nickname = row['nickname'],
                lastname = row['lastname'],
                suffix = row['suffix'],
            )

            i.preferredname = Preferredname()
            i.preferredname.preferredname_id = row['preferredname_id']

            result_list.append(i)

        return result_list

class Person(models.Model):
    person_id = models.IntegerField(primary_key=True)
    firstname = models.CharField(max_length=255, blank=True)
    middlename = models.CharField(max_length=255, blank=True)
    lastname = models.CharField(max_length=255, blank=True)
    nickname = models.CharField(max_length=255, blank=True)
    suffix = models.CharField(max_length=255, blank=True)
    preferredname = models.ForeignKey(Preferredname)
    objects = PersonCustom()

    def get_preferred_name(self):

        try:
            if self.preferredname.preferredname_id == 'N':
                pref = self.nickname
            elif self.preferredname.preferredname_id == 'M':
                pref = self.middlename
            else:
                pref = self.firstname

        except ObjectDoesNotExist:
            if self._preferred_name == 'N':
                pref = self.nickname
            elif self._preferred_name == 'M':
                pref = self.middlename
            else:
                pref = self.firstname

        name = "%s %s %s" % (pref, self.lastname, self.suffix)

        return name.strip()

    def set_preferred_name(self, val):
        self._preferred_name = val

    preferred_name = property(get_preferred_name, set_preferred_name)

As an example:

>>> p = Person.objects.getSpecial()
>>> p[0].preferred_name

Since the get_preferred_name() method accesses self.preferredname.preferredname_id(which in theory, should already be populated) it makes another query for preferredname.

Am I off base here, or should this work as I intend? If I'm off here, is there a way to populate related models from within a custom manager?


Rather than assigning your object to i.preferredname, try setting it to i._preferredname_cache, which is the internal object Django uses to cache foreign key lookups. That should work.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜