如何在Django视图中修复UnboundLocalError

时间:2019-04-30 04:25:28

标签: django

一段时间以来,我一直在努力处理这段代码,但似乎看不出它有什么问题。我一直在尝试在一种视图中实现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 :(得分:0)

您必须首先了解异常处理的一般工作原理。很明显。在上面的代码中,当try块中发生错误时,except块将生效,从而使pid变量未定义。然后,如果您的数据没有通过if product_form.is_valid() and shoes_form.is_valid():测试,那么您将获得未定义的pid变量,该变量将用于响应中。

因此,如果您只是想创建一个不存在的对象,请检查get_or_create()

答案 1 :(得分:0)

第一个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)

让我知道你的想法