LINUX.ORG.RU

[Django] Наследование моделей

 


0

0

Добрый день! Подскажите пожалуйста , как можно реализовать в Django сл. задачу.

Есть например модель A c некоторым полем dataA
и методом printdata, и есть наследник B (их может быть много):


class A(models.Model):
dataA = models.IntegerField()
def printdata(self):
print self.dataA


class B(A):
dataB = models.IntegerField()
def printdata(self):
print self.dataA + self.dataB


Как сделать функцию printdata виртуальной.

например:
b = B()
b.dataA = 10
b.dataB = 10
b.save()
a = A.objects.get(id = 1)
a.printdata() # здесь происходит вызов A.printdata, а нужен B.printdata

ps Если использовать абстрактную модель те через класс Meta сделать
модель абстрактоной. Тогда возникает другая проблема, связанная с
тем, что на абстрактную модель нельзя создавать ключей.

Например:
class A(models.Model):
dataA = models.IntegerField()
def printdata(self):
print self.dataA

class Meta:
abstract = True

class B(A):
dataB = models.IntegerField()
def printdata(self):
print self.dataA + self.dataB


class C(models.Model):
a = models.ForeignKey(A) # Так делать нельзя!


> a.printdata() # здесь происходит вызов A.printdata, а нужен

А почему бы не вызвать B.objects.get вместо A.objects.get? На крайняк можно создать инстанс B по словарю из A

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

> А почему бы не вызвать B.objects.get вместо A.objects.get? На крайняк можно создать инстанс B по словарю из A

Потому что наследников может быть несколько и какой именно объект был создан не известно.

aalek
() автор топика
Ответ на: комментарий от aalek

> и какой именно объект был создан не известно.

так можно выяснить :). Ты расскажи о задумке в целом, а то ты какую-то очень странную задачу ставишь.Я так и не понял почему инстанс класса A должен знать о методах класса B. И, не совсем уверен что правильно ли я понимаю понятие "виртуальных методов", но в питоне они, вроде, все публичные и виртуальные.

true_admin ★★★★★
()
Ответ на: комментарий от true_admin

В общем задумка такая.  

Например есть абстрактный класс Shape у которого есть периметр P и
 площадь S. И есть от него наследники Circle, Rectangle, и тд. 
Соответственно у каждой фигуры P и S вычисляются по своему. 
Для этого делаем две функции get_P и get_S , которые наследники
 будут переопределять . Так же у наследников могут быть свои доп. 
свойства.

class Shape(models.Model):
    p = models.InetgerField()
    s = models.IntegerField()
    
    def get_P(self):
       pass
    
    def get_S(self):
       pass

class Circle(Shape):
    r = models.IntegerField()
    
    def get_P(self):  #периметр для круга
    def get_S(self):  #площадь кргуа

class Rectangel(Shape):
    def get_P(self):  #периметр прямоугольника 
    def get_S(self):  #площадь прямоугольника

дальше у нас есть какая нибудь функция которая по запросу пользователя создает разные фигуры: 
например:
def create_shape(request, shape): 
       ....
       if shape == 'circle': 
           c = Circle()  
           ...
           c.save()
       elif shape == 'rect':
           r = Rectangle()
           ....
           r.save()

и функция которая вычисляет и выводит P,S созданных пользователем фигур. 


например:
def print_p_and_s(request):
    ....
    shapes = Shape.objects.all() #все созданные фигуры
    #вычислить p и s. соответственно для каждой 
    # фигуры должны вызываться свои get_s и get_p
    # вот тут то и нужен полиморфизм (насколько я понимаю ) 
    for i in shapes: 
        p = i.get_p()
        s = i.get_s()

Или мб есть какой нибудь  другой способ ? 

aalek
() автор топика
Ответ на: комментарий от aalek

> Или мб есть какой нибудь  другой способ ? 

У родительской модели есть метод, по которому можно достать наследуемую модель.

Пример из джанговской доки:

>>> p = Place.objects.filter(name="Bob's Cafe")
# If Bob's Cafe is a Restaurant object, this will give the child class:
>>> p.restaurant
<Restaurant: ...>

Можно проявить творческую мысль, и добавить в родительский объект поле child_type, и доставать чайлд гетаттром.

provaton ★★★★★
()
Ответ на: комментарий от provaton

>> У родительской модели есть метод, по которому можно достать наследуемую модель.

те что то типо этого:

class A(models.Model):
   child_type = models.CharField()
   .....
   def get_s(self): 
       try:
         cget_s = getattr(self, self.child_type)
         return cget_s.get_s()
       except AttributeError:
         ...

class B(A):
   .....
   def __int__(self):
      self.child_type = "b"
      .....
   .....
   def get_s(self):
      ....


В принципе это вариант. Спасибо за помощь.  

aalek
() автор топика
Ответ на: комментарий от aalek

> и функция которая вычисляет и выводит P,S созданных пользователем фигур.

Имхо ты совсем неправильно делаешь. Пусть объект сам вычисляет свою площадь и периметр. Тогда никакого гемора о котором ты писал нет.

true_admin ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.