0
votes

variable locale 'sql' référencée avant l'affectation

Salut, j'essaie d'écrire une fonction en utilisant if / elif, j'ai des problèmes en essayant d'exécuter la fonction de curseur finale après elif. Je pense que mon retrait est erroné et j'essaie de trouver où se situe l'erreur depuis plus d'un jour maintenant:

cursor.execute(sql)  UnboundLocalError: 
    local variable 'sql' referenced before assignment

L'erreur:

def api_report(request):
    params = request.GET
    if params["type"] == 'revenue':
        sql = get_revenue_query(params)

    elif params["type"] == 'order_count':
        sql = get_order_created_count(params)

    elif params["type"] == 'product_count':
        sql = get_product_count(params)

    elif params["type"] == 'order_card_created_count':
        sql = get_order_card_created_count(params)

    elif params["type"] == 'product_count':
        sql = get_product_count(params)

    elif params["type"] == 'card':
        sql = get_card_query(params)

    elif params["type"] == 'order_not_card_created_count':
        sql = get_order_not_card_created_count(params)

    elif params["type"] == 'product':
        get_product_report(params)

    elif params["type"] == 'order_rate_by_district':
        sql = get_order_rate_by_district(params)

        with connection.cursor() as cursor:
            cursor.execute(sql)
            rows = cursor.fetchall()
            data = []
            for row in rows:
                data.append(OrderRateDataEntry(row[0], row[1], row[2]))
        serializer = OrderRateDataEntrySerializer(data, many=True)
        return JsonResponse(serializer.data, safe=False)

    with connection.cursor() as cursor:
        cursor.execute(sql)
        rows = cursor.fetchall()
        data = []
        for row in rows:
            data.append(TimeSeriesDataEntry(row[0], row[1]))
    serializer = TimeSeriesDataEntrySerializer(data, many=True)
    return JsonResponse(serializer.data, safe=False)

Les elif params ["type"] == 'product': et elif params ["type"] == 'order_rate_by_district': ont leur propre fonction à exécuter, je veulent que les autres conditions sautent à la dernière fonction de curseur à la fin du code.


4 commentaires

le premier elif devrait être si? si votre code ne rencontre aucun des elifs, vous ne définissez jamais sql et à la sixième dernière ligne de votre code, vous appelez sql


dois-je ajouter "passer" au dernier elif? donc les autres conditions peuvent utiliser le sql?


si params ["type"] == 'produit' vous obtiendrez l'erreur car sql n'est pas défini. Est-ce le comportement souhaité? Que voulez-vous que votre fonction fasse dans ce cas? il ne peut pas faire d'action de curseur sql , voulez-vous que la fonction quitte et renvoie quelque chose?


Vous pouvez ajouter une instruction else à la fin. Avec juste une séquence de if et elif s, il est toujours possible que sql finisse par être indéfini.


5 Réponses :


0
votes

< gagnantIndice

variable locale 'sql' référencé avant affectation signifie que sql n'a pas encore été attribué lorsque vous essayez de l'utiliser avec cursor.execute ( sql) .

C'est le cas lorsque params ["type"] == 'product' ou lorsqu'aucune de vos vérifications if / elif n'est vraie. Par exemple, si params ["type"] vaut toto , sql ne sera pas attribué.

<½Solution

Attribuez une valeur à sql lorsque params ["type"] == 'product'

Utilisez une instruction else pour attribuer une valeur à sql ou générer une erreur lorsque params ["type"] ne correspond à aucune de vos chaînes attendues.


1 commentaires

le truc est que i params ["type"] == 'product' include dans la def avec une autre condition mais je ne veux pas utiliser sql pour ces paramètres



1
votes

Une fois que vous exécutez le programme, c'est ce que je suppose qui se produit (Lire #)

