2009-10-17 33 views
5

Tôi có một mô hìnhThừa kế Django: cách có một phương thức cho tất cả các lớp con?

BaseModel 

và một số lớp con của nó

ChildModelA(BaseModel), ChildModelB(BaseModel), ... 

sử dụng đa bảng thừa kế. Trong tương lai tôi dự định có hàng chục mô hình phân lớp.

Tất cả các lớp con có một số thực hiện của phương pháp

do_something() 

Làm thế nào tôi có thể gọi do_somthing từ một trường hợp BaseModel?

vấn đề

Hầu như giống hệt nhau (không có giải pháp) được đăng tải ở đây:
http://peterbraden.co.uk/article/django-inheritance

Một câu hỏi đơn giản: làm thế nào tôi giải quyết BaseModel instnace đến một trong những ví dụ lớp con của nó mà không cần kiểm tra tất cả các lớp con có thể?

Trả lời

1

Bạn có bao giờ làm việc với một thể hiện của loại cơ sở hoặc bạn sẽ luôn làm việc với các trường hợp của trẻ em không? Nếu trường hợp sau là trường hợp thì hãy gọi phương thức, ngay cả khi bạn có một tham chiếu đến kiểu cơ sở vì đối tượng IS-A là một kiểu con.

Vì hỗ trợ Python duck typing điều này có nghĩa là cuộc gọi phương thức của bạn sẽ là trái phiếu thích hợp vì trường hợp con sẽ thực sự có phương pháp này.

Một phong cách lập trình pythonic mà xác định loại hình của một đối tượng bằng cách kiểm tra phương pháp của mình hoặc thuộc tính chữ ký chứ không phải bởi rõ ràng mối quan hệ với một số đối tượng loại (“Nếu nó trông giống như một con vịt và quacks như một vịt, nó phải là một con vịt. ”) Bằng cách nhấn mạnh các giao diện thay vì các loại cụ thể, mã được thiết kế tốt cải thiện tính linh hoạt của nó bằng cách cho phép thay thế đa hình. Nhập sai số tránh các bài kiểm tra bằng cách sử dụng loại() hoặc isinstance(). (Lưu ý, tuy nhiên, nhập vịt có thể được bổ sung với lớp cơ sở trừu tượng.) Thay vào đó, nó thường sử dụng các thử nghiệm hasattr() hoặc lập trình EAFP.

Lưu ý rằng EAFP là viết tắt của Easier to Ask Forgiveness than Permission:

dễ dàng hơn để xin tha thứ hơn cho phép. Kiểu mã hóa Python phổ biến này giả định sự tồn tại của các khóa hoặc thuộc tính hợp lệ và bắt ngoại lệ nếu giả thiết chứng minh là sai. Phong cách sạch sẽ và nhanh chóng này được đặc trưng bởi sự hiện diện của nhiều câu thử và ngoại trừ. Kỹ thuật này tương phản với kiểu LBYL chung với nhiều ngôn ngữ khác như C.

+1

Điều này là đúng, nhưng không liên quan trong trường hợp này. Vấn đề chính là khi làm việc với sự thừa kế đa bảng Django, người ta thường có một cá thể của lớp cơ sở có sẵn (tức là từ truy vấn bảng cơ sở), mặc dù đối tượng là "thực sự" của một kiểu con (tức là có một nhập vào bảng con). –

0

Tôi đồng ý với Andrew. Trên một vài trang, chúng tôi có một lớp hỗ trợ toàn bộ các phương thức (nhưng không phải các trường (đây là tiền tố ORM trước)) phổ biến đối với hầu hết các lớp nội dung của chúng tôi. Họ sử dụng hasattr để tránh các tình huống mà phương thức không có ý nghĩa.

Điều này có nghĩa hầu hết các lớp học của chúng tôi được định nghĩa là:

class Foo(models.Model, OurKitchenSinkClass): 

Về cơ bản nó là loại một loại mixin điều. Hoạt động tuyệt vời, dễ bảo trì.

2

Nếu bạn muốn tránh kiểm tra tất cả các lớp con có thể, cách duy nhất tôi có thể nghĩ là lưu trữ tên lớp được liên kết với lớp con trong trường được xác định trên lớp cơ sở. lớp cơ sở của bạn có thể có một phương pháp như thế này:

def resolve(self): 
    module, cls_name = self.class_name.rsplit(".",1) 
    module = import_module(module) 
    cls = getattr(module, cls_name) 
    return cls.objects.get(pk=self.pk) 

Câu trả lời này không làm cho tôi hạnh phúc và tôi cũng rất thích nhìn thấy một giải pháp tốt hơn, như tôi sẽ phải đối mặt với một vấn đề tương tự sớm.

+0

Đây chủ yếu là những gì bạn phải làm, nhưng có những cách sạch hơn để làm điều đó (sử dụng contrib.contenttypes). Xem câu trả lời của tôi. –

+0

Xin chào Carl, tôi không thể thấy câu trả lời của bạn. Bạn có thể repost có thể, hoặc cung cấp cho một liên kết hữu ích. Cảm ơn –

+0

Đừng bận tâm, tôi hiểu rồi. Cảm ơn Carl vì lời giải thích của bạn. –

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