在自定义管理器中使用自定义SQL时,如何填充相关的Django模型?

时间:2011-02-09 22:47:38

标签: django django-models

我有一些我需要使用自定义SQL的东西。刚开始,我不想讨论为什么我们使用自定义SQL。那是旧的,无关紧要的。

无论如何,使用这个自定义SQL,我正在填充模型并尝试填充相关/子模型。这一切似乎都很顺利,直到在视图或模板中访问相关模型。如果我这样做,django会启动另一个SQL查询,这是完全没必要的,因为我已经通过第一个查询得到了数据。

以下是示例,修剪过的模型:

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)

举个例子:

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

由于get_preferred_name()方法访问self.preferredname.preferredname_id(理论上应该已经填充),因此它会对preferredname进行另一次查询。

我不在这里,或者这应该按照我的意愿行事吗?如果我离开这里,有没有办法从自定义管理器中填充相关模型?

1 个答案:

答案 0 :(得分:1)

不要将对象分配给i.preferredname,而是尝试将其设置为i._preferredname_cache,这是Django用于缓存外键查找的内部对象。这应该有用。