AssertionError : 뷰 함수 매핑이 기존 끝점 함수를 덮어 씁니다 : main


86

이 같은 URL 규칙이 두 개 있으면 기존 엔드 포인트 기능을 덮어 쓸 수없는 이유를 아는 사람이 있습니까?

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('main'),
                 methods=["GET"])

역 추적:

Traceback (most recent call last): 
  File "demo.py", line 20, in <module> methods=["GET"]) 
  File ".../python2.6/site-packages/flask‌​/app.py", 
    line 62, in wrapper_func return f(self, *args, **kwargs) 
  File ".../python2.6/site-packages/flask‌​/app.py", 
    line 984, in add_url_rule 'existing endpoint function: %s' % endpoint)  
AssertionError: View function mapping is overwriting an existing endpoint 
    function: main

어떻게 할 수 있는지, 왜 할 수 있는지 묻고 있습니까?
Michael Davis

5
작동하지 않는 이유 나는 튜토리얼을 따르고 있습니다
Kimmy

1
누군가 Flask에 고유 한 뷰 이름의 경계가있는 이유를 알고 싶다면 비슷한 질문에 대한 제 답변을 참조하십시오. stackoverflow.com/a/47558985/4440675 이 답변은 각 방법에 대해 고유 한 이름을 갖는 논리가 어떤 논리에 적용되는지 설명합니다.
Amit Tripathi

답변:


67

보기 이름은 동일한보기 방법을 가리키는 경우에도 고유해야합니다.

app.add_url_rule('/',
                 view_func=Main.as_view('main'),
                 methods = ['GET'])

app.add_url_rule('/<page>/',
                 view_func=Main.as_view('page'),
                 methods = ['GET'])

즉, .as_view($VIEW_NAME)메서드 호출 의 $ VIEW_NAME 은 고유 한 문자열 이름으로 전달되어야합니다.
Devy

112

이 같은 문제는 모듈에 API 함수가 두 개 이상 있고 각 함수를 2 개의 데코레이터로 래핑하려고 할 때 나에게 발생했습니다.

  1. @ app.route ()
  2. 내 맞춤 @exception_handler 데코레이터

이 두 데코레이터로 둘 이상의 함수를 래핑하려고 시도했기 때문에 이와 동일한 예외가 발생했습니다.

@app.route("/path1")
@exception_handler
def func1():
    pass

@app.route("/path2")
@exception_handler
def func2():
    pass

특히 이름 wrapper로 몇 가지 함수를 등록하려고했기 때문에 발생합니다 .

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code})
        return Response(r, status=error_code, mimetype='application/json')
  return wrapper

함수의 이름을 변경하면 문제가 해결되었습니다 ( wrapper .__ name__ = func .__ name__ ).

def exception_handler(func):
  def wrapper(*args, **kwargs):
    try:
        return func(*args, **kwargs)
    except Exception as e:
        error_code = getattr(e, "code", 500)
        logger.exception("Service exception: %s", e)
        r = dict_to_json({"message": e.message, "matches": e.message, "error_code": error_code})
        return Response(r, status=error_code, mimetype='application/json')
  # Renaming the function name:
  wrapper.__name__ = func.__name__
  return wrapper

그런 다음 둘 이상의 엔드 포인트를 장식하는 것이 효과가있었습니다.


28
functools.wraps함수 이름 바꾸기를 수행하는 데 사용할 수도 있습니다 .
ryannjohnson

4
내가 사용했다 wrapper.__name__대신 wrapper.func_name. 아마도 이것은 python2와 python3의 차이점입니까?
Resonance

2
그것은 데코레이터를 사용하는 플라스크 편안한 API의 문제였습니다. wrapper.__name__ = func.__name__래퍼를 호출하기 전에 문제가 해결되었습니다.
Tom Wojcik 2018

29

@ app.route를 사용하는 사용자 endpoint의 경우 Roei Bahumi가 언급 한 __name__것과 같은 값을 변경하는 것보다 키 인수를 사용하는 것이 좋습니다 . 그의 예를 들면 다음과 같습니다.

@app.route("/path1", endpoint='func1')
@exception_handler
def func1():
    pass

@app.route("/path2", endpoint='func2')
@exception_handler
def func2():
    pass

9

Flask를 사용하려면 단일 '보기 기능'을 '엔드 포인트'와 연결해야합니다. Main.as_view('main')두 개의 다른 함수를 만드는 두 번 호출 합니다 (정확히 동일한 기능이지만 메모리 서명이 다릅니다). 짧은 이야기, 당신은 간단히

main_view_func = Main.as_view('main')

app.add_url_rule('/',
             view_func=main_view_func,
             methods=["GET"])

app.add_url_rule('/<page>/',
             view_func=main_view_func,
             methods=["GET"])


4

이것은 다른 경로에 동일한 함수 이름이있는 경우에도 발생할 수 있습니다.


2

고유 한 엔드 포인트 이름이 있다고 생각하지만 여전히이 오류가 발생하면 문제 가있는 것입니다 . 저도 마찬가지였습니다.

이 문제는 플라스크 0.10에서 발생하며 동일한 버전을 사용하는 경우 다음을 수행하여 제거하십시오.

sudo pip uninstall flask
sudo pip install flask=0.9

1

이 예외가 발생하도록하는 Flask 문제 # 570 최근 (flask 0.10)에 대한 수정 사항이 있습니다.

참조 https://github.com/mitsuhiko/flask/issues/796를

따라서 flask / app.py로 이동하여 948..951 줄 4 개를 주석 처리하면 문제가 새 버전에서 완전히 다시 해결 될 때까지 도움이 될 수 있습니다.

그 변화의 차이점은 여기에 있습니다 : http://github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1


3
Re : "새 버전에서 문제가 완전히 해결 될 때까지": 해결할 "문제"가 없습니다. 문제 논의에서 알 수 있듯이 질문에있는 코드의 경우 예외가 발생하는 것이 예상되는 결과입니다. 수락 된 답변에 설명 된대로 엔드 포인트가 충돌합니다. 이것은 Flask 자체가 아닌 Flask 사용자 코드의 오류입니다.
Mark Hildreth


0

플라스크 0.9를 대신 사용하십시오. sudo pip uninstall flask

sudo pip install flask==0.9

0

@wraps(f)래퍼 함수 위에 추가하면 내 문제가 해결되었습니다.

def list_ownership(f):
    @wraps(f)
    def decorator(*args,**kwargs):
        return f(args,kwargs)
    return decorator
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.