AssertionError: Görünüm işlevi eşlemesi, mevcut bir uç nokta işlevinin üzerine yazıyor: ana


86

Bunun gibi iki url kuralım varsa neden mevcut bir uç nokta işlevinin üzerine yazamayacağımı bilen var mı?

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"])

Geri iz:

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

Nasıl yapabileceğinizi veya neden yapabileceğinizi mi soruyorsunuz?
Michael Davis

5
neden çalışmıyor Bir öğreticiyi takip ediyorum
Kimmy

1
Birisi Flask'ın neden bu benzersiz görünüm adlarına sahip olduğunu merak ederse, benzer bir soruya verdiğim yanıtı görün: stackoverflow.com/a/47558985/4440675 Bu yanıt, her yöntem için benzersiz bir adın arkasında mantığın ne olduğunu açıklar.
Amit Tripathi

Yanıtlar:


67

Görünüm adlarınızın, aynı görünüm yöntemine işaret etseler bile benzersiz olması gerekir.

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'])

Başka bir deyişle, .as_view($VIEW_NAME)yöntem çağrısındaki $ VIEW_NAME benzersiz bir dize adı olarak aktarılmalıdır.
Devy

112

Modülde birden fazla API işlevim olduğunda ve her işlevi 2 dekoratörle sarmaya çalıştığımda aynı sorun başıma geldi:

  1. @ app.route ()
  2. Benim özel @exception_handler dekoratörüm

Aynı istisnayı aldım çünkü bu iki dekoratörle birden fazla işlevi sarmaya çalıştım:

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

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

Özellikle, ad sarmalayıcıyla birkaç işlevi kaydetmeye çalışmaktan kaynaklanır :

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

Fonksiyonun adını değiştirmek sorunu benim için çözdü ( 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

Sonra birden fazla uç noktayı dekore etmek işe yaradı.


28
functools.wrapsİşlevin yeniden adlandırılmasını sağlamak için de kullanabilirsiniz .
ryannjohnson

4
Bunun wrapper.__name__yerine kullanmak zorunda kaldım wrapper.func_name. Belki de bu python2 ve python3 arasındaki farktır?
Rezonans

2
Dekoratörleri kullanan flask dinlendirici API'mdeki problem buydu. wrapper.__name__ = func.__name__sarmalayıcıyı aramadan önce sorunu çözdü.
Tom Wojcik

29

@ App.route kullanan kullanıcılar için Roei Bahumi'nin belirttiği gibi endpointdeğeri değiştirmek yerine anahtar argümanını kullanmak daha iyidir . Onun örneğini almak:__name__

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

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

9

Flask, tek bir 'görünüm işlevini' bir 'uç nokta' ile ilişkilendirmenizi gerektirir. Main.as_view('main')İki farklı işlevi (tam olarak aynı işlevsellik, ancak bellek imzasında farklı) oluşturan iki kez arama yapıyorsunuz . Kısa hikaye, sadece yapmalısın

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

Bu, farklı rotalarda aynı işlev adlarına sahip olduğunuzda da olabilir.


2

Benzersiz uç nokta adlarınız olduğunu düşünüyorsanız ve yine de bu hata veriliyorsa, muhtemelen sorunla karşı karşıyasınızdır . Aynı benim için de geçerliydi.

Bu sorun, aynı sürüme sahipseniz, bundan kurtulmak için aşağıdakileri yapın: flask 0.10 ile ilgilidir:

sudo pip uninstall flask
sudo pip install flask=0.9

1

Son zamanlarda tanıtılan Flask sorunu # 570 için (şişe 0.10) bu istisnanın ortaya çıkmasına neden olan bir düzeltme var.

Bkz. Https://github.com/mitsuhiko/flask/issues/796

Dolayısıyla, flask / app.py adresine gidip 4 satır 948..951'e yorum yaparsanız, sorun yeni bir sürümde tamamen yeniden ele alınana kadar bu yardımcı olabilir.

Bu değişikliğin farkı burada: http://github.com/mitsuhiko/flask/commit/661ee54bc2bc1ea0763ac9c226f8e14bb0beb5b1


3
Ynt: "sorun yeni bir sürümde tamamen çözülene kadar": Çözülecek "sorun" yoktur. Konu tartışmasının gösterdiği gibi, sorudaki kod durumunda bir istisnanın ortaya çıkması beklenen sonuçtur. Kabul edilen cevapta açıklandığı gibi, uç noktalar çelişkili. Bu, Flask'ın kendisinde DEĞİL, Flask kullanıcısının kodundaki bir hatadır.
Mark Hildreth


0

flask 0.9'u kullanın yerine aşağıdaki komutları kullanın sudo pip uninstall flask

sudo pip install flask==0.9

0

@wraps(f)Sarmalayıcı işlevinin üstüne eklemek sorunumu çözdü.

def list_ownership(f):
    @wraps(f)
    def decorator(*args,**kwargs):
        return f(args,kwargs)
    return decorator
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.