Как исправить UnboundLocalError в представлениях Django - PullRequest
0 голосов
/ 30 апреля 2019

Я действительно долго боролся с этим кодом, и я не могу понять, что с ним не так. Я пытался реализовать 2 модели формы в одном представлении здесь. Таким образом, ShoesForm отображается только тогда, когда пользователь хочет создать или отредактировать обувной продукт. (Я скрываю форму, используя JavaScript). Поля в модели обуви все blank=True, поэтому field.cleaned_data всегда подтверждается.

Однако всякий раз, когда я пытаюсь отредактировать существующий предмет, не относящийся к обуви, я получаю сообщение об ошибке UnboundLocalError: local variable 'pid' referenced before assignment. Я знаю, это означает, что есть случай, когда pid не назначен, но я не вижу его. Какие-либо предложения?

views.py

def create_or_update_inventory(request, product_id=None):
    """Combined form view for BaseInventory and Shoes model

    The two available forms in the context are:
        1. product_form: linked to BaseInventory model
        2. shoes_form: linked to Shoes model

    If the form is submitted, it will first create the product for the BaseInventory model.
    If any of the forms inside the shoes_form is filled, it will take the product and link
    it to the inventory field in the Shoes model and then it will save the shoes_form.

    This vies uses the inventory_list/product_detail.html as its template.
    """
    context = {}

    # if form is posted, this happens
    # TODO: fix pid not found when editing non-shoe item
    if request.method == 'POST':

        try:
            instance = get_object_or_404(Product, product_id=product_id)
            instance2 = get_object_or_404(Shoes, inventory__product_id=product_id)

            product_form = ProductForm(request.POST, instance=instance)
            shoes_form = ShoesForm(request.POST, instance=instance2)
            pid = instance.product_id

        except:
            product_form = ProductForm(request.POST)
            shoes_form = ShoesForm(request.POST)


        if product_form.is_valid() and shoes_form.is_valid():
            product_form.save()
            pid = product_form.instance.product_id
            product = Product.objects.get(product_id=pid)

            # if the shoes_form is filled, save to Shoes model, else ignore this
            if shoes_form.cleaned_data['collection'] or \
                    shoes_form.cleaned_data['material'] or \
                    shoes_form.cleaned_data['ground_type']:
                shoes_form.cleaned_data['inventory'] = product
                shoes_form.instance.inventory = product
                shoes_form.save()

        # redirect to view all fields
        return HttpResponseRedirect(reverse('inventory_list:product-detail', kwargs={'product_id': pid}))


    else:
        if product_id:
            # if the user wants to update product, fill in with preexisting values
            item = Product.objects.get(product_id=product_id)
            pid = item.product_id
            product_form = ProductForm(
                initial={
                    'product_id': item.product_id,
                    'name': item.name,
                    'color_primary': item.color_primary,
                    'color_secondary': item.color_secondary,
                    'category': item.category,
                    'description': item.description,
                    'gender': item.gender,
                    'active': item.active,
                }
            )
            if item.category == Product.SHOES:
                shoes_form = ShoesForm(
                    initial={
                        'collection': item.shoes.collection,
                        'material': item.shoes.material,
                        'ground_type': item.shoes.ground_type,
                    }
                )
            else:
                shoes_form = ShoesForm()

        else:
            # if the user wants to create product, create empty form
            product_form = ProductForm()
            shoes_form = ShoesForm()

    # the list of contexts for the front end
    context.update({
        'product_form': product_form,
        'shoes_form': shoes_form,
        'colors': Color.objects.all(),
    })

    return render(request, 'inventory_list/product_detail.html', context)

