【问题标题】:'NoneType' object has no attribute 'model' error when retrieving POST request data'NoneType' 对象在检索 POST 请求数据时没有属性 'model' 错误
【发布时间】:2020-11-29 22:05:00
【问题描述】:

我收到 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)

【问题讨论】:

  • 分享完整视图。
  • 我编辑以包含完整视图
  • 为什么在request.method == 'POST'的情况下使用InitialSearchForm
  • InitialSearchForm 用在另一个模板上——我只是设置了这个视图的动作来处理帖子数据
  • 处理DateChoiceForm的POST请求的视图是什么?看来你那边没有设置DateChoiceForm(request.POST, trips=...)

标签: python django attributeerror


【解决方案1】:

你不能像except (ValueError, TypeError, self.queryset.model.DoesNotExist)那样使用except子句。改用实际模型 DoesNotExist: except (ValueError, TypeError, <modelname_here>.DoesNotExist).

另外,您不能设置queryset=None。那是不可能的。您必须改用 <model>.objects.none() 查询集。

如果您希望为视图选择动态模型,我建议您改用基于类的视图。继承使得处理多种模型类型变得更加容易。


编辑:再次阅读您的问题后,我注意到trip_dates = kwargs.pop('trips', None) 实际上检索'trips' 而不是'trip' 这是故意的吗?鉴于您的帖子变量trips 将等于None

第二:您实际上并没有设置查询集。 self.fields['trip'].queryset = trip_dates 将是 None 或字符串列表,但绝不是实际的查询集。因此,无论是否在__init__ 中为ModelChoiceField 设置查询集,它都不是查询集。

【讨论】:

  • 好的,我会调查的,谢谢。实际上,我从终端复制/粘贴了 except - 它没有给出模型名称,只是“model.DoesNotExist”,所以我猜它没有发现问题所在的模型。
  • 我认为主要问题实际上是queryset=None 部分。那肯定是一个查询集。可以为空,但必须是查询集
  • 我在 Init 方法中给它一个查询集。这样不行吗?
  • @fdeboo 我认为问题实际上与您如何处理 POST 数据有关。检查我的更新答案
  • 我的理解是,在表单定义中为“trip”字段设置查询集意味着 DateChoiceForm 现在在其构造函数中具有强制参数。因此,当我使用 request.POST 初始化表单时,它会导致错误,因为我没有传递所需的参数。一个很好的例子在这里:simpleisbetterthancomplex.com/questions/2017/03/22/… 我只是不知道我应该通过什么。在该示例中 ^ 它使用 modelformset_factory。我不确定这是否是我需要的?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-27
  • 2017-09-14
  • 2021-02-17
  • 2023-02-17
  • 2021-09-17
  • 2014-07-10
相关资源
最近更新 更多