2

私のコードは昨日 (自動テストによって) 正常に実行されましたが、今日は壊れてしまいました。基本的に @api_view デコレータが壊れてメソッドの申請に失敗したような感じです。状況は次のとおりです。

「advance_orders」という名前のメソッドがあり、次のようにラップされています。

@api_view(http_method_names=['POST'], hack=True)
@permission_classes((IsAuthenticated,))
@check_wallet_token
@disallow_disabled_users
def advance_orders(request):
    # code that is irrelevant for this issue

注: hack=True は、最初にバグを発見した後、デバッグ目的で作成した小さな追加です。

メソッド@check_wallet_token@disallow_disabled_usersもここでは無関係であり、それらがバグの原因ではないことを 99.99% 確信しています (昨日、同様にラップされた他のメソッド内/上で正常に動作したため)。

関数への URL マッピングは次のとおりです。 re_path(r'^vendor/orders/advance/$', vendor.advance_orders, name='advance_order'),

今、あるテストで私は持っています:

client = RequestsClient()
# absolute_url == http://testserver/wallet/vendor/orders/advance/
# there are some helper methods which generate it...
# the headers are irrelevant honestly
r = client.post(absolute_url, headers=self.headers, data={"order_id": "asdf"})
print(r.text)
self.assertEqual(r.status_code, 400)
self.assertEqual(json.loads(r.text), {"display_message": "Missing order_id (int)."})

テストは失敗し、私が見つけた応答テキストを印刷すると: {"detail":"Method \"POST\" not allowed."}

これは意味がありません!私が露骨に間違ったことをしていない限り、そうではないと確信しています。

++++++++++++++++++++++++++++++++++++++++++++++++++++ +++++++++++++++++++++

ここで、さらに証拠を集めます。仮想環境にインストールされた DRF のソース コードにアクセスし、2 つのメソッドを変更して追加のデバッグ情報を出力します。

views.py では、次のように変更views.APIView.dispatch()します。

def dispatch(self, request, *args, **kwargs):
        """
        `.dispatch()` is pretty much the same as Django's regular dispatch,
        but with extra hooks for startup, finalize, and exception handling.
        """
        self.args = args
        self.kwargs = kwargs
        request = self.initialize_request(request, *args, **kwargs)
        self.request = request
        self.headers = self.default_response_headers  # deprecate?

        hack = False
        if request.META['PATH_INFO'] == '/wallet/vendor/orders/advance/':
            print("[HACK - views.py] Method identified as advance_order")
            hack = True

        try:
            self.initial(request, *args, **kwargs)

            # Get the appropriate handler method
            if request.method.lower() in self.http_method_names:
                handler = getattr(self, request.method.lower(),
                                  self.http_method_not_allowed)
            else:
                print("[HACK - views.py] list of http_method_names associated with the function: {}".format(self.http_method_names))
                handler = self.http_method_not_allowed

            response = handler(request, *args, **kwargs)

        except Exception as exc:
            response = self.handle_exception(exc)
# and so on as usual...

私が変更する他の方法は次のdecorators.api_view()とおりです。

def api_view(http_method_names=None, exclude_from_schema=False, hack=False):
    """
    Decorator that converts a function-based view into an APIView subclass.
    Takes a list of allowed methods for the view as an argument.
    """
    http_method_names = ['GET'] if (http_method_names is None) else http_method_names

    if hack:
        print("[HACK - decorators.py] Provided http_method_names: {}".format(http_method_names))
# and so on as usual...

./manage.py test Wallet.tests.test_api_vendors.API_VendorTestCase --failfast ここで、得られた結果を使用して印刷してテストを実行します。

[HACK - decorators.py] Provided http_method_names: ['POST']
System check identified no issues (0 silenced).
[HACK - views.py] Method identified as advance_order
[HACK - views.py] list of http_method_names associated with the function: ['get', 'options']
{"detail":"Method \"POST\" not allowed."}
F
======================================================================
FAIL: test_advance_order (Wallet.tests.test_api_vendors.API_VendorTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/mnt/CommonShare/Code/DVM/APOGEE/Wallet/tests/test_api_vendors.py", line 231, in test_advance_order
    self.assertEqual(r.status_code, 400)
AssertionError: 405 != 400

----------------------------------------------------------------------
Ran 1 test in 0.377s

FAILED (failures=1)
Destroying test database for alias 'default'...

これは、デコレーターが「POST」メソッドを許可したいことを認識したことを意味するため、完全に困惑したままですが、ビュー「advance_order」が実行されると、許可されたメソッドのリストに「POST」が含まれません。

だから私の質問は次のとおりです。間違いは私の側にありますか? もしそうなら、どのように?そうでなければ、そのような問題を解決するにはどうすればよいですか? ( __pycache__ ファイルの削除は機能しませんでした)。

PS 非常に冗長な質問をお詫びします。私の問題について明確にしたいだけです。

4

0 に答える 0