一段时间以来,我一直在努力处理这段代码,但似乎看不出它有什么问题。我一直在尝试在一种视图中实现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
答案 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)
让我知道你的想法