【问题标题】:Class Based FormView基于类的 FormView
【发布时间】:2018-05-07 20:14:41
【问题描述】:

我已经研究了这个问题几天,但似乎无法找到我正在寻找的确切内容。我已经在 StackOverflow 和 Google 上搜索了 ModelChoiceField 和 ChoiceField,我的问题有很多变体,但都没有。简而言之,我正在尝试使用基于类的 FormView,然后捕获用户选择并将其传递给基于类的 ListView。这是我的代码。

Forms.Py

class BookByStatus(forms.Form):

   dropdown = forms.ChoiceField(choices=[],required=False)

   def __init__(self, user, *args, **kwargs):
        super(BookByStatus, self).__init__(*args, **kwargs)
        self.fields['dropdown'].widget.attrs['class'] = 'choices1'
        self.fields['dropdown'].empty_label = ''
        self.fields['dropdown'].choices = 
        Book.objects.values_list("author","author").distinct("Publisher")

上面的代码运行良好,并在我的视图中显示了我正在寻找的输出。那里没有问题....然后我有我的 FormView...

class BookByStatusView(LoginRequiredMixin,FormView):
    model = Book
    form_class = BookByStatus
    template_name = 'xyz123/publisher.html'
    success_url = reverse_lazy('Book:book_by_list',kwargs=
                               {'dropdown':'dropdown'})

    def get_form_kwargs(self):
        kwargs = super(BookByStatusView, self).get_form_kwargs()
        kwargs['user'] = self.request.user        
        return kwargs

    def form_valid(self, form):
        self.request.POST['dropdown']
        BookByStatusView = form.cleaned_data['dropdown']
        return super(BookByStatusView, self).form_valid(form)

上面的代码工作正常,但带我到下面的 ListView,我似乎无法将下拉值传递给....我尝试了几种不同的 get_form_kwargs 迭代,并将我的表单更改为 ModelChoiceField,但似乎仍然无法理解如何根据用户的输入获取查询集...

最后是 ListView...

class BookByStatusListView(LoginRequiredMixin,ListView):
    model = Book
    form_class = BookByStatus
    context_object_name = 'book_list'
    template_name = 'xyz123/book_by_status_list.html'
    paginate_by = 15

    def get_queryset(self, *kwargs):
        form = self.form_class(self.request.GET)
        dropdown = self.kwargs.get('dropdown', None)
        if form.is_valid():
            return Book.objects.filter(dropdown__icontains=form.
            cleaned_data['dropdown'])
        return Book.objects.all()

我正在尝试从 FormView 中获取下拉输入,然后使用两个单独的视图将其传递给列表视图。我需要将值从 FormView 传递到 ListView。我很清楚如何在 ChoiceField 中获取 FormView 中的数据,以及如何显示 ListView,但我似乎无法弄清楚如何将下拉数据从 FormView 传递到 ListView。我可以让 ListView 工作,但只能使用完整的查询集,而不是过滤的。

这是书本模型....

class Book(models.Model):
    Author CHOICES = (
        ("New","New"),
        ("Old","Old"),
    )

    Author = models.CharField(choices=Author_CHOICES,max_length=10)

这是网址...

url(r'^book_by_list/(?
P<dropdown>\w+)/$',views.BookByStatusListView.as_view(), 
name='book_by_list'),

提前感谢您的任何建议!

更新的方法...使用 request.session。无论我尝试了多少 get_context_data 或 get_form_kwargs 组合,我之前的方法都不允许我将值从一个视图传递到另一个视图。根据我收到的输入,我开始探索 request.session 方法并且我已经走得更远了。最后一件仍然存在,在我的 LISTVIEW 中获取 request.session 值,以便我可以相应地过滤我的查询集。

class BookByStatusView(LoginRequiredMixin,FormView):

    model = Book
    form_class = BookByStatus
    template_name = 'xyz123/publisher.html'
    success_url = reverse_lazy('Book:book_by_list') 

    def form_valid(self, form):
        self.request.session['dropdown'] = form.cleaned_data['dropdown']
        return super(BookByStatusView, self).form_valid(form)

    def get_form_kwargs(self):
        kwargs = super(BookByStatusView, self).get_form_kwargs()
        kwargs['user'] = self.request.user
        return kwargs

在我的 html 模板中,我将 request.session 值用作...

{{ request.session.dropdown }}

我将 URL 恢复为..

url(r'^book_by_list/$,views.BookByStatusListView.as_view(), 
name='book_by_list'),

剩下的最后一部分是弄清楚如何通过这种方法利用 LISTVIEW。

我当前的列表视图:

