【问题标题】:'str' object has no attribute 'visible_fields'; django class based views“str”对象没有属性“visible_fields”; django 基于类的视图
【发布时间】:2015-11-01 17:01:03
【问题描述】:

在昨天开始关注班级观点之后,我整天都在为班级观点苦苦挣扎。我的问题是不断收到'str' object has no attribute 'visible_fields',所以下面的“表单”项并不是真正的表单:

模板-

<form action="" method="post">
    {% csrf_token %}
    {{form|bootstrap}}
    <input type="submit" name="submit" value="Add new article"/>
</form>

查看-

class ArticleCreateView(CreateView):
    model = Article
    template_name = 'index/add_article.html'
    form_class = ArticleForm

    def post(self, request, *args, **kwargs):
        article_form = self.get_form()
        if article_form.is_valid():
            article = article_form.save(commit=False)
            title   = article_form.cleaned_data['title']
            url     = article_form.cleaned_data['url']
            title = process_title(url)
            article.title = title
            article.save()
            return redirect("index:article_list")
        else:
            form = ArticleForm()
            print type(form)
            print dir(self)
            return render(request, 'index/add_article.html')

最糟糕的部分是打印type(form) 显示它是&lt;class 'index.forms.ArticleForm'&gt;。如果表单已保存,我试图让它重定向到列表视图,如果表单不正确,则重播带有错误的表单(您已经有一篇带有该 URL 的文章)。我听说类视图更易于使用,并且我读过的大型项目都使用它们,但它们看起来确实比旧视图更糟糕。我认为那是因为我没有很好地使用它们

我见过的每个示例都有一个以某种方式获取“表单”的模板,例如

class RangeCreateView(CreateView):
    model = Range
    template_name = 'dashboard/ranges/range_form.html'
    form_class = RangeForm

    def get_success_url(self):
        if 'action' in self.request.POST:
            return reverse('dashboard:range-products',
                           kwargs={'pk': self.object.id})
        else:
            msg = render_to_string(
                'dashboard/ranges/messages/range_saved.html',
                {'range': self.object})
            messages.success(self.request, msg, extra_tags='safe noicon')
            return reverse('dashboard:range-list')

    def get_context_data(self, **kwargs):
        ctx = super(RangeCreateView, self).get_context_data(**kwargs)
        ctx['title'] = _("Create range")
        return ctx

然后像魔术一样range_form.html:

{% include "dashboard/partials/form_fields.html" with form=form %}

我的问题是我需要处理表单的标题,用

def process_title(url):
    def _search_for_title(url):
        try:
            r = requests.get(url)
            content = r.text
            t = html.document_fromstring(content)
            return t.find(".//title").text
        except IOError:
            return None

    title = _search_for_title(url)
    return title or 'None'

这种方式破坏了基于类的视图的目的。看来我应该通过覆盖表单本身的“干净”来处理标题?

否则,我怎样才能让这个视图传递一个表单对象,在模板中渲染它,如果表单没有通过,就重新渲染模板?

我如何访问模板中的表单?

谢谢

【问题讨论】:

  • 怎么样?通过执行与示例视图相同的操作,而不是像您所做的那样覆盖 post
  • 所以我应该在表单的 clean 方法中更改标题,然后再到达视图?
  • 这就是我现在正在尝试的
  • 但是你要什么?在问题标题中,您要问为什么表单在模板中是“str”类型,但在解释中,您要问如何正确处理表单标题。
  • 我意识到我应该只处理表单中的字段,这解决了我的问题,但我的问题仍然是为什么“表单”没有像往常一样显示在模板中?跨度>

标签: django forms django-class-based-views


【解决方案1】:

您可以按照示例视图执行此操作,而不是像您一样覆盖post

在您的情况下,简单地显示和处理表单是 CreateView 的默认行为。所以根本不需要重写任何方法。你的观点应该是:

class ArticleCreateView(CreateView):
    model = Article
    template_name = 'index/add_article.html'
    form_class = ArticleForm

【讨论】:

  • 其实先生。 Roseman 我需要处理标题(当他们提交表单时)。如果用户没有输入标题,title = process_title(url) 将尝试获取 html 标题元素,如果他们将“标题”留空,我的表单占位符会告诉他们“我将尝试获取标题”。如何在不像上面那样弄乱我的视图的情况下对“标题”进行一些基本处理?
  • 你可以覆盖form_validform_invalid方法,或者覆盖post但是通过使用super调用父方法。
猜你喜欢
  • 2018-05-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-05
  • 2017-10-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多