【问题标题】:Django Forms - object has no attribute 'request' errorDjango Forms - 对象没有属性“请求”错误
【发布时间】:2015-03-23 15:40:51
【问题描述】:

我有一个搜索表单,其中有一个可选字段 city_id

我的表格:

class BusinessSearchForm(SearchForm):

def no_query_found(self):
    return self.searchqueryset.all()

def search(self):

    sqs = super(BusinessSearchForm, self).search()

    # if something goes wrong
    if not self.is_valid():
        return self.no_query_found()

    # filter search results 
    if 'city_id' in self.request.GET: # or POST
        sqs = sqs.filter(city_id=self.request.GET.get('city_id')) 
    else:
        sqs = sqs.filter(...)

    return sqs

这是我得到的错误:

object has no attribute 'request' error

默认干草堆搜索表单:

 class SearchForm(forms.Form):
q = forms.CharField(required=False, label=_('Search'),
                    widget=forms.TextInput(attrs={'type': 'search'}))

def __init__(self, *args, **kwargs):
    self.searchqueryset = kwargs.pop('searchqueryset', None)
    self.load_all = kwargs.pop('load_all', False)

    if self.searchqueryset is None:
        self.searchqueryset = SearchQuerySet()

    super(SearchForm, self).__init__(*args, **kwargs)

def no_query_found(self):
    """
    Determines the behavior when no query was found.

    By default, no results are returned (``EmptySearchQuerySet``).

    Should you want to show all results, override this method in your
    own ``SearchForm`` subclass and do ``return self.searchqueryset.all()``.
    """
    return EmptySearchQuerySet()

def search(self):
    if not self.is_valid():
        return self.no_query_found()

    if not self.cleaned_data.get('q'):
        return self.no_query_found()

    sqs = self.searchqueryset.auto_query(self.cleaned_data['q'])

    if self.load_all:
        sqs = sqs.load_all()

    return sqs

def get_suggestion(self):
    if not self.is_valid():
        return None

    return self.searchqueryset.spelling_suggestion(self.cleaned_data['q'])

view.py

query = ''
results = EmptySearchQuerySet()

args = {}
args.update(csrf(request))

if request.GET.get('q'):
    form = form_class(request.GET, searchqueryset=searchqueryset,
                      load_all=load_all)

    if form.is_valid():
        query = form.cleaned_data['q']
        results = form.search()
else:
    form = form_class(searchqueryset=searchqueryset,
                      load_all=load_all)
....

【问题讨论】:

  • 不,表单没有请求属性。是什么让您认为它确实有效?
  • 能否提供 SearchForm 类的导入语句?
  • @daniel 每次我将request 添加到表单时,都会收到错误name 'request' is not defined
  • @justcompile 这是默认的 Haystack 表单
  • @justcompile 我将搜索表单添加到我的 OP 中

标签: python django search


【解决方案1】:

您需要将 city_id 传递给表单:

def search(self, city_id):
    ...

    sqs = sqs.filter(city_id=city_id) 
    ...

并像这样使用它:

city_id = request.GET.get('city_id')
my_form.search(city_id)

【讨论】:

    【解决方案2】:

    错误语句本身回答了您的问题。您必须将请求传递给您的 search 函数。试试这个:

    def search(self,request):
    
    sqs = super(BusinessSearchForm, self).search()
    
    # if something goes wrong
    if not self.is_valid():
        return self.no_query_found()
    
    # filter search results 
    if 'city_id' in self.request.GET: # or POST
        sqs = sqs.filter(city_id=self.request.GET.get('city_id')) 
    else:
        sqs = sqs.filter(...)
    
    return sqs
    

    【讨论】:

    • 1.这仍然行不通,默认表单构造函数 2 从未定义“self.request”。即使它确实 工作,它也是糟糕的设计。表单和视图具有完全不同的关注点。让我们不要把糟糕的做法传授给初学者。
    • @lullis 是正确的,它不起作用,我试过了。你得到search() takes exactly 2 arguments (1 given) 错误
    【解决方案3】:

    您似乎正在尝试在表单类中运行特定于视图的代码。表单应该只关心验证数据。我假设您有一个视图函数,该表单正在被实例化,并且从那里视图应该是进行查询的视图:

    在你的视野中尝试:

    query = ''
    results = EmptySearchQuerySet()
    
    args = {}
    args.update(csrf(request))
    
    posted_data = {'q': request.GET.get('city_id') }
    
    form = form_class(posted_data, searchqueryset=searchqueryset, load_all=load_all)
    
    if form.is_valid():
        results = form.search(request.GET.get('city_id'))
    

    并以您的形式:

    def search(self, city_id=None):
    
        sqs = super(BusinessSearchForm, self).search()
    
        if city_id is not None:
            sqs = sqs.filter(city_id=city_id)
        return sqs
    

    【讨论】:

    • 这是一个 Haystack SearchForm,我可以手动过滤结果。如果我写sqs = sqs.filter(city_id=1),我将得到city_id=1 的正确结果。我只想动态过滤city_id,仅此而已。
    • 我明白这一点。我要说的是,此表单仅为您提供了有关如何验证搜索参数的构建块。你仍然需要有一个观点,对吧?你的 Django 视图如何使用这个表单?
    • 我已将视图添加到我的 OP
    【解决方案4】:

    虽然这是不好的做法,但您可以按照以下方式扩展 init 方法:

    class BusinessSearchForm(SearchForm):
        def __init__(self, *args, **kwargs):
            self.searchqueryset = kwargs.pop('searchqueryset', None)
            self.load_all = kwargs.pop('load_all', False)
    
            if self.searchqueryset is None:
                self.searchqueryset = SearchQuerySet()
    
            self.request = kwargs.pop('request', None)
    
            super(SearchForm, self).__init__(*args, **kwargs)
    

    然后,无论您在哪里初始化 BusinessSearchForm,您都将请求作为额外的 kwarg 传递:

    if request.GET.get('q'):
        form = form_class(request.GET, searchqueryset=searchqueryset,
                          load_all=load_all, request=request)
    
    if form.is_valid():
        query = form.cleaned_data['q']
        results = form.search()
    else:
        form = form_class(searchqueryset=searchqueryset,
                      load_all=load_all, request=request)
    

    【讨论】:

    • 如果我错了请纠正我,但我们可以通过将代码拆分为views.py来避免request未找到的问题,对吧?
    • 绝对!答案线程上有许多潜在的方法,如上所述,上面的代码在封装方面并不理想,但可以解决 OP 缺少属性的问题
    • 我无法理解为什么 BusinessForm 类中有一个 search 方法,我是 Djano 的新手 :)
    • @justcompile 感谢您的反馈。我正在尝试实施此解决方案,但不确定我是否做对了。第一部分将进入我的 forms.py,第二部分进入视图,对吗?话虽如此,如果我仍将原始 def search(self) ... 保留在 BusinessSearchForm 中,并且仅将您的部分包含在我的 def no_query_found(self) ... 上方,我仍然会收到相同的错误 global name 'request' is not defined。我错过了什么?
    • 这一次听起来像是一个不同的错误(全局名称未定义,而不是对象没有属性)。这意味着视图中的请求对象不可用,这可能是缩进问题...您使用的是基于类的视图还是方法视图?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-24
    • 2017-01-22
    • 2015-12-06
    • 1970-01-01
    • 2021-10-09
    • 1970-01-01
    相关资源
    最近更新 更多