2011-09-23 33 views
7

Mô hình Discount của tôi mô tả các trường phổ biến cho tất cả các loại giảm giá trong hệ thống. Tôi có một số mô hình proxy mô tả thuật toán cụ thể cho tổng số. Lớp cơ sở Discount có trường thành viên có tên là type, là một chuỗi nhận dạng loại của nó và lớp liên quan của nó.Mô hình đa hình django với kế thừa proxy

class Discount(models.Model): 
    TYPE_CHOICES = (
    ('V', 'Value'), 
    ('P', 'Percentage'), 
) 

    name = models.CharField(max_length=32) 
    code = models.CharField(max_length=32) 
    quantity = models.PositiveIntegerField() 
    value = models.DecimalField(max_digits=4, decimal_places=2) 
    type = models.CharField(max_length=1, choices=TYPE_CHOICES) 

    def __unicode__(self): 
    return self.name 

    def __init__(self, *args, **kwargs): 
    if self.type: 
     self.__class__ = getattr(sys.modules[__name__], self.type + 'Discount') 
    super(Discount, self).__init__(*args, **kwargs) 

class ValueDiscount(Discount): 
    class Meta: 
    proxy = True 

    def total(self, total): 
    return total - self.value 

Nhưng tôi vẫn nhận ngoại lệ của AttributeError nói rằng bản thân không có loại. Làm thế nào để sửa lỗi này hoặc là có một cách khác để đạt được điều này?

Trả lời

11

phương pháp init của bạn cần phải trông giống như thay vì điều này:

def __init__(self, *args, **kwargs): 
    super(Discount, self).__init__(*args, **kwargs) 
    if self.type: 
     self.__class__ = getattr(sys.modules[__name__], self.type + 'Discount') 

Bạn cần phải gọi siêu của __init__ trước khi bạn sẽ có thể truy cập self.type.

Kêu gọi với trường của bạn typetype cũng là một hàm được xây dựng sẵn trong python, mặc dù bạn có thể không gặp phải bất kỳ sự cố nào.

Xem: http://docs.python.org/library/functions.html#type

+0

Cảm ơn bạn. Còn một câu hỏi nữa, tại sao tôi cần gọi super __init__ trước khi truy cập các thuộc tính của đối tượng? Tôi nghĩ rằng đó là một con trăn mà làm cho tất cả các thành viên tuyên bố trong đối tượng có thể truy cập trong constructor, không phải siêu lớp (models.Model từ Django). Làm thế nào mà? – aambrozkiewicz

+2

Điều này là do django.db.models.Model có '__metaclass__ = ModelBase'. Điều này có nghĩa là django sử dụng 'ModelBase' để tạo lớp Model của bạn thay vì' type' thông thường. Tôi khuyên bạn nên đọc: http://stackoverflow.com/questions/100003/what-is-a-metaclass-in-python - và một khi bạn đã thành thạo metaclasses, hãy xem mã nguồn django. –

0

gọi super(Discount, self).__init__(*args, **kwargs) trước khi tham khảo self.type.

Các vấn đề liên quan