django admin中的外键数据范围过滤

o8x7eapl  于 2023-11-20  发布在  Go
关注(0)|答案(1)|浏览(144)

对于使用django admin的酒店预订系统,我想过滤给定日期范围内的可用房间,模型如下

class Room(models.Model):
    id = models.AutoField(primary_key=True)
    hotel = models.ForeignKey(Hotel, on_delete=models.CASCADE)

class Booking(models.Model):
    id = models.AutoField(primary_key=True)
    start_date = models.DateField(verbose_name=_("Start date"))
    end_date = models.DateField(verbose_name=_("End date"))
    room = models.ForeignKey(Room, on_delete=models.CASCADE)

字符串
我如何在管理中过滤房间,以便我可以选择一个日期范围,并只返回在选择范围内没有预订的房间?
非常感谢

zed5wv10

zed5wv101#

为了传递范围数据,我在admin中创建了一个表单。为此,我覆盖了admin/change_list.html templatechange_list.html模板添加到目录:templates/admin
我尝试只使用Django进行过滤,例如:

response.context_data['cl'].result_list = (
                        Room.objects.filter(~Q(booking__end_date__range=val) &
                                            ~Q(booking__start_date__range=val)))

字符串
但结果并不完全正确。
我认为需要从每个预订记录创建一个日期范围,并将其与从表单日期创建的范围进行比较。Pandas非常适合此目的。使用以下方法:date_range,isinloc
admin.py

import pandas as pd
from django.contrib import admin
from .forms import TestForm
from .models import *

class Room_Admin(admin.ModelAdmin):
    list_display = ('id', 'hotel')
    change_list_template = 'admin/change_list.html'

    def changelist_view(self, request, extra_context=None):
        response = super().changelist_view(
            request,
            extra_context=extra_context,
        )

        if request.method != 'POST':
            response.context_data['form'] = TestForm()
        else:
            form = TestForm(request.POST)
            if form.is_valid():
                response.context_data['form'] = form
                # Getting the start and end from the form
                val = [form.cleaned_data.get('start'), form.cleaned_data.get('end')]

                bkg = Booking.objects.values('start_date', 'end_date', 'room')
                # Create a list based on form dates from and to
                custom_range = pd.date_range(start=val[0], end=val[1])

                df = pd.DataFrame(bkg)

                def f(x):
                    abc = pd.date_range(
                        start=df.loc[x, 'start_date'], end=df.loc[x, 'end_date']
                    ).isin(custom_range)

                    return ~abc.any()

                # List of rooms based on the secondary Booking model whose
                # dates do not intersect with custom_range dates
                room = [df.loc[i, 'room'] for i in range(len(df)) if f(i)]

                # room numbers that are not booked at all
                no_booking = [i.id for i in Room.objects.all() if len(i.booking_set.all()) < 1]
                room = room + no_booking
                response.context_data['cl'].result_list = Room.objects.filter(id__in=room)

                return super(Room_Admin, self).changelist_view(request, extra_context=response.context_data)

        return response

admin.site.register(Room, Room_Admin)


forms.py

class TestForm(forms.Form):
    start = forms.DateField(widget=forms.SelectDateWidget(years=range(2022, 2025)))
    end = forms.DateField(widget=forms.SelectDateWidget(years=range(2022, 2025)))


模板

{% extends 'admin/change_list.html' %}

{% block result_list %}
<form action='' method='POST'>
    {% csrf_token %}
    {{ form.as_p }}
    <input type='submit' value='adding'/>
</form>

{{block.super}}

{% endblock %}

相关问题