带有ModelChoiceField的基于Django类的视图

带有ModelChoiceField的基于Django类的视图,django,python-3.x,django-forms,django-views,Django,Python 3.x,Django Forms,Django Views,我已经和Django一起工作了大约3个月了,我觉得自己已经好了一点,正在努力实现基于类的视图。从表面上看,它们看起来更干净、更容易理解,在某些情况下,它们的确如此。在其他国家,情况并非如此。我试图通过ModelChoiceField和表单使用一个简单的下拉视图。我可以让它使用基于函数的视图,如下所示,在my views.py文件中: def book_by_name(request): form = BookByName(request.POST or None) if requ

我已经和Django一起工作了大约3个月了,我觉得自己已经好了一点,正在努力实现基于类的视图。从表面上看,它们看起来更干净、更容易理解,在某些情况下,它们的确如此。在其他国家,情况并非如此。我试图通过ModelChoiceField和表单使用一个简单的下拉视图。我可以让它使用基于函数的视图,如下所示,在my 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”对象没有属性“object”

我也尝试过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,我正在使用该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\u detail”相反,没有找到任何参数。

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


注意,你也做了很多其他奇怪的事情。您的
get
方法是毫无意义的,您对
initial
dict的定义也是如此;你应该同时删除它们。此外,FormView已经从View继承,您的声明中不需要显式包含View。

您可以覆盖FormView中的form\u 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())

谢谢你花时间回答我的问题。正如我所写的,我在这方面是新手,因此我在论坛上提出了问题。你能详细解释一下语法吗?我根据你的评论更新了代码,这更接近你的建议吗?在玩了一些之后,我更新了视图以使用ListView,这就是我想要它做的,将书籍列表加载到我的modelchoicefield中。那很好。但是,当我尝试在modelchoicefield中选择一个条目时,它似乎无法显示单个记录。我快到了。。。