我试图了解如何将 htmx 与 Django 基于类的视图结合使用。为了提供一些背景信息,这里反映了我想同时实现基于 django 类的视图和 htmx 的场景:
我有一个初始视图,它呈现主模板和初始上下文。作为初始上下文的一部分,我添加了一个日期表格。我想使用 htmx 将此表单中的数据发布到 APIView(我们称之为 APIView1)。
我希望 APIView1 摄取通过 htmx 发布到它的数据,在其上运行一个函数,然后将数据作为上下文返回,同时渲染利用该上下文的部分模板(我们称之为 PartialTemplate1)。因此,根据我的理解,我可以在 get() 函数中执行此操作;所以它可能看起来有点像这样:
views.py
Class InitialView(View):
template_name = “initial_template.html”
form_class = date_form
def get(self, request, *args, **kwargs):
…
date_form=self.form_class()
context = {
'date_form': date_form
}
return render(request, template_name, context)
Class APIView1(APIView):
template_name = “PartialTemplate1.html”
def get(self, request, *args, **kwargs):
date = request.POST.get(‘date’)
timeslots = function(date)
context = {
‘timeslots’: timeslots
}
return render(request, template_name, context).
初始模板.html:
<form hx-post='{% url "appname:apiview1_url" %}' hx-target='#ticket-form'>
{% csrf_token %}
{{ date_form }}
<input type="submit" value="View Time Slots">
</form>
<div id="booking-form-container">
<div id="ticket-form">
<input type="submit" value="View Time Slots">
</div>
</div>
PartialTemplate1.html:
<div class="container mt-5" style="width: 80%">
<div id="time-slots">
{% for timeslot in timeslots %}
<button name="timeslot_button" hx-post='{% url " appname:apiview2_url" %}' hx-target="#booking-form-container" hx-swap="outerHTML show:#ticket-form:top " hx-include="this">
{{ timeslot.start_time|format_time }} - {{ timeslot.end_time|format_time }}
<input name="data-timeslot" value="{{timeslot}}" type="hidden">
</button>
{% endfor %}
</div>
</div>
PartialTemplate1 应在提交日期表单后在主模板内呈现。这应包括给定日期的可用时段列表。
用户随后可以从 PartialTemplate1 段中选择一个时隙。当他们选择一个时间段时,他们选择的时间段的数据应该被发布到另一个APIView(APIView2):
Class APIView2(APIView):
form_class = ticket_form
def get(self, request, *args, **kwargs):
selected_timeslot = request.POST.get(‘timeslot’)
timeslot_ticket_data = function(selected_timeslot)
form = self.form_class(timeslot_ticket_data=timeslot_ticket_data)
return response(form)
APIView2 将用表单实例 (ticket_form) 替换时段列表。然后用户可以填写表格。
现在,据我了解,最初包含的日期表单、选择的时段以及他们在门票表单上选择的门票中的数据都应该在初始模板中可用吗?因此,回到我最初的视图,我应该能够在发布请求中获取使用 htmx 和 APIViews 生成的所有数据,并将其发布在一起(在提交 Ticket_form 时)以创建,这个例子是预订摘要吗?
Class InitialView(View):
…
def post(self, request, *args, **kwargs):
date = request.GET.get(‘date)
timeslot = request.GET.get(‘timeslot’)
form = ticket_form(request.POST)
if form.is_valid():
*create a new model instance using above data on post*
redirect(reverse(app_name:booking_summary, kwargs={'slug': self.kwargs[‘slug’]}))
我的理解正确吗?
从您需要实现的目标来看,您不需要三个单独的视图。只要有两个:
InitialView
和TimeslotView
。 InitialView should render the
date_formduring
GETrequest and on
POSTrequest return
timeslotspartial template (partial_template_1.html).
TimeslotsViewwill then only have to handle
POSTrequest and return
ticket_form`.
这是建议的结构:
class DateView(View): # or InitialView
def get(self, request, *args, **kwargs):
context = dict(date_form=date_form())
return render(request, self.template_name, context)
def post(self, request, *args, **kwargs):
date = request.POST.get("date")
timeslots = ....
context = dict(timeslots=timeslots)
return render(request, timeslots_partial.html, context)
class TimeslotsView(View):
def post(self, request, *args, **kwargs):
timeslot = request.POST.get("timeslot")
timeslot_data = function(timeslot)
ticket_form = ticket_form(timeslot_data=timeslot_data)
context = dict(form=ticket_form)
return render(request, ticket_form_partial.html, context)
class TicketView(View):
def get(self, request, *args, **kwargs):
....
def post(self, request, *args, **kwargs):
....
主模板:
<form hx-post='{% url "appname:date_view" %}' hx-target='#ticket-form'>
{% csrf_token %}
{{ date_form }}
<input type="submit" value="View Time Slots">
</form>
<div id="booking-form-container">
<div id="ticket-form">
<!-- leave this empty -->
</div>
</div>
timeslots_partial.html
我将时间段变成了表单,因为我相信将其作为表单而不是任意值提交是合乎逻辑的(我猜有例外,但在这种情况下我没有看到它们。
<form hx-post='{% url "appname:timeslots_view" %}' hx-target='#ticket-form'>
{% csrf_token %}
<label for="timeslot">Available timeslots </label>
<select id="timeslot" name="timeslot">
{% for timeslot in timeslots %}
<option value="{{timeslot}}"> {{ timeslot.start_time|format_time }} - {{ timeslot.end_time|format_time }} </option>
{% endfor %}
</select>
<input type="submit" value="View ticket">
</form>
<div id="booking-form-container">
<div id="ticket-form">
<input type="submit" value="View Time Slots">
</div>
</div>
ticket_form.html
<form hx-post='{% url "appname:ticket_view" %}' hx-swap="none">
<!-- I don't know what you want to do after submitting a ticket, maybe redirect?? -->
{% csrf_token %}
{{ ticket_form }}
<input type="submit" value="Save ticket">
</form>