локальная переменная ‘sql’, на которую ссылаются перед назначением

#python #sql #django #indentation

#python #sql #django #отступ

Вопрос:

Привет, я пытаюсь написать функцию, используя if / elif, у меня возникли проблемы при попытке выполнить последнюю функцию курсора после elif. Я думаю, что мой отступ неверен, и я пытался найти, где ошибка, уже более суток :

 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)
  

Ошибка:

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

У elif params["type"] == 'product': и elif params["type"] == 'order_rate_by_district': есть своя функция для выполнения, я хочу, чтобы другие условия переходили к последней функции курсора в конце кода.

Комментарии:

1. первый elif должен быть if? если ваш код не работает ни с одним из elifs, вы никогда не определяете sql, и в шестой последней строке вашего кода вы вызываете sql

2. должен ли я добавить «pass» к последнему elif? значит, другие условия могут использовать sql?

3. если params["type"] == 'product' вы получите сообщение об ошибке, потому что sql не определено. Это желаемое поведение? Что вы хотите, чтобы ваша функция делала в этом случае? она не может выполнять никаких sql действий с курсором, вы хотите, чтобы функция завершила работу и вернула что-то?

4. Вы можете добавить else инструкцию в конце. Все еще возможно, что при использовании только последовательности if и elif s sql значение в конечном итоге будет неопределенным.

Ответ №1:

Как только вы запустите программу, это то, что, как я предполагаю, произойдет (Читать #)

 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 перед первым оператором if make и пустой переменной sql. (или любое другое значение по умолчанию, которое вы предпочитаете)

Комментарии:

1. это опция, но это api, поэтому я не хочу, чтобы он выводил какие-либо данные, если в них нет параметров

2. Я думаю, что вы хотите заменить все 2-е соединение.cursro() … на оператор else: «else: data=[]», который не вернет никаких данных, если все предыдущие утверждения ложны. Это то, что вы имеете в виду?

3. второй захват sql должен выполняться для других условий, кроме product и order_rate_by_district

4. Какое условие вы хотите выполнить? Это в переменной params?

5. да, все переменные params будут использовать назначенный sql для выполнения 2-го захвата sql, который является последними 6 строками кода (за исключением тех 2 условий, о которых я говорю)

Ответ №2:

Проблема

local variable 'sql' referenced before assignment означает, что sql она еще не была назначена, когда вы пытаетесь использовать ее с cursor.execute(sql) .

Это тот случай, когда params["type"] == 'product' или когда ни одна из ваших проверок if / elif не верна. Например, if params["type"] is foo , sql не будет присвоен.

Решение

Присваивайте значение sql, когда params["type"] == 'product'

Используйте else инструкцию, чтобы либо присвоить значение sql, либо выдать ошибку, когда params["type"] нет ни одной из ожидаемых строк.

Комментарии:

1. дело в том, что я включаю параметры [«type»] == ‘product’ в def с другим условием, но не хочу ли я использовать sql для этих параметров

Ответ №3:

Вам следует изменить свою последовательность if, чтобы игнорировать случаи, когда sql она пуста. В противном случае вы могли бы просто добавить sql = 'some default value' поверх нее, но это уже трудно читать.

Ответ №4:

вы можете присвоить sql значение по умолчанию в начале:

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

Ответ №5:

После того, как я изменил

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

Для

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

это сработало, потому что get_product_report является его собственной функцией, поэтому не было никакого результата возврата к условию param = ‘product’, поэтому оно неверно в строке параметров продукта (return None)

Комментарии:

1. Это все равно приведет к сбою, если params["type"] нет ни одного из вариантов. Также произойдет сбой, если не будет параметра GET «type». Итак, если ваш URL-адрес «/ api / report», то простой вызов «/api /report» вызовет исключение, а вызов «/ api / report?type=blabla» также вызовет исключение. Не очень хороший дизайн.