2010-10-13 31 views
5

Tôi vẫn còn một chút nhầm lẫn về mối quan hệ của mô hình Proxy cho Superclasses của họ trong django. Câu hỏi của tôi bây giờ là làm thế nào để có được một thể hiện của một mô hình Proxy từ một thể hiện đã được truy xuất của Superclass?bằng cách sử dụng django, làm thế nào để tôi xây dựng một thể hiện đối tượng proxy từ một cá thể đối tượng superclass?

Vì vậy, cho phép nói rằng tôi có:

class Animal(models.Model): 
    type = models.CharField(max_length=20) 
    name = models.CharField(max_length=40) 

class Dog(Animal): 
    class Meta: 
     proxy = True 

    def make_noise(self): 
     print "Woof Woof" 

Class Cat(Animal): 
    class Meta: 
     proxy = True 

    def make_noise(self): 
     print "Meow Meow" 

animals = Animal.objects.all() 
for animal in animals: 
    if (animal.type == "cat"): 
     animal_proxy = # make me a cat 
    elif (animal.type == "dog"): 
     animal_proxy = # make me a dog 
    animal_proxy.make_noise() 

OK. Vì vậy, .. gì đi vào "# làm cho tôi một con mèo" mà không đòi hỏi một truy vấn trở lại cơ sở dữ liệu như:

animal_proxy = Cat.objects.get(id=animal.id) 

Có cách nào đơn giản để tạo một thể hiện của Cát từ một thể hiện của động vật mà tôi biết là một con mèo?

Trả lời

5

Bạn đang cố gắng triển khai tính kiên trì cho một hệ thống phân cấp thừa kế. Sử dụng một bảng bê tông và một công tắc type là một cách hay để thực hiện việc này. Tuy nhiên, tôi cho rằng triển khai của bạn, cụ thể là:

for animal in animals: 
    if (animal.type == "cat"): 
     animal_proxy = # make me a cat 

sẽ chống lại hạt của Django. Loại chuyển đổi không nên không liên quan đến lớp proxy (hoặc mô hình).

Nếu tôi là bạn, tôi sẽ làm như sau:

Đầu tiên, thêm trình quản lý "nhận thức loại" vào mô hình proxy. Điều này sẽ đảm bảo rằng Dog.objects sẽ luôn tìm nạp Animal trường hợp với type="dog"Cat.objects sẽ tìm nạp Animal trường hợp với type="cat".

class TypeAwareManager(models.Manager): 
    def __init__(self, type, *args, **kwargs): 
     super(TypeAwareManager, self).__init__(*args, **kwargs) 
     self.type = type 

    def get_query_set(self): 
     return super(TypeAwareManager, self).get_query_set().filter(
       type = self.type) 

class Dog(Animal): 
    objects = TypeAwareManager('dog') 
    ... 

class Cat(Animal): 
    objects = TypeAwareManager('cat') 
    ... 

Thứ hai, tìm nạp các trường hợp phân lớp riêng biệt. Sau đó, bạn có thể kết hợp chúng trước khi hoạt động trên chúng. Tôi đã sử dụng itertools.chain để kết hợp hai Querysets.

from itertools import chain 
q1 = Cat.objects.all() # [<Cat: Daisy [cat]>] 

q2 = Dog.objects.all() # [<Dog: Bruno [dog]>] 

for each in chain(q1, q2): 
    each.make_noise() 

# Meow Meow 
# Woof Woof 
+0

Tôi biết rằng tôi sẽ chống lại hạt của Django. Tôi làm điều này bởi vì Django không cho phép tôi làm những gì tôi muốn, đó là có được một danh sách các đối tượng được lưu trữ trong cùng một bảng nhưng trong đó có các thuộc tính khác nhau mà không thực sự chuỗi kết quả với nhau. Tôi đã xây dựng một trình quản lý nhận biết kiểu, nhưng ở cấp độ siêu lớp và bây giờ tôi chỉ cần 'bỏ' trả về các cá thể đối tượng siêu lớp để trở thành các đối tượng lớp proxy. Có cách nào để làm điều này không? –

+0

Trên thực tế, tôi đã làm điều này, nhưng tôi hiện đang thực hiện một cuộc gọi trở lại cơ sở dữ liệu theo: animal_proxy = Cat.objects.get (id = animal.id) Tôi muốn một cái gì đó giống như animal_proxy = (Cat) động vật. tôi biết có phải là thủ đoạn python mà có thể làm điều này cho tôi. –

+0

@Bubba: Xem câu hỏi này. Các câu trả lời có thể được bạn quan tâm. http://stackoverflow.com/questions/2218867/right-way-to-return-proxy-model-instance-from-a-base-model-instance-in-django –

2

tôi sẽ làm:

def reklass_model(model_instance, model_subklass): 

    fields = model_instance._meta.get_all_field_names() 
    kwargs = {} 
    for field_name in fields: 
     try: 
      kwargs[field_name] = getattr(model_instance, field_name) 
     except ValueError as e: 
      #needed for ManyToManyField for not already saved instances 
      pass 

    return model_subklass(**kwargs) 

animals = Animal.objects.all() 
for animal in animals: 
    if (animal.type == "cat"): 
     animal_proxy = reklass_model(animal, Cat) 
    elif (animal.type == "dog"): 
     animal_proxy = reklass_model(animal, Cat) 
    animal_proxy.make_noise() 

# Meow Meow 
# Woof Woof 

tôi đã không thử nghiệm nó với "sở thú";) nhưng với mô hình của riêng tôi dường như làm việc.

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