2012-08-03 27 views
6

Tôi muốn tạo mối quan hệ đối xứng trên mô hình của mình và cũng thêm một trường trong mối quan hệ. Tôi đã xem qua số this blog (và cũng là this another blog) và làm theo các bước trong việc tạo mô hình của riêng tôi.Làm thế nào để tự động tạo đối tượng đối xứng trên ManyToManyField của Django?

class CreditCardIssuer(models.Model): 
    name = models.CharField(_('name'), max_length=256) 
    transfer_limits = models.ManyToManyField('self', through='Balancetransfer', related_name='no_transfer_allowed+', symmetrical=False, help_text=_('List of issuers to which balance transfer is not allowed.')) 

    def add_balancetransfer(self, creditcardissuer, until): 
     balance_transfer, _newly_created = Balancetransfer.objects.get_or_create(
      no_transfer_from=self, 
      no_transfer_to=creditcardissuer, 
      until=until) 
     balance_transfer, _newly_created = Balancetransfer.objects.get_or_create(
      no_transfer_from=creditcardissuer, 
      no_transfer_to=self, 
      until=until) 
     return balance_transfer 

    def remove_balancetransfer(self, creditcardissuer, until): 
     Balancetransfer.objects.filter(
      no_transfer_from=self, 
      no_transfer_to=creditcardissuer, 
      until=until).delete() 
     Balancetransfer.objects.filter(
      no_transfer_from=self, 
      no_transfer_to=creditcardissuer, 
      until=until).delete() 
     return 

    def get_transfer_limits(self, until): 
     return self.transfer_limits.filter(
      no_transfer_to__until=until, 
      no_transfer_to__no_transfer_from=self) 


class Balancetransfer(models.Model): 
    no_transfer_from = models.ForeignKey('CreditCardIssuer', related_name='no_transfer_from') 
    no_transfer_to = models.ForeignKey('CreditCardIssuer', related_name='no_transfer_to') 
    until = models.IntegerField(blank=True, null=True, help_text='Minimum card ownership period to allow balance transfer.') 

    class Meta: 
     unique_together = ('no_transfer_from', 'no_transfer_to') 

Nhưng khi tôi tạo mối quan hệ từ quản trị, chỉ một người được tạo. Bạn có thể giúp tôi tìm ra vấn đề không?

+0

Bạn có thể có thể xây dựng một chút chi tiết hơn những gì bạn có ý nghĩa với _only ai created_? Hoặc xác định những gì bạn mong đợi sẽ xảy ra? –

+0

Chức năng CreditCardIssuer.add_balancetransfer hiển thị những gì tôi muốn thực hiện khi tạo mối quan hệ từ quản trị viên. Bằng cách đó, mối quan hệ sẽ được tạo ra cho cả hai đối tượng. Cảm ơn bạn đã dành thời gian giải quyết nó. – noel

+0

Hai mối quan hệ sẽ không được tạo "tự động" - tôi không rõ 100% mặc dù bạn đang mong đợi hành vi nào. Bạn có thể xây dựng? – coleifer

Trả lời

1

Bạn nói rằng bạn đã có một nửa số này trong quản trị Django (bạn không nói như thế nào, nhưng tôi sẽ giả sử nó hoạt động trừ khi bạn đăng mã): bước còn lại là thiết lập một nửa mối quan hệ còn thiếu.

tôi nghi ngờ rằng nếu bạn đặt một breakpoint trong phương pháp add_balancetransfer() của bạn (import pdb; pdb.set_trace()), bạn sẽ thấy rằng nó không bao giờ được gọi là - một phần của mối quan hệ đó được tạo ra được thực hiện thông qua xây dựng trong hành vi admin Django .

Tóm lại, bạn có thể chỉ cần tự gọi add_balancetransfer() khi mô hình được lưu - hoặc, tốt hơn, một phiên bản khác chỉ thêm mối quan hệ còn thiếu.

Một cách để làm điều này là overriding the model's save() method, nhưng điều này có thể là một chút mong manh. Đối với tình hình của bạn, nó có thể làm việc tốt hơn để điền vào các mối quan hệ thiếu trong model's post_save signal:

from django.db.models.signals import post_save 
from django.dispatch import receiver 

from yourapp.models import CreditCardIssuer 

@receiver(post_save, sender=CreditCardIssuer) 
def add_missing_relationship(sender, **kwargs): 
    # Add the other side of what should be a symmetrical relationship 
    ... 
+0

Cảm ơn các đề xuất. Tôi đã thêm một số đăng nhập trong các phương pháp đó và xác nhận rằng chúng không bao giờ được gọi. Nếu không có cách tự động để tạo đối tượng quan hệ ngược lại, có lẽ tôi sẽ đi với phương thức save() ghi đè. – noel

+0

@supervacuo trông giống như lỗi đánh máy. Quá trình nhập của bạn dành cho post_save và người nhận của bạn sử dụng pre_save. – hobs

+0

@hobs tốt, cảm ơn bạn. Đã sửa (thành 'post_save') ngay bây giờ. – supervacuo

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