def api_report(request):
    params = request.GET
    if params["type"] == 'revenue': # False so sql is not made, move to next elif
        sql = get_revenue_query(params)

    elif params["type"] == 'order_count': # False so sql is not made, move to next elif
        sql = get_order_created_count(params)

    elif params["type"] == 'product_count': # False so sql is not made, move to next elif
        sql = get_product_count(params)

    elif params["type"] == 'order_card_created_count': # False so sql is not made, move to next elif
        sql = get_order_card_created_count(params)

    elif params["type"] == 'product_count': # False so sql is not made, move to next elif
        sql = get_product_count(params)

    elif params["type"] == 'card': # False so sql is not made, move to next elif
        sql = get_card_query(params)

    elif params["type"] == 'order_not_card_created_count': # False so sql is not made, move to next elif
        sql = get_order_not_card_created_count(params)

    elif params["type"] == 'product': # False so sql is not made, move to next elif
        get_product_report(request) # P.S There is also a chance that if this is run then sql variable will also not be made!

    elif params["type"] == 'order_rate_by_district':  # This is also false so code leaves.
        sql = get_order_rate_by_district(params)

        with connection.cursor() as cursor:
            cursor.execute(sql)
            rows = cursor.fetchall()
            data = []
            for row in rows:
                data.append(OrderRateDataEntry(row[0], row[1], row[2]))
        serializer = OrderRateDataEntrySerializer(data, many=True)
        return JsonResponse(serializer.data, safe=False)

        pass
    # When the code is here it still didn't made variable sql. Thus so will crashes when refere to variable sql as it wasn't yet created
    with connection.cursor() as cursor:
        cursor.execute(sql) # sql was never made here and thus doesn't exist. Code crashes here.
        rows = cursor.fetchall()
        data = []
        for row in rows:
            data.append(TimeSeriesDataEntry(row[0], row[1]))
    serializer = TimeSeriesDataEntrySerializer(data, many=True)
    return JsonResponse(serializer.data, safe=False)

Maby avant la première instruction if make et variable sql vide. (ou quelle que soit la valeur par défaut que vous préférez)


6 commentaires

c'est une option mais c'est une api donc je ne veux pas qu'elle produise des données s'il n'y a pas de passage de paramètres


Je pense que vous voulez remplacer la totalité du 2nd connection.cursro () ... par une instruction else: "else: data = []" qui ne renverra aucune donnée si toutes les déclarations précédentes sont fausses. C'est ce que tu veux dire?


la deuxième saisie SQL est à exécuter pour d'autres conditions sauf product et order_rate_by_district


Quelle est la condition que vous souhaitez exécuter? Est-ce dans la variable params?


oui toutes les variables params utiliseront le sql assigné pour exécuter le 2nd sql grab qui est les 6 dernières lignes du code (sauf pour ces 2 conditions dont je parle)


qu'est-ce qui est censé se passer si param ["type"] n'est dans aucun des elif? Que doit-il se passer alors?



0
votes

Vous devriez réorganiser votre séquence if pour ignorer les cas où sql est vide. Sinon, vous pouvez simplement ajouter sql = 'some default value' dessus, mais c'est déjà difficile à lire.


0 commentaires

0
votes

vous pouvez donner à sql une valeur par défaut au début:

def api_report(request):
    params = request.GET
    sql=''


0 commentaires

0
votes

Après avoir changé le

 elif params["type"] == 'product': 
      return get_product_report(params)

en

 elif params["type"] == 'product':
      get_product_report(request)

cela a fonctionné car le get_product_report est sa propre fonction donc il n'y a pas eu de retour result to param = condition 'product' donc il est faux de la ligne de param product (return None)


1 commentaires

Cela plantera toujours si params ["type"] ne fait pas partie des choix. Il plantera également s'il n'y a pas de paramètre GET "type". Donc, si votre URL est "/ api / report", le simple fait d'appeler "/ api / report" déclenchera une exception et l'appel de "/ api / report? Type = blabla" déclenchera également une exception. Pas un bon design.