2011-10-20 24 views
18

Tôi cần thiết lập mối quan hệ một-một mà cũng phải là chung chung. Có thể bạn có thể tư vấn cho tôi một thiết kế tốt hơn. Cho đến nay tôi đã đưa ra các mô hình sau đâyQuan hệ chung một-một trong Django

class Event(models.Model): 
    # skip event related fields... 
    content_type  = models.ForeignKey(ContentType) 
    object_id   = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

    class Meta: 
     unique_together = ('content_type', 'object_id') 

class Action1(models.Model): 
    # skip action1 related fields... 
    events = generic.GenericRelation(Event, content_type_field='content_type', object_id_field='object_id') 

    @property 
    def event(self): 
     return self.events.get() # <<<<<< Is this reasonable? 

class Action2(models.Model):... 

Trong danh sách sự kiện Django trong danh sách sự kiện Tôi muốn thu thập tất cả các hành động và từ đó tôi muốn đến trang quản trị hành động. Có thể tránh tạo tài sản event trong các mô hình hành động không? Có giải pháp nào tốt hơn không? Sẽ thật tuyệt khi kết hợp trường events và thuộc tính event theo một định nghĩa duy nhất. Dự án tôi đang làm việc với sử dụng Django 1.1

+0

Nếu bạn thực sự muốn tránh 'sự kiện', bạn sẽ cần triển khai truy vấn vào bảng' Sự kiện' theo cách thủ công, như được đề xuất bên dưới. Tôi vẫn muốn có 'sự kiện' như một GenericRelation và sau đó sử dụng' self.events.first() 'trong thuộc tính' event'. Ngoài ra, điều này sẽ dễ dàng hơn cho phép bạn loại bỏ ràng buộc duy nhất, trong tương lai. – alexcasalboni

Trả lời

14

Tôi gần đây came across this problem. Những gì bạn đã làm là tốt, nhưng bạn có thể khái quát nó hơn một chút bằng cách tạo ra một mixin mà đảo ngược mối quan hệ minh bạch:

class Event(models.Model): 
    content_type  = models.ForeignKey(ContentType) 
    object_id   = models.PositiveIntegerField() 
    content_object = generic.GenericForeignKey('content_type', 'object_id') 

    class Meta: 
     unique_together = ('content_type', 'object_id') 

class EventMixin(object): 
    @property 
    def get_event(self): 
     ctype = ContentType.objects.get_for_model(self.__class__) 
     try: 
      event = Event.objects.get(content_type__pk = ctype.id, object_id=self.id) 
     except: 
      return None 
     return event 

class Action1(EventMixin, models.Model): 
    # Don't need to mess up the models fields (make sure the mixing it placed before models.Model) 
    ... 

action = Action1.object.get(id=1) 
event = action.get_event 

Bạn có thể muốn thêm bộ nhớ đệm để điều ngược lại mối quan hệ quá

+0

Hoạt động tốt, nhưng không cung cấp khả năng: 'Action.objects.select_related ('event')' – ramusus

+0

Tôi không thích giải pháp này -> 'GenericRelation' trông đẹp hơn nhiều, ngay cả khi bạn cần sử dụng 'self.events.get()' hoặc 'self.events.first()' – alexcasalboni

+0

Giống như ý kiến ​​ở trên. Những gì bạn đã có ban đầu với 'GenericRelation' là tốt hơn nhiều. –

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