【发布时间】:2021-03-21 01:35:29
【问题描述】:
我正在尝试重构我的代码以继承 FormView 而不是 View。我正在使用的视图在 GET 请求中接收值。我在 get_context_data 方法中检索值并将它们传递给不同的函数,最终得到一组我可以在上下文中传递的变量。
简而言之:
为了举例,变量集包括变量 FOO 和 BAR。我需要通过在 kwargs 中传递变量 FOO 来初始化我的表单,并将表单字段的初始值设置为 BAR。我知道我应该使用 get_initial() 和 get_form_kwargs() 方法来做到这一点。我只是在纠结如何从 get_context_data 方法中获取 FOO 和 BAR。
我尝试将 FOO 和 BAR 添加到上下文字典中:
context = super().get_context_data(**kwargs)
context["FOO"] = foo
context["BAR"] = bar
return context
然后从其他方法调用它:
def get_initial(self):
""" Get initial value for the form field """
initial = super(NameOfView, self).get_initial()
context = self.get_context_data()
initial_value = context["BAR"]
initial.update({'name': inital_value})
return initial
get_form_kwargs 也是如此。但我得到一个 RecursionError:
调用 Python 对象时超出最大递归深度
任何帮助理解我如何实现这一点将不胜感激
更新:我的实际代码更像这样:*
class ConfirmTripView(FormView):
"""
Provides the user a set of choice options based on their search input in
the products.TripsView
"""
model = Booking
template_name = "bookings/trips_available.html"
form_class = DateChoiceForm
def __init__(self):
self.searched_date = None
self.passengers = None
self.destination_id = None
self.gte_dates = None
self.lt_dates = None
def convert_to_int(self, type_tuple):
""" Converts tuple value to integer """
type_int = int(''.join(type_tuple))
return type_int
def get_available_trips(self, destination, passengers):
""" Find trips with enough seats for searched no. of passengers """
available_trips = Trip.objects.filter(
destination=destination
).filter(seats_available__gte=passengers)
return available_trips
def get_trips_matched_or_post_date(self, date, destination, passengers):
"""
Returns trips that either match or are post- searched_date
Refine to trips with dates closest to searched_date
limit to 3 results
"""
available_trips = self.get_available_trips(destination, passengers)
gte_dates = available_trips.filter(date__gte=date)[:3]
return gte_dates
def get_trips_preceding_date(self, date, destination, passengers):
"""
Returns trips that are pre- searched_date
Refines to trips with dates closest to searched_date
limits to 3 results
"""
available_trips = self.get_available_trips(destination, passengers)
lt_dates = available_trips.filter(date__lt=date).order_by("-date")[:3]
return lt_dates
def make_timezone_naive(self, obj):
""" Turns date attribute to a time-zone naive date object """
date_attr = obj.date
date_string = date_attr.strftime("%Y-%m-%d")
datetime_naive = datetime.strptime(date_string, "%Y-%m-%d")
return datetime_naive
def get_trips_queryset(self, gte_dates, lt_dates):
""" Creates the queryset that will be used by the ModelChoiceField
in the DateChoiceForm """
# Merge both queries
trips = lt_dates | gte_dates
trips = trips.order_by('date')
return trips
def get_initial(self, **kwargs):
""" Takes values from get request and formulates variables
to be used in the form """
# Values from GET request
self.searched_date = self.request.GET.get('request_date')
self.passengers = self.request.GET.get('passengers')
self.destination_id = self.convert_to_int(
self.request.GET.get("destination")
)
# Return querysets for dates before/beyond searched_date respectively:
self.gte_dates = self.get_trips_matched_or_post_date(
self.searched_date,
self.destination_id,
self.passengers)
self.lt_dates = self.get_trips_preceding_date(
self.searched_date,
self.destination_id,
self.passengers)
naive_searched_date = datetime.strptime(self.searched_date, "%Y-%m-%d")
# Find the trip closest to the searched_date (for form initial value)
if self.gte_dates:
gte_date = self.gte_dates[0]
naive_gte_date = self.make_timezone_naive(gte_date)
if self.lt_dates:
lt_date = self.lt_dates[0]
naive_lt_date = self.make_timezone_naive(lt_date)
if (
naive_gte_date - naive_searched_date
> naive_searched_date - naive_lt_date
):
default_selected = lt_date
else:
default_selected = gte_date
else:
default_selected = gte_date
elif self.lt_dates:
lt_date = self.lt_dates[0]
default_selected = lt_date
else:
messages.error(
self.request,
"Sorry, there are no dates currently available for the"
"selected destination.",
)
# Get initial valuees for the form
initial = super(ConfirmTripView, self).get_initial()
initial.update({'trip': default_selected})
return initial
def get_form_kwargs(self, **kwargs):
""" Provides keyword arguemnt """
kwargs = super(ConfirmTripView, self).get_form_kwargs()
trips = self.get_trips_queryset(self.gte_dates, self.lt_dates)
kwargs.update({'trips': trips})
return kwargs
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
destination = Product.objects.filter(id=self.destination_id)
context["passengers"] = self.passengers
context["destination_obj"] = destination
return context
def form_valid(self, form):
"""
Takes the POST data from the DateChoiceForm and creates an
Intitial Booking in the database
"""
booking = form.save(commit=False)
booking.status = "RESERVED"
booking.save()
trip = form.cleaned_data['trip']
destination = trip.destination
booking_line_item = BookingLineItem(
booking=booking,
product=destination,
quantity=self.request.GET.get("passengers")
)
booking_line_item.save()
return redirect('create_passengers', booking.pk)
【问题讨论】: