2016-01-11 14 views
7

Tôi đang cố gắng tạo chế độ xem nơi tôi lưu đối tượng nhưng tôi muốn hoàn tác lưu nếu một số ngoại lệ được nêu ra. Đây là những gì tôi đã thử:Django - Rollback lưu với giao dịch nguyên tử

class MyView(View): 

    @transation.atomic 
    def post(self, request, *args, **kwargs): 
     try: 
      some_object = SomeModel(...) 
      some_object.save() 

      if something: 
       raise exception.NotAcceptable() 
       # When the workflow comes into this condition, I think the previous save should be undome 
       # Whant am I missing? 

     except exception.NotAcceptable, e: 
      # do something 

Tôi đang làm gì sai? ngay cả khi ngoại lệ được nâng lên some_object vẫn còn trong DataBase.

Trả lời

11

Atomicity Documentation

để tóm tắt, @transaction.atomic sẽ thực hiện giao dịch trên cơ sở dữ liệu nếu chế độ xem của bạn tạo ra phản hồi không có lỗi. Bởi vì bạn đang bắt các ngoại lệ cho mình, nó xuất hiện để Django rằng quan điểm của bạn thực hiện tốt.

Nếu bạn bắt ngoại lệ, bạn cần phải xử lý nó tự hỏi: Controlling Transactions

Nếu bạn cần để tạo ra một phản ứng json thích hợp trong trường hợp thất bại:

from django.db import SomeError, transaction 

def viewfunc(request): 
    do_something() 

    try: 
     with transaction.atomic(): 
      thing_that_might_fail() 
    except SomeError: 
     handle_exception() 

    render_response() 
+0

Chế độ xem này dành cho API, vì vậy tôi nghĩ rằng tôi cần xử lý bất kỳ lỗi nào có thể để đưa ra phản hồi json propper. Không có cách nào để làm điều này với trang trí nguyên tử? – Gocht

+0

Không phải với trang trí imho, bởi vì nó xử lý giao dịch bên ngoài chức năng của bạn. Ví dụ hay với trình quản lý ngữ cảnh! – jpic

+0

Bạn phải có một khối nguyên tử bên trong thử .. trừ khối như trong câu trả lời. Bạn cũng có thể sử dụng trình trang trí nguyên tử trên chế độ xem nếu bạn muốn. – Alasdair

5

Tuy nhiên, nếu một ngoại lệ xảy ra trong một chức năng được trang trí với transaction.atomic, sau đó bạn không có bất cứ điều gì để làm, nó sẽ rollback automatically to the savepoint created by the decorator before running the your function, như documented:

nguyên tử cho phép chúng ta tạo ra một khối mã trong đó nguyên tử trên cơ sở dữ liệu được đảm bảo. Nếu khối mã được hoàn tất thành công, các thay đổi được cam kết với cơ sở dữ liệu. Nếu có ngoại lệ, các thay đổi sẽ được khôi phục.

Nếu ngoại lệ được đánh bắt trong một ngoại trừ khối, sau đó nó nên được tái huy động cho nguyên tử để bắt nó và làm rollback, tức là .:

try: 
     some_object = SomeModel(...) 
     some_object.save() 

     if something: 
      raise exception.NotAcceptable() 
      # When the workflow comes into this condition, I think the previous save should be undome 
      # Whant am I missing? 

    except exception.NotAcceptable, e: 
     # do something 
     raise # re-raise the exception to make transaction.atomic rollback 

Ngoài ra, nếu bạn muốn kiểm soát nhiều hơn , bạn có thể rollback bằng tay để previously set savepoint, tức là .:

class MyView(View): 
    def post(self, request, *args, **kwargs): 
     sid = transaction.savepoint() 
     some_object = SomeModel(...) 
     some_object.save() 

     if something: 
      transaction.savepoint_rollback(sid) 
     else: 
      try: 
       # In worst case scenario, this might fail too 
       transaction.savepoint_commit(sid) 
      except IntegrityError: 
       transaction.savepoint_rollback(sid) 
+0

Đó là những gì tôi mặc dù, và đó là lý tại sao tôi đã thực hiện chức năng này theo cách này, nhưng như tôi đã nói trong câu hỏi, đối tượng vẫn còn trong sự kiện cơ sở dữ liệu khi ngoại lệ được nêu ra, liệu có bước nào để sử dụng các điểm lưu trữ không? – Gocht

+0

Có lẽ đó là vì ngoại lệ đã bị bắt bởi khối ngoại trừ, và không được nâng lên, do đó, nguyên tử nghĩ rằng nó thực hiện chức năng thành công. – jpic

+0

Nếu tôi không bắt được lỗi, tôi không thể trả lời tốt. Làm thế nào tôi có thể xây dựng chức năng của tôi? – Gocht

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