РЕДАКТИРОВАТЬ: журнал ошибок

Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/django/contrib/staticfiles/handlers.py", line 66, in __call__
    return self.application(environ, start_response)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/wsgi.py", line 146, in __call__
    response = self.get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 81, in get_response
    response = self._middleware_chain(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 37, in inner
    response = response_for_exception(request, exc)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 87, in response_for_exception
    response = handle_uncaught_exception(request, get_resolver(get_urlconf()), sys.exc_info())
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 122, in handle_uncaught_exception
    return debug.technical_500_response(request, *exc_info)
  File "/usr/local/lib/python3.6/site-packages/django_extensions/management/technical_response.py", line 37, in null_technical_500_response
    six.reraise(exc_type, exc_value, tb)
  File "/usr/local/lib/python3.6/site-packages/six.py", line 692, in reraise
    raise value.with_traceback(tb)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
    response = get_response(request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/usr/local/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/usr/local/lib/python3.6/contextlib.py", line 52, in inner
    return func(*args, **kwds)
  File "/app/inventory_list/views.py", line 133, in create_or_update_inventory
    return HttpResponseRedirect(reverse('inventory_list:product-detail', kwargs={'product_id': pid}))
UnboundLocalError: local variable 'pid' referenced before assignment

Ответы [ 2 ]

0 голосов
/ 30 апреля 2019

Самое первое try except вызывает исключение 404.Получив его в блоке except, вы не определяете никакой pid, поэтому, когда элемент управления переходит к вашему reverse, он выбрасывает UnboundLocalError для pid.

также обновляет некоторую другую часть, так как ячувствовал, что код был излишним.

попробуйте это (я написал это в спешке, пожалуйста, не возражайте, если есть какие-либо грамматические ошибки, но вы поймете, что делать) Я обновлю ответ случшее объяснение, если это работает.

def create_or_update_inventory(request, product_id=None):
"""Combined form view for BaseInventory and Shoes model

The two available forms in the context are:
    1. product_form: linked to BaseInventory model
    2. shoes_form: linked to Shoes model

If the form is submitted, it will first create the product for the BaseInventory model.
If any of the forms inside the shoes_form is filled, it will take the product and link
it to the inventory field in the Shoes model and then it will save the shoes_form.

This vies uses the inventory_list/product_detail.html as its template.
"""
context = {}

# if form is posted, this happens
# TODO: fix pid not found when editing non-shoe item
if request.method == 'POST':

    try:
        product_instance = Product.objects.get(product_id=product_id)
        product_form = ProductForm(request.POST, instance=product_instance)
    except Product.DoesNotExist:
        product_form = ProductForm(request.POST)

    try:
        shoes_instance = Shoes.objects.get(inventory__product_id=product_id)
        shoes_form = ShoesForm(request.POST, instance=shoes_instance)
    except Shoes.DoesNotExist:
        shoes_form = ShoesForm(request.POST)

    if product_form.is_valid() and shoes_form.is_valid():
        product_form.save()
        product = Product.objects.get(product_id=product_id)

        # if the shoes_form is filled, save to Shoes model, else ignore this
        if shoes_form.cleaned_data['collection'] or \
                shoes_form.cleaned_data['material'] or \
                shoes_form.cleaned_data['ground_type']:
            shoes_form.cleaned_data['inventory'] = product
            shoes_form.instance.inventory = product
            shoes_form.save()

    if product_id:
        # redirect to view all fields
        return HttpResponseRedirect(reverse('inventory_list:product-detail', kwargs={'product_id': product_id}))

elif product_id:
        # if the user wants to update product, fill in with preexisting values
        item = Product.objects.get(product_id=product_id)
        pid = item.product_id
        product_form = ProductForm(
            initial={
                'product_id': item.product_id,
                'name': item.name,
                'color_primary': item.color_primary,
                'color_secondary': item.color_secondary,
                'category': item.category,
                'description': item.description,
                'gender': item.gender,
                'active': item.active,
            }
        )
        if item.category == Product.SHOES:
            shoes_form = ShoesForm(
                initial={
                    'collection': item.shoes.collection,
                    'material': item.shoes.material,
                    'ground_type': item.shoes.ground_type,
                }
            )
        else:
            shoes_form = ShoesForm()

else:
    # if the user wants to create product, create empty form
    product_form = ProductForm()
    shoes_form = ShoesForm()

# the list of contexts for the front end
context.update({
    'product_form': product_form,
    'shoes_form': shoes_form,
    'colors': Color.objects.all(),
})

return render(request, 'inventory_list/product_detail.html', context)

Дайте мне знать, что вы думаете

0 голосов
/ 30 апреля 2019

Сначала вы должны понять, как работает обработка исключений.Ясно.В приведенном выше коде, когда в вашем блоке try происходит ошибка, блок исключений вступает в действие, делая переменную pid неопределенной.И после этого снова, если ваши данные не пройдут тест if product_form.is_valid() and shoes_form.is_valid():, у вас останется неопределенное значение pid var, которое вы используете в своем ответе.

Итак, если вы просто хотите создать объектесли он не существует, проверьте это get_or_create ()

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...