Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Django管理接口不使用子类';s _uu unicode___()_Python_Django_Django Admin - Fatal编程技术网

Python Django管理接口不使用子类';s _uu unicode___()

Python Django管理接口不使用子类';s _uu unicode___(),python,django,django-admin,Python,Django,Django Admin,(Django 1.x、Python 2.6.x) 我有以下几款车型: class Animal(models.Model): pass class Cat(Animal): def __unicode__(self): return "This is a cat" class Dog(Animal): def __unicode__(self): return "This is a dog" class AnimalHome(models.Model):

(Django 1.x、Python 2.6.x)

我有以下几款车型:

class Animal(models.Model):
  pass

class Cat(Animal):
  def __unicode__(self):
    return "This is a cat"

class Dog(Animal):
  def __unicode__(self):
    return "This is a dog"

class AnimalHome(models.Model):
  animal = models.ForeignKey(Animal)
我没有实例化任何动物,因为这应该是一个虚拟类。我已经实例化了猫和狗,但在AnimalHome的管理页面中,我对动物的选择显示为“动物对象”(我猜是默认的_unicode _()),而不是我为这两个子类定义的_unicode _)。救命啊


我认为,抽象基类问题是对这个问题的一种回避。即使Animal不应该是抽象的,我仍然有一个问题,因为某种原因,ForeignKey是在Animal上定义的,而不是它的子类,所以调用的是超类方法而不是子类。在OO编程中,当您调用object.method()时,您应该得到最低子类的实现,并且您必须做额外的工作才能得到任何超类的实现。那么为什么在子类上定义uuUnicode_uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu。所以,如果我为动物定义uuunicode uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu


好吧,我想我理解ORM的问题。这两个答案帮助我理解了这一点,谢谢。在进行实验时,我发现当Django保存子类模型时,它会做两件事:(1)在超类的表中为子类对象创建一行,(2)使子类表中的PK与在超类表中指定的PK相同。子类表中的这个PK被命名为superclass_ptr。基于此,我炮制了以下内容。我希望得到反馈

Class Animal(models.Model)
  def __unicode__(self):
    if Dog.objects.filter(pk=self.pk).count() > 0:
      return unicode(Dog.objects.get(pk=self.pk))
    elif Cat.objects.filter(pk=self.pk).count() > 0:
      return unicode(Cat.objects.get(pk=self.pk))
    else:
      return "An Animal!"

在这个问题上,劳伦斯似乎是最正确的。猫和狗将有不相交的PK集(动物的任何子类都将有与其超类记录相同的PK),但不幸的是,Django没有在幕后执行任何工作a la:“我是一只动物。我知道动物有狗和猫两个子类。具体来说,我是3号动物,而且我刚刚检查过,还有一只3号猫。这意味着我实际上是第三只猫”。尽管使用Python的内省,这似乎完全可能而且非常合理(因为猫不会做动物自己做不到的事情)。谢谢大家。

Django(以及一般的关系数据库)不要这样做。即使在使用像Django这样的ORM时,您也不会使用这样的类层次结构

您的问题有两种可能的解决方案:

(1) 为动物模型指定一个“名称”,然后添加名称来自['Dog'、'Cat']的实体。这将在外键选择框中显示动物的名称

(2) 如果您确实需要将外键链接到不同的模型(这实际上不是使用RDBMS的常用方法),您应该在contenttypes框架的文档中阅读

不过,我的建议是(1)。

您需要一个(“虚拟”在Python中没有任何意义。)

从文件中:

class CommonInfo(models.Model):
    name = models.CharField(max_length=100)
    age = models.PositiveIntegerField()

    class Meta:
        abstract = True

编辑

“在OO编程中,当您调用object.method()时,您应该得到最低的子类实现。”

没错,但不是全部

这不是一个OO问题。甚至不是Python或Django问题。这是一个ORM问题

问题是“在FK引用的末尾重建了什么对象?”答案是,对于如何处理从FK值到对象的转换,没有标准的、明显的答案

我在
AnimalHome
中有一行
animals
值为42。它指的是
Animal.objects.get(pk=42)
。动物的哪个子类?猫?狗?ORM层如何知道它应该做
Dog.objects.get(pk=42)
还是
Cat.objects.get(pk=42)