class BookByStatusListView(LoginRequiredMixin,ListView):
    model = Book
    form_class = BookByStatus
    context_object_name = 'book_list'
    template_name = 'xyz123/book_by_status_list.html'
    paginate_by = 15

def get_queryset(self):
    queryset = Book.objects.none()
    dropdown = self.request.session.get('dropdown')
    if dropdown == 'New':
        queryset = Book.objects.all()
    elif dropdown == 'Old':
        queryset = Book.objects.none()
    return queryset

我似乎无法弄清楚如何将下拉值正确传递给 ListView,以便正确显示查询集。根据我的测试,我似乎没有在 get_queryset 函数中正确捕获下拉列表。有任何想法吗?

我想通了。我用正确的语法更新了 get_queryset。感谢所有帮助我朝着正确的方向前进。最后的问题..这是将值从一个视图传递到另一个视图的最佳方式吗?有一个更好的方法吗?这种方法有什么问题吗?

【问题讨论】:

  • 请您展示一下 Book 模型、它的 get_absolute_url1() 方法和 URL。
  • @Daniel Roseman 我昨晚做了更多研究,据我所知,我可以使用 URL 将值传递给 LISTVIEW?我玩了几个选项,但也无法让它发挥作用。这通常是我应该尝试做的吗?
  • 我真的不明白你在这里做什么。除此之外,您的 BookByStatusView form_valid 方法不可能工作,因为您从下拉列表中获取了一个字符串,然后尝试在其上调用 get_absolute_url1()。但是您确实需要准确解释您要在 ListView 上显示的 什么
  • 我正在尝试使用 FormView 上的下拉菜单将值传递给 ListView。我已经更新了我的 FormView,我更接近了。我更新了 formview 代码以包含 KWARGS,我还更新了 URL 以包含我发送到 LISTVIEW 的 KWARG。这正在工作......我成功地将 KWARG 传递给 URL,但不是实际值。我仍在试图弄清楚如何获得价值。我怀疑它是 GET_Context_Data 或 Get_queryset,但还没有弄清楚……我已经用最新的更新更新了上面的代码。
  • 我在 FormView 的 form_valid 函数中添加了一个新行,并通过添加 Print(self.request.POST[ 'dropdown']) 到代码中,但仍然无法弄清楚如何将值作为 KWARG 发送到 LISTVIEW。 KWARG 仍然以 DROPDOWN 的形式出现,而不是我在 FORMVIEW 中捕获的值...

标签: django python-3.x django-forms django-templates django-views


【解决方案1】:

这不起作用,因为重定向会创建一个新的请求/响应,并且之前的数据会丢失。如果我正确理解您想要什么,其中一个选项是将下拉值保存到BookByStatusView 中的会话,然后在BookByStatusListView 中检索它。

您保存到会话:

request.session['dropdown_value'] = form.cleaned_data['dropdown']

并通过以下方式检索:

dropdown_value = request.GET.get('dropdown_value')

这是How to use session Django 文档的一部分。

编辑:您也可以像这样将值作为 url 参数传递:

author = 'michael cricthon'
title = 'kongo'
year = [1999, 2000, 2001]
type = ['electronic', 'print', 'hardcover', 'softcover']

params = '?author={}&title={}&&year={}&type={}'.format(
            urllib.parse.quote_plus(author), 
            urllib.parse.quote_plus(title),
            ','.join(year),
            ','.join(type))

return HttpResponseRedirect(reverse('search') + params)

链接如下所示:

../search/?author=michael+crichton&title=kongo&year=1999,2000,2001&type=electronic,print,hardcover,softcover

你得到参数

author = request.GET.get('author')
title = request.GET.get('title')
... etc.

【讨论】:

  • 感谢您的意见。我会研究那个。我正在使用基于类的视图,根据您上面的输入,这有关系吗?我也开始探索通过 URL 传递值。这行得通吗?
  • 是否使用 CBV 没关系。如果它是一个简单的值,如数字、字符串或列表,则可以通过 URL 传递值。我将使用将值作为 URL 参数传递的选项来更新答案。
  • Request.session 让我的代码更进一步。最后一点是尝试在我的列表视图中获取值。我已经用我迄今为止尝试过的方法更新了我的解决方案。除查询集过滤外,所有功能均有效。关于我可能做错的任何想法?
  • 相信我解决了。更新了上面的代码以反映我的最终答案。感谢您的帮助。
猜你喜欢
  • 2012-05-11
  • 1970-01-01
  • 1970-01-01
  • 2018-02-22
  • 1970-01-01
  • 2014-10-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多