2009-10-28 29 views
10

Tôi đang cố gắng cập nhật ngay lập tức một bản ghi sau khi đã lưu. Ví dụ này có vẻ vô nghĩa nhưng hãy tưởng tượng chúng ta cần phải sử dụng một API sau khi dữ liệu được lưu để có được một số thông tin thêm và cập nhật các bản ghi:post_save trong django để cập nhật phiên bản ngay lập tức

def my_handler(sender, instance=False, **kwargs): 
    t = Test.objects.filter(id=instance.id) 
    t.blah = 'hello' 
    t.save() 

class Test(models.Model): 
    title = models.CharField('title', max_length=200) 
    blah = models.CharField('blah', max_length=200) 

post_save.connect(my_handler, sender=Test) 

Vì vậy, các trường 'thêm' là nghĩa vụ phải được thiết lập để 'hello' sau mỗi lần lưu. Chính xác? Nhưng nó không hoạt động.

Bất kỳ ý tưởng nào?

+0

Có thể bạn có thể mô tả cách nó không hoạt động? Lúc đầu đỏ mặt, nó có vẻ như nó sẽ làm cho một vòng lặp vô hạn, kể từ khi post_save gọi tiết kiệm, mà nên gọi post_save, vv Có lẽ Django đang ngăn chặn đệ quy? –

+0

Tôi thấy một vòng lặp vô hạn ở đó. Sau khi t.save() một tín hiệu post_save được gửi đi, hãy đoán hàm nào được gọi là ... – stefanw

+0

oh, tôi đã bị ấn tượng bởi Django sẽ không để cho post_save lưu lại lần thứ hai nữa? Tôi đoán là không. Trong trường hợp đó, bạn đã đúng. Nó sẽ là một vòng lặp vô hạn. Nhưng tôi không thấy vòng lặp hay gì cả. – givp

Trả lời

18

Khi bạn thấy mình sử dụng tín hiệu post_save để cập nhật đối tượng của lớp người gửi, rất có thể bạn nên ghi đè phương pháp lưu thay thế. Trong trường hợp của bạn, định nghĩa mô hình sẽ trông giống như:

class Test(models.Model): 
    title = models.CharField('title', max_length=200) 
    blah = models.CharField('blah', max_length=200) 

    def save(self, force_insert=False, force_update=False): 
     if not self.blah: 
      self.blah = 'hello' 
     super(Test, self).save(force_insert, force_update) 
+1

Nếu anh ta làm điều này với các mô hình quản trị, post_save là một giải pháp tốt hơn so với phân lớp các mô hình quản trị hiện có và ghi đè lưu. –

+0

@Paul McMillan tại sao? –

+0

'using = False' là cần thiết tại 'lưu' phương pháp đối số danh sách trong Django 1.3 và cao hơn – eviltnan

6

Trình xử lý post_save không lấy trường hợp? Tại sao bạn lọc bằng cách sử dụng nó? Tại sao không chỉ làm:

def my_handler(sender, instance=False, created, **kwargs): 
    if created: 
    instance.blah = 'hello' 
    instance.save() 

Mã hiện tại của bạn không hoạt động vì vòng lặp và Test.objects.filter(id=instance.id) trả về bộ truy vấn chứ không phải đối tượng. Để nhận trực tiếp một đối tượng, sử dụng Queryset.get(). Nhưng bạn không cần phải làm điều đó ở đây. Đối số được tạo sẽ giữ cho nó khỏi vòng lặp, vì nó chỉ đặt nó lần đầu tiên.

Nói chung, trừ khi bạn hoàn toàn cần sử dụng tín hiệu post_save, bạn nên ghi đè phương thức save() của đối tượng của mình.

+0

Tôi thực sự đã thử rằng cũng không có kết quả. nhưng nếu những người ở trên là chính xác, tôi không thể làm điều này anyway vì nó sẽ chỉ gặp khó khăn trong một vòng post_save. – givp

+0

Hãy thử sử dụng cờ đã tạo. Tôi nghĩ rằng nên khắc phục vấn đề của bạn, bởi vì tạo ra được bỏ đặt trên các vòng lặp tiếp theo thông qua. –

+1

Bạn có thể muốn xem câu hỏi này để biết thêm thông tin về thời điểm sử dụng tín hiệu và thời điểm ghi đè lưu: http://stackoverflow.com/questions/170337/django-signals-vs-overriding-save-method –

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