“但是等等,”你说,“它应该获取动物对象,而不是狗或猫对象。”你可以这样希望,但Django ORM不是这样工作的。每个类都是一个不同的表。根据定义,猫和狗是单独的表,有单独的查询。你不使用对象存储。你使用ORM来处理关系表


编辑

首先,只有狗和猫共享一个共同的密钥生成器,并且没有重叠的PK集时,您的查询才有效

如果你有一只PK为42的狗和一只PK为42的猫,你就有问题了。而且,由于你无法轻松控制密钥生成,你的解决方案就无法工作

运行时类型识别很糟糕。它在很多方面都不是面向对象的。几乎任何可以避免RTTI的方法都比不断扩展的if语句序列更好,可以区分子类

然而,您试图构建的模型是——具体地说——ORM系统的一个病态问题。事实上,它是如此病态,以至于我几乎愿意打赌它是一个家庭作业。[纯SQL系统也有病态问题。它们通常以家庭作业的形式出现。]

问题是ORM不能做你认为它应该做的事情。所以你有两个选择

  • 停止使用Django
  • 做Django直接做的事情
  • 打破OO设计准则,求助于像RTTI这样脆弱的东西,这使得添加另一个动物子类非常困难
考虑使用这种方法来进行RTTI——它包括类名和PK

KIND_CHOICES = (
   ( "DOG", "Dog" ),
   ( "CAT", "Cat" ),
)

class Animal( models.Model ):
    kind = models.CharField( max_length= 1, choices=KIND_CHOICES )
    fk = models.IntegerField()
    def get_kind( self ):
        if kind == "DOG":
            return Dog.objects.get( pk = fk )
        elif kind == "CAT":
            return Cat.objects.get( pk = fk )

这与S.Lott的建议是一致的,但是没有if/elif/…,随着需要支持的子类数量的增加,if/elif/…会变得越来越难维护

class Cat(models.Model):
    def __unicode__(self):
        return u'A Cat!'

class Dog(models.Model):
    def __unicode__(self):
        return u'A Dog!'        

class Eel(models.Model):
    def __unicode__(self):
        return u'An Eel!'        

ANIMALS = {
    'CAT': {'model': Cat, 'name': 'Cat'},
    'DOG': {'model': Dog, 'name': 'Dog'},
    'EEL': {'model': Eel, 'name': 'Eel'},
}
KIND_CHOICES = tuple((key, ANIMALS[key]['name']) for key in ANIMALS)

class Animal(models.Model):
    kind = models.CharField(max_length=3, choices=KIND_CHOICES)
    fk = models.IntegerField()
    def get_kind(self):
        return ANIMALS[self.kind]['model'].objects.get(pk=self.fk)
    def __unicode__(self):
        return unicode(self.get_kind())
Django的多表继承也可以实现类似的功能(搜索Django的文档)

ANIMALS = {
    'CAT': {'model_name': 'Cat', 'name': 'Cat'},
    'DOG': {'model_name': 'Dog', 'name': 'Dog'},
    'EEL': {'model_name': 'Eel', 'name': 'Eel'},
}
KIND_CHOICES = tuple((key, ANIMALS[key]['name']) for key in ANIMALS)

class Animal(models.Model):
    kind = models.CharField(max_length=3, choices=KIND_CHOICES)
    def get_kind(self):
        return getattr(self, ANIMALS[self.kind]['model_name'].lower())
    def __unicode__(self):
        return unicode(self.get_kind())

class Cat(Animal):
    def __unicode__(self):
        return u'A Cat!'

class Dog(Animal):
    def __unicode__(self):
        return u'A Dog!'        

class Eel(Animal):
    def __unicode__(self):
        return u'An Eel!'        
我个人更喜欢第二种选择,因为子类的实例将具有所有
class Animal(models.Model):
    def __unicode__(self):
        if hasattr(self, 'dog'):
            return self.dog.__unicode__()
        elif hasattr(self, 'cat'):
            return self.cat.__unicode__()
        else:
            return 'Animal'
# This will fail
>>> TaggedItem.objects.filter(content_object=guido)
# This will also fail
>>> TaggedItem.objects.get(content_object=guido)