2015-10-29 14 views
7

Tôi có hai trường hợp liên quan nên luôn được tạo cùng nhau. Tôi muốn làm điều này mà không sử dụng tín hiệu hoặc ghi đè phương thức save() của mô hình.Phương thức quản lý tùy chỉnh Django 1.8 và .create() không được sử dụng bởi .update_or_create()

class Car(models.Mode): 
    make = models.CharField(max_length=32) 
    model = models.CharField(max_length=32) 

    class Meta: 
     unique_together = ('make', 'model',) 

    objects = CarManager() 

class CarProfile(models.Model): 
    car = models.OneToOneField(Car) 
    last_checkup = models.DateTimeField(blank=True, null=True)   

tôi đã tạo ra một CarManager tùy chỉnh đó sẽ ghi đè models.Manager.create() để đảm bảo việc tạo ra các CarProfile khi một xe được tạo ra:

class CarManager(models.Manager): 
    def create(self, **kwargs): 
     with transaction.atomic(): 
      car = self.model(**kwargs) 
      car.save(force_insert=True) 
      CarProfile.objects.create(car=car) 
     return car 

Khi tôi gọi Car.objects.create(make='Audi', model='R8'), một trường hợp xe mới và CarProfile tương ứng của nó được tạo như mong đợi. Tuy nhiên khi tôi cố gắng tạo ra một chiếc xe mới sử dụng Car.objects.update_or_create(make='Audi', model='R8') hoặc Car.objects.get_or_create(make='Audi', model='R8'), trong cả hai trường hợp một trường hợp xe được tạo ra nhưng không có CarProfile tương ứng được tạo ra.

Tại sao không update_or_createget_or_create tạo phiên bản CarProfile dự kiến ​​khi tôi đã chỉ định hành vi đó trong tùy chỉnh create() method?

Dường như cả hai phương pháp này đều gọi số create() từ lớp QuerySet thay vì lớp tùy chỉnh của tôi.

Trả lời

3

Django's Manager lớp thực sự là QuerySet đã là reconstituted vào một Manager. Điều gì sẽ xảy ra nếu bạn triển khai create trên QuerySet và sau đó xây dựng một Manager từ đó?

class CarQuerySet(models.QuerySet): 

    def create(self, **kwargs): 
     with transaction.atomic(): 
      car = self.model(**kwargs) 
      car.save(force_insert=True) 
      CarProfile.objects.create(car=car) 
     return car 

Sau đó Car là:

class Car(models.Mode): 
    make = models.CharField(max_length=32) 
    model = models.CharField(max_length=32) 

    class Meta: 
     unique_together = ('make', 'model',) 

    objects = CarQuerySet.as_manager() 
+0

Tôi đã nhận thấy cách Trình quản lý thực sự được kế thừa từ 'BaseManager.from_queryset (QuerySet)'. Tôi có thể sai, nhưng có vẻ như ['from_queryset'] (https://goo.gl/1L0x8N) và [' _get_queryset_methods'] (https://goo.gl/uEssIf) tạo một lớp học đặc biệt cho Người quản lý lớp con sao chép trên bất kỳ phương thức nào trong 'QuerySet' không được định nghĩa trong' BaseManager'. Lớp 'CarManager' của tôi sau đó phân lớp lớp ad-hoc đó nên tôi bị nhầm lẫn là tại sao' create' không ghi đè lên một 'QuerySet' chỉ cho' update_and_create' và 'get_or_create'. – lajitong

+1

Ngoài ra, @Nathan Villaescusa, cảm ơn bạn đã trả lời. Tôi đã kết thúc việc tạo ra một tùy chỉnh 'CarQuerySet' và trả về một thể hiện của nó trong' get_queryset' của 'CarManager' (tôi đã có các phương thức quản lý khác trong đó). 'update_and_create' và' get_or_create' hiện có hành vi đúng. Nhưng tôi vẫn tự hỏi tại sao triển khai trước đó của tôi không hoạt động. – lajitong

2

Lý do thực tế rằng trọng create không hoạt động trong trường hợp này là bởi vì bạn cần phải ghi đè cả update_and_createget_or_create phương pháp cũng như create ảnh hưởng đến hành vi của họ.

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