2

나는 장고 앱을 개발하는 중이며 코드에서 오류와 버그를 처리하는 적절한 방법에 대한 조언을 받기를 희망합니다.Django/Python 응용 프로그램에서 적절한 오류 처리를위한 코드를 설계 하시겠습니까?

다음은 내가 가진 문제의 예입니다. 사용자가 제품을 구매했습니다.

  1. 먼저, 뷰가 데이터베이스에 User 객체를 생성해야합니다 구입을 처리하려면, 내보기는 여러 작업을 수행해야합니다.
  2. 성공적이면보기에서 Order 개체를 만들어 새로 만든 사용자에게 할당해야합니다.
  3. 성공한 경우 내 코드는 Product 개체를 만들어 새로 만든 Order에 추가해야합니다.

오류가 발생하지 않은 경우이 모든 경우에 문제가 발생하지 않지만 가끔 오류가 발생하는 것은 필연적이며 오류가 발생하지 않도록 정상적으로 오류를 처리하기를 원합니다. 예를 들어 어떤 이유로 든 Order 개체를 만들 수 없으면보기에 사용자에게 오류가 표시되고 이전에 만들어진 User 개체가 제거되어야합니다. 그리고, 그것은 명백하게 충돌하고 사용자에게 Http 500 오류를 제공하기보다는 우아한 오류 메시지를 던져야합니다.

내가 이것을 할 수있는 유일한 방법은 아래와 같이 중첩 된 try/except 절의 매우 복잡한 시리즈입니다. 그러나이 방법으로 코드를 작성하는 것은 지저분하고 시간이 오래 걸리고 일을 올바르게 수행하는 것처럼 느껴지지 않습니다. 장고와 파이썬에서 적절한 오류 처리를 설계하는 더 좋은 방법이 있어야한다는 것을 알고 있지만 그것이 무엇인지는 확실하지 않습니다.

이 상황에서 코드를 더 잘 구조화하는 방법에 대한 조언을 주시면 감사하겠습니다.

예제 코드 :이 방법에 대해

try: 

    # Create a new user 
    u = User(email='[email protected]') 
    u.save() 

    try: 

     # Create a new order 
     o = Order(user=u, name='Order name') 
     o.save() 

     try: 

      # Create a new product 
      p = Product(order=o, name='Product name') 
      p.save() 

     # If a product cannot be created, print an error message and try deleting the user and order that were previously created 
     except: 

      messages.add_message(request, messages.ERROR, 'Product could not be created') 

      # If deleting the order doesn't work for any reason (for example, o.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
      try: 
       o.delete() 

      # I use these 'except: pass' clauses to ensure that if an error occurs, my app doesn't serve a Http 500 error and instead shows the user a graceful error 
      except: 
       pass 

      # If deleting the user doesn't work for any reason (for example, u.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
      try: 
       u.delete() 
      except: 
       pass 

    # If an order cannot be created, print an error message and try deleting the user that was previously created 
    except: 
     messages.add_message(request, messages.ERROR, 'Order could not be created') 

     # If deleting the user doesn't work for any reason (for example, u.save() didn't properly save the user), 'pass' to ensure my application doesn't crash 
     try: 
      u.delete() 
     except: 
      pass 

# If the user cannot be created, throw an error 
except: 
    messages.add_message(request, messages.ERROR, 'User could not be created') 

답변

3

내가 (장고 문서에서 link)과 같이 당신의 모델 생성을 묶어야한다 transaction.atomic 블록을 사용하는 것이 좋습니다 문제.

P. 실제로 이것은 django가 기본적으로 각각의 뷰를 처리하는 방법이지만, 이 될 것이므로 500 개의 오류를 없애고 발생한 모든 문제를 해결할 수 있습니다. .

+0

이것이 정확히 내가 찾고 있었던 것이다. 도와 줘서 고마워! – Sam

-1

? 생성하려는 각 항목에 None을 할당하십시오. 인스턴스 생성자 (생성자 호출)가 예외를 throw하면 None으로 유지됩니다. 반면에 올바르게 인스턴스화되었지만 제대로 저장되지 않으면 기본 키가 None이됩니다. 따라서 :

u = None 
o = None 
p = None 

try: 
    # Create a new user 
    u = User(email='[email protected]') 
    u.save() 

    # Create a new order 
    o = Order(user=u, name='Order name') 
    o.save() 

    # Create a new product 
    p = Product(order=o, name='Product name') 
    p.save() 

except: 
    if u == None or u.pk == None: 
     messages.add_message(request, messages.ERROR, 'User could not be created') 

    else if o == None or o.pk == None: 
     messages.add_message(request, messages.ERROR, 'Order could not be created') 

    else if p == None or p.pk == None: 
     messages.add_message(request, messages.ERROR, 'Product could not be created') 

당신이 더 개선하고 U, O 및 P의리스트를 반복하기보다는 코드에게 내가했던 방법을 반복하여 더 많은 접촉을, 그러나 이것은 당신에게 일반적인 아이디어를 제공해야 할 수 있습니다.

예외로서 : 기능적 프로그래밍은 순수 함수 프로그래밍이 예외 발생을 금지하기 때문에 이에 대한 통찰력을 제공합니다. 그러한 언어는 Maybe 모나드 (이름은 다를 수 있음)를 기본적으로 가지며, 이는 객체 자체 또는 None의 두 가지 값을 갖는 래퍼 클래스이며 foo 매개 변수를 취하는 메서드 get_or_else을 가지며 존재하는 경우, 또는 null 인 경우 foo. 파이썬에서는 이것을 쉽게 구현할 수 있습니다.하지만 나는 그것이 unpythonic으로 간주됩니다.컨텍스트 매니저 내부에서 수행 어떤 변화가 어떤 발생한 경우 자동으로 롤백 할 것이다 이런 식으로

try: 
    with transaction.atomic(): 
     create_your_objects() 
except IntegrityError: 
    handle_exception() 

:

+0

답장을 보내 주셔서 감사합니다. 그러나이 대답으로 문제가 해결되지는 않습니다. 예를 들어 주문 생성 라인이 실패한 경우 새로 만든 사용자 개체도 삭제되도록하는 코드가 예제에 없습니다. – Sam

+0

@Sam은 수정하기 쉽습니다. 제품은 오직 주문이 있었기 때문에 주문이 있었고 사용자가있는 경우에만 주문이 생성되었습니다. 각 if 검사에서 모든 종속 객체를 삭제합니다. 다른 옵션은 일반 예외를 제외하고, 예외 예외가 'save'와 생성자에 의해 발생되므로 특정 예외를 확인할 수 있습니다. – ubadub

+0

@badub 생각에 감사드립니다! 위의 응답 (re : transaction.atomic)은 승인 된 응답으로 유지되지만 대체 솔루션과 함께 작동 할 수 있습니다. – Sam

관련 문제