2013-05-18 39 views
5

Có cách nào thông minh để thực hiện xóa trong trường hợp này không?Xóa đối tượng liên quan qua OneToOneField

class Bus(models.Model): 
    wheel = OneToOneField(Wheel) 

class Bike(models.Model): 
    wheel = OneToOneField(Wheel) 
    pedal = OneToOneField(Pedal) 

class Car(models.Model): 
    wheel = OneToOneField(Wheel) 

class Wheel(models.Model): 
    somfields 

car = Car()  
wheel = Wheel() 
wheel.save() 
car.wheel = wheel 
car.save() 
car.delete() # I want to delete also wheel (and also all stuff pointing via OneToOneField eg pedal) 

Tôi có cần phải ghi đè lên các phương pháp xóa của xe hơi, xe đạp, mô hình xe buýt hoặc là có một số cách tốt hơn? Tùy chọn khác là tạo ra các trường ô tô, xe đạp, xe buýt trên mô hình Bánh xe, nhưng nó không có ý nghĩa nhiều.

Trả lời

9

Đây là điều, kể từ khi Car liên kết đến Wheel, đây là mô hình phụ thuộc trong mối quan hệ. Do đó, khi bạn xóa Wheel, nó sẽ xóa tất cả các kiểu phụ thuộc (bao gồm cả Car hàng có liên quan). Tuy nhiên, khi bạn xóa Car, kể từ Wheel không phụ thuộc vào Car, nó sẽ không bị xóa.

Để xóa quan hệ cha mẹ trong Django, bạn có thể ghi đè lên delete phương pháp 's Car:

class Car(models.Model): 
    # ... 

    def delete(self, *args, **kwargs): 
     self.wheel.delete() 
     return super(self.__class__, self).delete(*args, **kwargs) 

Sau đó, khi thực hiện:

Car.objects.get(...).delete() 

cũng sẽ xóa Wheel.

+1

Vấn đề với trọng 'xóa() 'phương pháp này là nó sẽ không được gọi là nếu bạn làm với số lượng lớn xóa hoạt động như 'Car.objects.filter(). Delete()' – Rohan

+2

@Rohan có bạn nói đúng. Đối với hoạt động xóa hàng loạt aka. querysets theo khuyến cáo của django docs - https://docs.djangoproject.com/en/dev/ref/models/querysets/#django.db.models.query.QuerySet.delete sử dụng tín hiệu django 'post_delete' decorator. –

+0

@Rohan Để cụ thể một đoạn trích cho liên kết tài liệu django ở trên - >> Phương thức delete() thực hiện xóa hàng loạt và không gọi bất kỳ phương thức delete() nào trên các mô hình của bạn. Nó không, tuy nhiên, phát ra các tín hiệu pre_delete và post_delete cho tất cả các đối tượng đã xóa (bao gồm xóa các tầng). –

7

Xóa tầng đã được cung cấp bởi django, thông qua on_delete giá trị thuộc tính CASCADE. Nó cũng có sẵn cho OneToOneField cùng với ForeignKey.

ForeignKey.on_delete

Khi một đối tượng được tham chiếu bởi một ForeignKey là xóa, Django theo mặc định mô phỏng hành vi của các hạn chế SQL ON DELETE CASCADE và cũng xóa các đối tượng có chứa các ForeignKey.

Tuy nhiên, trong các mô hình của bạn, bạn đang đặt OneToOneField trong một mô hình khác, do đó bạn không thấy hành vi mong đợi.

Thay đổi mô hình của bạn:

class Car(models.Model): 
    somefields 

class Wheel(models.Model): 
    somfields 
    car = OneToOneField(Car) 

Đó là đưa OneToOneField trong Wheel mô hình thay vì Car. Giờ đây, khi bạn xóa Car mô hình tương ứng Wheel cũng sẽ bị xóa.

Vấn đề với phương pháp trọng delete() là nó sẽ không được gọi nếu bạn làm với số lượng lớn xóa hoạt động như Car.objects.filter().delete()

+0

Vâng, đó là những gì tôi muốn tránh để có các ô tô vv trên mô hình Bánh xe. Vì vậy, đối với tôi giải pháp tốt nhất trông giống như nghe tín hiệu pre_delete, tìm tất cả OneToOneFields và xóa chúng theo cách thủ công. – ChRapO

+0

@ChRapO, Làm thế nào mà vấn đề mà nó được xác định? Bạn có thể có 'parent_link = True' nếu bạn muốn liên kết ngược. – Rohan

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