2016-06-10 24 views
6

Tôi đang cố gắng triển khai tính năng định vị địa lý cho một đội xe tải. Tôi phải liên kết một danh sách các ranh giới với một chiếc xe. Trên hết, một trong những yêu cầu đó là giữ mọi thứ ngay cả khi nó bị xóa vì mục đích kiểm toán. Vì vậy, chúng tôi phải thực hiện xóa mềm trên mọi thứ. Đây là chỗ có vấn đề. Trường nhiều đến nhiều của tôi không tuân theo trình quản lý xóa mềm, nó bao gồm cả bản ghi hoạt động và không hoạt động trong tập dữ liệu tra cứu.Làm cách nào để lọc qua Mô hình của trường nhiều đến nhiều?

class Vehicle(SoftDeleteModel): 
    routes = models.ManyToManyField('RouteBoundary', through='VehicleBoundaryMap', verbose_name=_('routes'), 
            limit_choices_to={'active': True}) 


class VehicleBoundaryMap(SoftDeleteModel): 
    vehicle = models.ForeignKey(Vehicle, verbose_name="vehicle") 
    route_boundary = models.ForeignKey(RouteBoundary, verbose_name="route boundary") 
    # ... more stuff here 

    alive = SoftDeleteManager() 


class SoftDeleteManager(models.Manager): 

    use_for_related_fields = True 

    def get_queryset(self): 
     return SoftDeleteQuerySet(self.model).filter(active=True) 

Như bạn thấy ở trên tôi đã cố gắng để đảm bảo quản lý mặc định là một người quản lý xóa mềm (ví dụ. Lọc cho hồ sơ hoạt động chỉ) và cũng có thể thử sử dụng giới hạn limit_choices_to nhưng mà bật ra trường mô hình nước ngoài chỉ không mô hình "thông qua" mà tôi muốn. Nếu bạn có bất cứ đề nghị hoặc đề nghị tôi rất thích nghe từ bạn.

Cảm ơn!

+0

Thay vì tự mình thực hiện xóa mềm, hãy sử dụng thứ gì đó như [django-reversion] (https://github.com/etianen/django-reversion). – Anonymous

+0

Xóa mềm đó đã được triển khai ở mọi nơi rồi, tôi không thể thay đổi được nữa. Tôi ước chúng ta sẽ sử dụng sự đảo ngược, nó sẽ cứu chúng ta rất nhiều đau đầu. –

Trả lời

5

Vấn đề đầu tiên: việc bạn sử dụng limit_choices_to sẽ không làm việc vì như documentation says:

limit_choices_to không có tác dụng khi sử dụng trên một ManyToManyField với một bảng tùy chỉnh trung gian quy định sử dụng tham số through.

Bạn đang sử dụng through vì vậy limit_choices_to không có hiệu lực.

Vấn đề thứ hai: việc bạn sử dụng use_for_related_fields = True cũng không hiệu quả. Các documentation nói về thuộc tính này:

Nếu thuộc tính này được thiết lập trên người quản lý mặc định cho một mô hình (chỉ có người quản lý mặc định được xem xét trong những tình huống này), Django sẽ sử dụng lớp đó bất cứ khi nào nó cần để tự động tạo một người quản lý cho lớp.

Trình quản lý tùy chỉnh của bạn được gán cho thuộc tính alive của VehicleBoundaryMap thay vì objects để bị bỏ qua.

Một cách tôi nhìn thấy mà có thể làm việc sẽ là:

  1. Tạo một proxy model cho VehicleBoundaryMap. Hãy gọi nó là VehicleBoundaryMapProxy. Đặt nó để quản lý mặc định của nó là SoftDeleteManager() Cái gì như:

    class VehicleBoundaryMapProxy(VehicleBoundaryMap): 
        class Meta: 
         proxy = True 
    
        objects = SoftDeleteManager() 
    
  2. through='VehicleBounddaryMapProxy' trên ManyToManyField của bạn:

    class Vehicle(SoftDeleteModel): 
        routes = models.ManyToManyField('RouteBoundary', 
                through='VehicleBoundaryMapProxy', 
                verbose_name=_('routes')) 
    
+0

Hãy để tôi thử này, cho đến nay có vẻ đầy hứa hẹn. –

+0

Nó hoạt động khá đẹp, cảm ơn Louis vì giải pháp. –

+0

Bạn được chào đón! – Louis

1

gì về nếu bạn chỉ cần làm:

class Vehicle(SoftDeleteModel): 
    #you can even remove that field 
    #routes = models.ManyToManyField('RouteBoundary', through='VehicleBoundaryMap', verbose_name=_('routes'), 
    #        limit_choices_to={'active': True}) 

    @property 
    def routes(self): 
     return RouteBoundary.objects.filter(
      vehicleboundarymap__active=True, 
      vehicleboundarymap__vehicle=self, 
     ) 

Và bây giờ thay vì vehicle.routes.clear(), hãy sử dụng vehicle.vehicleboundarymap_set.delete(). Bạn sẽ chỉ mất quan hệ ngược lại (RouteBoundary.vehicles) nhưng bạn có thể thực hiện lại nó bằng cách sử dụng cùng một kiểu.

Phần còn lại của M2M field tính năng là disabled vì kiểu mô hình trung gian.

+0

Tôi thích ý tưởng của bạn, nó nằm bên ngoài hộp. Tuy nhiên kể từ khi tôi không thể sử dụng prefetch trên nó, đó là một không lớn cho tôi. –

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