Django表单预览 - 如何使用'cleaning_data' [英] Django Form Preview - How to work with 'cleaned_data'

查看:178
本文介绍了Django表单预览 - 如何使用'cleaning_data'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

感谢Insin回答以前的问题相关。



他的回答工作良好,但是对于cleaning_data的提供感到困惑,更准确地说,如何使用它?

  class RegistrationFormPreview(FormPreview):
preview_template ='workshop / workshop_register_preview.html'
form_template ='workshop / workshop_register_form.html'

def done(self,request,clean_data):
#使用clean_data执行某些操作,然后将
#重定向到成功页面。

注册=注册(clean_data)
registration.user = request.user
registration.save()
#尝试使用clean_data抛出错误:TypeError
#int()参数必须是字符串或数字,而不是'dict'
#显然fk是python对象(?)而不是fk_id
#但是如何在简单的方法?



#以下工作正常,但是,似乎是双重处理POST数据
#已经在django.formtools.preview中处理.post_post
#方法,并传递给这个'完成'方法,其设计为
#被覆盖。
'''
form = self.form(request.POST)#用POST数据表示形式
registration = form.save(commit = False)#添加用户$ b之前保存
registration.user = request.user#添加用户
registration.save()#并保存。
'''

return HttpResponseRedirect('/ register / success')

为了快速参考,这里是post_post方法的内容:

  def post_post(self,request):
验证POST数据,如果有效,调用done(),否则重新显示表单。
f = self.form(request.POST,auto_id = AUTO_ID)
如果f.is_valid():
如果self.security_hash(request,f)!= request.POST.get(self .unused_name('hash')):
返回self.failed_hash(请求)#安全哈希失败。
return self.done(request,f.cleaned_data)
else:
返回render_to_response(self.form_template,
{'form':f,'stage_field':self.unused_name ('stage'),'state':self.state},
context_instance = RequestContext(request))


解决方案

之前我从未尝试过您在这里使用的ModelForm,但是您可以使用**操作符将clean_data字典扩展到关键字预期您的注册构造函数的参数:

 注册=注册(** cleaning_data)

您的模型类的构造函数使用Django的Model元类转换为生成对象的实例级属性的关键字参数。 **操作符是一个调用约定,它告诉Python将你的字典扩展成这些关键字参数。



换句话说...



你目前正在做的等同于:

 注册=注册({'key': 'value',...})

哪些不是你想要的,因为构造函数期望关键字参数而不是包含你的关键字参数的字典。



你想做什么是这个

 注册=注册(key ='value',...)

类似于这一点:

 注册=注册(** {'key':'value',...} )

再次,我从来没有尝试过,但似乎只要你工作对您的表单没有任何想法,例如为您的注册预期不会添加新的属性构造函数。在这种情况下,在执行此操作之前,您可能需要修改clean_data字典中的项目。



您似乎失去了某些功能虽然通过窗体预览实用程序,ModelForms固有的。也许你应该把你的用例放到Django邮件列表中,看看这个API是否有潜在的增强,可以使它更好的使用ModelForms。



编辑



上面我已经说过,你可以随时从clean_data字典手动提取字段,并将它们传递到注册构造函数但是请注意,在您向模型添加新字段时,您必须记住更新此代码。

 注册=注册(
x = clean_data ['x'],
y = cleaning_data ['y'],
z = cleaning_data ['z'],
...


Thanks to Insin for answering a previous question related to this one.

His answer worked and works well, however, I'm perplexed at the provision of 'cleaned_data', or more precisely, how to use it?

class RegistrationFormPreview(FormPreview):
    preview_template    = 'workshops/workshop_register_preview.html'
    form_template       = 'workshops/workshop_register_form.html'

    def done(self, request, cleaned_data):
        # Do something with the cleaned_data, then redirect
        # to a "success" page. 

        registration            = Registration(cleaned_data)
        registration.user       = request.user
        registration.save()
        # an attempt to work with cleaned_data throws the error: TypeError 
        # int() argument must be a string or a number, not 'dict'
        # obviously the fk are python objects(?) and not fk_id
        # but how to proceed here in an easy way?



        # the following works fine, however, it seems to be double handling the POST data
        # which had already been processed in the django.formtools.preview.post_post
        # method, and passed through to this 'done' method, which is designed to 
        # be overidden.
        '''
        form                    = self.form(request.POST)   # instansiate the form with POST data
        registration            = form.save(commit=False)   # save before adding the user
        registration.user       = request.user              # add the user
        registration.save()                                 # and save.
        '''

        return HttpResponseRedirect('/register/success')

For quick reference, here's the contents of the post_post method:

def post_post(self, request):
    "Validates the POST data. If valid, calls done(). Else, redisplays form."
    f = self.form(request.POST, auto_id=AUTO_ID)
    if f.is_valid():
        if self.security_hash(request, f) != request.POST.get(self.unused_name('hash')):
            return self.failed_hash(request) # Security hash failed.
        return self.done(request, f.cleaned_data)
    else:
        return render_to_response(self.form_template,
            {'form': f, 'stage_field': self.unused_name('stage'), 'state': self.state},
            context_instance=RequestContext(request))

解决方案

I've never tried what you're doing here with a ModelForm before, but you might be able to use the ** operator to expand your cleaned_data dictionary into the keyword arguments expected for your Registration constructor:

   registration = Registration (**cleaned_data)

The constructor to your model classes take keyword arguments that Django's Model meta class converts to instance-level attributes on the resulting object. The ** operator is a calling convention that tells Python to expand your dictionary into those keyword arguments.

In other words...

What you're doing currently is tantamount to this:

registration = Registration ({'key':'value', ...})

Which is not what you want because the constructor expects keyword arguments as opposed to a dictionary that contains your keyword arguments.

What you want to be doing is this

registration = Registration (key='value', ...)

Which is analogous to this:

registration = Registration (**{'key':'value', ...})

Again, I've never tried it, but it seems like it would work as long as you aren't doing anything fancy with your form, such as adding new attributes to it that aren't expected by your Registration constructor. In that case you'd likely have to modify the items in the cleaned_data dictionary prior to doing this.

It does seem like you're losing out on some of the functionality inherent in ModelForms by going through the form preview utility, though. Perhaps you should take your use case to the Django mailing list and see if there's a potential enhancement to this API that could make it work better with ModelForms.

Edit

Short of what I've described above, you can always just extract the fields from your cleaned_data dictionary "by hand" and pass those into your Registration constructor too, but with the caveat that you have to remember to update this code as you add new fields to your model.

registration = Registration (
    x=cleaned_data['x'],
    y=cleaned_data['y'],
    z=cleaned_data['z'],
    ...
)

这篇关于Django表单预览 - 如何使用'cleaning_data'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