0

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.

Community
  • 1
  • 1
cutteeth
  • 2,148
  • 3
  • 25
  • 45
  • Whats inside of `form.errors`? (btw `request.user` is the same result as your `User.objects.get(id..)` query) – Sayse Feb 15 '16 at 14:39

1 Answers1

2

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)
Tiago Martins Peres
  • 14,289
  • 18
  • 86
  • 145
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • `exclude = ['CreatedBy']` resolved this issue. I did override all these methods since I wanted just the validation part in `form_valid` and form manipulation happening in a more apt place. But I missed form exclude attributes.Thanks for pointing me the right direction :) – cutteeth Feb 15 '16 at 14:55