python - 'NoneType' 对象在检索 POST 请求数据时没有属性 'model' 错误
问题描述
我得到 AttributeError 'NoneType' 对象没有属性 'model'
首先,让我解释一下我有两种形式。用户遇到的第一个表单是 InitialSearchForm。它需要一个日期输入、一个选定对象(旅行实例)和一个整数(乘客人数)。InitialSearchForm 中的 POST 请求数据被发送到 TripSelection 视图。此数据用于查询数据库并检索查询集,该查询集将用作我的第二种形式 - DateChoiceForm - 在 HttpResponse 中呈现的选择集。
下面的代码适用于views.py中的 TripSelection 视图。在初始化 DateChoiceForm 时,我将查询集作为参数“trips”传递:
class TripSelection(View):
""" A view to show results of search """
template = "bookings/trips_available.html"
def post(self, request):
"""
Takes the POST data from the InitialSearchForm and uses it to
initialise the DateChoiceForm before passing to the template
"""
form = InitialSearchForm(request.POST)
if form.is_valid():
destination_choice = request.POST.get("destination")
searched_date = request.POST.get("request_date")
passenger_total = int(request.POST.get("passengers"))
# Find trips with enough seats for requested no. of passengers
available_trips = Trip.objects.filter(
destination=destination_choice
).filter(seats_available__gte=passenger_total)
# Refine to trips with dates closest to searched_date
# limit to 3 results
gte_dates = available_trips.filter(
date__gte=searched_date
).order_by("date")[
:3
] # Returns trips that either match or are post- searched_date
lt_dates = available_trips.filter(date__lt=searched_date).order_by(
"-date"
)[
:3
] # Returns trips that are pre- searched_date
# Merge both queries
trips = gte_dates | lt_dates
naive_searched_date = datetime.strptime(searched_date, "%Y-%m-%d")
# Find trip closest to searched_date and make timezone naive
if gte_dates:
date_gte = gte_dates[0]
naive_closest_gte = self.timezone_naive(date_gte)
if lt_dates:
date_lt = lt_dates[0]
naive_closest_lt = self.timezone_naive(date_lt)
if (
naive_closest_gte - naive_searched_date
> naive_searched_date - naive_closest_lt
):
default_selected = date_lt
else:
default_selected = date_gte
else:
default_selected = date_gte
elif lt_dates:
date_lt = lt_dates[0]
naive_closest_lt = self.timezone_naive(date_lt)
default_selected = date_lt
else:
messages.error(
request,
"Sorry, there are no dates currently available for the"
"selected destination.",
)
form = DateChoiceForm(
trips=trips,
initial={
"trip_date": default_selected,
"num_passengers": passenger_total,
},
)
return render(request, self.template, {"form": form})
def timezone_naive(self, query_object):
""" Turns date attributes to a time-zone naive date """
date_attr = query_object.date
date_string = date_attr.strftime("%Y-%m-%d")
date_obj_naive = datetime.strptime(date_string, "%Y-%m-%d")
return date_obj_naive
在forms.py 中,我在表单的 __init__ 方法中为字段“trip”设置了查询集:
class DateChoiceForm(forms.Form):
num_passengers = forms.IntegerField(widget=forms.HiddenInput())
trip = forms.ModelChoiceField(
queryset=None,
widget=forms.RadioSelect()
)
def __init__(self, *args, **kwargs):
trips = kwargs.pop('trips', None)
super(DateChoiceForm, self).__init__(*args, **kwargs)
self.fields['trip'].queryset = trips
表单在模板中按预期呈现,但是当我做出选择并单击表单上的“提交”时,我得到了 AttributeError。这是在处理 DateChoiceForm 的 POST 数据的视图中引起的,特别是在以下行form = DateChoiceForm(request.POST)
:
def trip_confirmation(request):
if request.method == "POST":
form = DateChoiceForm(request.POST)
if form.is_valid():
passengers = request.POST.get("num_passengers")
trip_choice = request.POST.get("trip")
print(trip_choice)
else:
print("Hello")
template = "bookings/confirm/trip.html"
context = {
"passengers": passengers,
"trip_choice": trip_choice
}
return render(request, template, context)
print("Error!").
如果我理解正确,这是因为从视图传递了查询集并在 __init__ 方法中设置了查询集,现在每次我调用 DateChoiceForm 时,它都希望发送一个参数来初始化表单。由于这次我没有传递任何参数,所以它到达这一行:trips = kwargs.pop('trips', None)
并采用 None 的后备值。
我不知道如何为这个表单字段设置查询集,因为它不是一个简单的静态过滤器,我可以在 forms.py 中完成。还有另一种方法吗?我目前唯一的解决方法是将第一个表单的发布请求数据传递给会话存储,在视图中检索它并创建相同的查询集作为参数传递给 DateChoiceForm(request.POST)
解决方案
You can't use the except clause like that except (ValueError, TypeError, self.queryset.model.DoesNotExist)
. Use the actual model DoesNotExist instead:
except (ValueError, TypeError, <modelname_here>.DoesNotExist)
.
Also, you can't set the queryset=None
. That's not possible. You must use the <model>.objects.none()
queryset instead.
If you want dynamic model selection for your view I recommend using class-based views instead. The inheritance makes it way easier to handle multiple model types.
Edit: after reading your question again I noticed that trip_dates = kwargs.pop('trips', None)
actually retrieves 'trips'
and not 'trip'
is this intentional? Given your post variables trips
will be equal to None
.
Second: You don't actually set a queryset. self.fields['trip'].queryset = trip_dates
will be either None
or list of strings but never an actual queryset. So regardless of whether setting the queryset for the ModelChoiceField
in the __init__
it's never a queryset.
推荐阅读
- generics - 将泛型从 Java 转换为 Kotlin
- angularjs - AngularJS服务功能在while循环完成后没有返回完整的承诺
- svelte - 如何像 Vue 一样在 Svelte 中制作无标签插槽模板
- vue.js - 如何向 v-data-table 添加点击事件?
- c# - 旋转 UILabel 的拉伸宽度
- python - 根据 MultiIndex DataFrame 中的第一级列删除重复项
- buildkite - 如何在 buildkite 中为存储库/管道级别添加访问控制?
- java - 错误:SqlExceptionHelper:HOUR_OF_DAY:2 -> 3
- ios - Xcode 11 GM Seed 2 在构建工作区/项目时冻结
- ios - 如何激活包月试订阅(自动续费)?