Django: CreateView with custom field?
I am trying to program a Django CreateView (CBV) that takes a custom email instead of a user id and defines (or creates) a user based on the email.
My model doesn't contain anything special:
class Project(models.Model):
name = models.CharField(_('Title'), max_length=100,)
user = models.ForeignKey(User, verbose_name=_('user'),)
...
My forms.py adds an extra email field to the form:
class ProjectCreateForm(forms.ModelForm):
email = forms.EmailField(required=True, )
class Meta:
model = Project
fields = ('name', ...,)
In my views.py, I'm trying to determine if a user exists or should be created. In both cases, the user ID must be saved as part of the project instance.
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)
However, I ran into the error that 'Solution' object has no attribute 'email'
.
Do I need to switch to FormView instead of CreateView?
source to share
You will get an error 'Solution' object has no attribute 'email'
because it is form.email
invalid. Validated data is never available as shape attributes or model shape. When the forms (including model forms) are valid, the successfully validated data is available in the dictionary form.cleaned_data
.
Note that you don't need to call user.save()
. The call create_user
has already added the user to the database. You also don't need to generate a random password - if password
- None
will create_user
set an inappropriate password.
Finally, make sure you don't include the field user
in ProjectCreateForm
. You probably won't, but your code speaks fields = ('name', ...,)
, so I can't tell for sure.
Put it together and you end up with the following (untested) code:
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)
source to share