【问题标题】:Django Class Based View With ModelChoiceField带有 ModelChoiceField 的 Django 基于类的视图
【发布时间】:2018-03-12 10:24:21
【问题描述】:

我已经使用 Django 大约 3 个月了,感觉自己变得更好了,我的工作方式是基于类的视图。从表面上看,它们看起来更干净、更容易理解,在某些情况下确实如此。在其他方面,没有那么多。我正在尝试通过 ModelChoiceField 和表单使用简单的下拉视图。我可以让它与基于函数的视图一起使用,如下所示在我的 views.py 文件中:

def book_by_name(request):
    form = BookByName(request.POST or None)
    if request.method == 'POST':
        if form.is_valid():
            book_byname = form.cleaned_data['dropdown']
            return HttpResponseRedirect(book_byname.get_absolute_url1())
    return render(request,'library/book_list.html',{'form':form})

这是我在 forms.py 中的表单:

class BookByName(forms.Form):

    dropdown = forms.ModelChoiceField(queryset=Book.objects.none())

    def __init__(self, *args, **kwargs):
        super(BookByName, self).__init__(*args, **kwargs)
        self.fields['dropdown'].widget.attrs['class'] = 'choices1'
        self.fields['dropdown'].empty_label = ''
        self.fields['dropdown'].queryset = Book.objects.order_by('publisher')

此代码有效。当我尝试转换为基于类的视图时,问题就开始了。我试图在views.py中做这样的事情:

class BookByNameView(FormView, View):
    form_class = BookByName
    initial = { 'Book' : Book }
    template_name = 'library/book_list.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(initial=self.initial)
        return render(request, self.template_name, {'form': form})

    def get_success_url(self, *args):
        return reverse_lazy('library:book_detail', args = (self.object.id,))

当在同一个表单中使用这个时,我收到一个属性错误,

“BookByNameView”对象没有“对象”属性。

我也尝试过 ListView 并且在此过程中收到了其他几个错误。 get_success_url 还需要接受一个主键,我也不知道如何把它传入。同样,我是 3 个月的 Django 新手,所以请保持温柔,并提前感谢您的想法和建议!我觉得我在球场上......只是找不到我的座位!如果有更清洁/更好的方法可以做到这一点,我非常愿意以不同的方式做这件事!

根据最新反馈,基于类的视图应该如下所示:

class BookNameView(FormView):
    form_class = BookName
    template_name = 'library/book_list.html'

    def get_success_url(self, *args):
        return reverse_lazy('library:book_detail')

这是正确的吗?我运行了一个测试版本,并回答了你关于我为什么要使用 self.object.id 的问题,我试图从我用来返回视图的 modelchoicefield 中获取 pk .这可能是我有点迷路的地方。我正在尝试从 modelchoicefield 下拉列表中获取详细视图,并返回所选的书。但是,我似乎无法将 pk 成功传递给此视图。

我将代码更新为...

class BookByNameView(FormView, ListView):
    model = Book
    form_class = BookByName
    template_name = 'library/book_list.html'

    def get_success_url(self, *args):
        return reverse_lazy('library:book_detail')

但现在它显示错误...为“book_detail”反转,未找到任何参数。

【问题讨论】:

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


    【解决方案1】:

    你为什么要在那里使用self.object?您在原始视图中使用了form.cleaned_data,这也是您应该在基于类的版本中使用的。请注意,表单被传递给form_valid

    请注意,您还做过很多其他奇怪的事情。您的 getmethod 毫无意义,就像您对 initial dict 的定义一样;你应该删除它们。此外,FormView 已经从 View 继承,无需在声明中明确包含 View。

    【讨论】:

    • 感谢您抽出宝贵时间回答我的问题。正如我所写,我对此很陌生,因此我在论坛上提出了问题。你能详细说明一下语法吗?
    • 我根据你的 cmets 更新了代码,这更接近你的建议吗?
    • 在玩了一些之后,我更新了视图以使用 ListView,它可以做我想做的事情,将书籍列表加载到我的模型选择字段中。这很好用。但是,当我尝试在我的模型选择字段中选择一个条目时,它似乎无法显示单个记录。我快到了……
    【解决方案2】:

    你可以重写 FormView 中的 form_valid() 函数来实现你想要的。如果表单有效,则将其传递给 form_valid() 函数。

    试试这个:

    class BookByNameView(FormView):
           model = Book
           form_class = BookByName
           template_name = 'library/book_list.html'
    
           def form_valid(self, form):
                bookbyname = form.cleaned_data['dropdown']
                return HttpResponseRedirect(bookbyname.get_absolute_url())
    

    【讨论】:

      猜你喜欢
      • 2014-11-15
      • 2011-09-18
      • 2012-10-23
      • 2013-10-22
      • 1970-01-01
      • 2010-12-24
      • 1970-01-01
      • 1970-01-01
      • 2014-02-16
      相关资源
      最近更新 更多