3

我想编写一个Django CreateView的(CBV),它代替用户ID的用户的电子邮件,并确定(或创建)基于电子邮件的用户。Django:使用附加字段创建视图?

我的模型不包含任何特殊:

class Project(models.Model): 
    name = models.CharField(_('Title'), max_length=100,) 
    user = models.ForeignKey(User, verbose_name=_('user'),) 
    ... 

我forms.py增加了额外的电子邮件字段的形式:

class ProjectCreateForm(forms.ModelForm): 
    email = forms.EmailField(required=True,) 

    class Meta: 
     model = Project 
     fields = ('name', ...,) 

在我的views.py,我想确定如果用户存在或应该创建。在这两种情况下,用户标识都应该保存为Project实例的一部分。

class ProjectCreateDetails(CreateView): 
    form_class = ProjectCreateForm 
    template_name = '...' 
    success_url = reverse_lazy('login') 
    model = Project 

    def form_valid(self, form): 
     try: 
      user = User.objects.get(email=form.email) 
     except User.DoesNotExist: 
      user = User.objects.create_user(form.email, form.email, ''.join([random.choice(string.digits + string.letters) for i in range(0, 10)])) 
      user.save() 
     form.instance.user = user 
     return super(ProjectCreateDetails, self).form_valid(form) 

不过,我现在面临一个错误的'Solution' object has no attribute 'email'

我需要切换到一个FormView而不是CreateView的?

回答

5

你得到错误'Solution' object has no attribute 'email'因为form.email无效。验证的数据永远不可用作为表单或模型表单的属性。当形式(包括模型形式)是有效的,在成功验证数据在form.cleaned_data字典可用。

请注意,您无需致电user.save()。调用create_user已将用户添加到数据库。你不必产生一个随机的密码或者 - 如果passwordNone,然后create_user将设置不可用口令。

最后,请确保您没有在ProjectCreateForm中包含user字段。你可能不这样做,但你的代码说fields = ('name', ...,)所以我不能告诉是肯定的。

把它在一起,你会得到以下的(未经测试)代码:

def form_valid(self, form): 
    try: 
     user = User.objects.get(email=form.cleaned_data['email']) 
    except User.DoesNotExist: 
     user = User.objects.create_user(form.cleaned_data['email'], form.cleaned_data['email']) 
    form.instance.user = user 
    return super(ProjectCreateDetails, self).form_valid(form) 
+0

只是写此评论指出,你可以使用get_or_create方法 –

+1

@AymaneShuichi不,我们不能用'这里get_or_create' - 我们使用'create_user'方法来正确处理密码。 – Alasdair