I am trying to assign currently logged in user as an attribute to a field of a modelform instance using generic views. I have referred to this SO post and did override post
method but it was giving me an error that CreatedBy field was required. Also I have gone through mro
on ccbv many times. View as below.
class PostCreate(LoginRequiredMixin, CreateView):
model = Post
form_class = PostForm
success_message = "Post Updated"
success_url = '/home/'
def get_form(self, form_class=None):
"""
Returns an instance of the form to be used in this view.
"""
form = super(PostCreate, self).get_form(form_class)
form.instance.CreatedBy=User.objects.get(id=self.request.user.id)
return form
def get_initial(self):
"""
Returns the initial data to use for forms on this view.
"""
self.initial = {'CreatedBy': User.objects.get(id=self.request.user.id)}
return self.initial.copy()
def get_form_kwargs(self):
"""
Returns the keyword arguments for instantiating the form.
"""
kwargs = {
'initial': self.get_initial(),
'prefix': self.get_prefix(),
}
if self.request.method in ('POST', 'PUT'):
kwargs.update({
'data': self.request.POST,
'files': self.request.FILES,
})
return kwargs
The reason I did override all these methods is to check the availability of initial dict in every method. It is available in every method but still form validation fails. But I think its better not to set values in get_initial(self)
since I do not prepopulate form fields with existing data of any saved object, rather I want to update a field of an initialized form with User object of logged in user
. I have gone through flow of control in ipdb
but enden up with same error.
ipdb> form.initial={'CreatedBy':User.objects.get(id=request.user.id)}
ipdb> form.fields['CreatedBy']=User.objects.get(id=request.user.id)
ipdb> form.instance.CreatedBy=User.objects.get(id=request.user.id)
ipdb> form.is_valid()
False
ipdb> form.instance.CreatedBy
<User: userone>
ipdb> form.fields['CreatedBy']
<User: userone>
ipdb> form.initial
{'CreatedBy': <User: userone>}
Please notice that I am not looking for a manipulated form_valid(self)
method.
I am caught up with this for hours. Any help is much appreciated.
The reason that created_by is still required is because you have not excluded it from the form itself; you need to do that in PostForm.
class PostForm(forms.ModelForm):
class Meta:
exclude = ['created_by']
As for assigning it automatically, the docs on the editing views have a specific section describing exactly how to do this; you override form_valid()
:
def form_valid(self, form):
form.instance.created_by = self.request.user
return super(PostCreate, self).form_valid(form)