8

Let's say I have a simple model:

class Contact(models.Model):
    owner = models.ForeignKey(User, editable=False)
    first_name = models.CharField(max_length=255,)
    last_name = models.CharField(max_length=255,)
    email = models.EmailField()

I would like to set owner (request.user, logged in user) for the object automatically when it is created. I've searched a lot of different options but most of them are related to how you do it in admin side and other ones just don't work for me. I tried this for example http://blog.jvc26.org/2011/07/09/django-automatically-populate-request-user and then I've tried many ways to override save method or some kind of pre_save signal stuff. Nothing seems to do the trick, I just get an error

IntegrityError at /new
null value in column "owner_id" violates not-null constraint

What is the right way to do that? I know that this is simple think to do but I just can't find the way to do it.

...EDIT... My create view looks like this:

class CreateContactView(LoginRequiredMixin, ContactOwnerMixin, CreateWithInlinesView):
    model = models.Contact
    template_name = 'contacts/edit_contact.html'
    form_class = forms.ContactForm
    inlines = [forms.ContactAddressFormSet]

    def form_valid(self, form):
        obj = form.save(commit=False)
        obj.owner = self.request.user
        obj.save()
        return HttpResponseRedirect(self.get_success_url())

    def get_success_url(self):
        return reverse('contacts-list')

    def get_context_data(self, **kwargs):
        context = super(CreateContactView, self).get_context_data(**kwargs)
        context['action'] = reverse('contacts-new')
        return context

That is just one way I tried to solve that problem so far. I found that solution from http://blog.jvc26.org/2011/07/09/django-automatically-populate-request-user

m5seppal
  • 1,186
  • 3
  • 15
  • 31
  • 1
    Where is the code that produced the error? – Bibhas Debnath Mar 03 '14 at 16:08
  • @m5seppal show the view code where you save the model – almalki Mar 03 '14 at 16:20
  • I forgot to say that I'm using class based views, I edited the question – m5seppal Mar 03 '14 at 16:30
  • I manged to get this work when I changed my view to use django's generic CreateView instead of CreateWithInlinesView. I posted a new [question](http://stackoverflow.com/questions/22155302/django-integrityerror-at-new-null-value-in-column-owner-id-violates-not-null) about that problem. Thank you guys from your help! – m5seppal Mar 04 '14 at 01:15

3 Answers3

6

Assuming you are using ContactForm ModelForm:

def contact(request):
    if request.method == 'POST':
        form = ContactForm(request.POST)
        if form.is_valid():
            contact = form.save(commit=False)
            contact.owner = request.user
            contact.save()
            return HttpResponseRedirect('/thanks/')
    else:
         # do stuff
almalki
  • 4,595
  • 26
  • 30
0

please post the exact code of what you tried.

If your view requires that a user is logged in, make sure it is enforced. This can be done by using the @login_required decorator

If you are in a view, and using a ModelForm to create the Contact, pass the commit=False kwarg to save method (like the example in the link you posted). This will keep the contact from being created until you assign the owner = request.user.

Since a logged in user is only available within the context of a request, just make sure that you are setting owner attribute it the views when creating a new Contact

dm03514
  • 54,664
  • 18
  • 108
  • 145
  • That's exactly what I've tried but I still get that error: null value in column "owner_id" violates not-null constraint It looks like form_valid is never called. Do you have any idea what I should do for that? – m5seppal Mar 03 '14 at 16:45
  • @well also make sure that request has a user. You could do this with the `@login_required` decorator. I'm assuming the user is not logged in that's why `request.user` is `None` – dm03514 Mar 03 '14 at 17:19
  • I'm using that LoginRequiredMixin, it should do the same thing. It's from the django-braces. – m5seppal Mar 03 '14 at 19:01
0

The problem is that the default implementation of the form_valid method sets self.object, which is then used by get_success_url to determine where to redirect to.

If you replace your local obj variable with self.object, you should be fine:

def form_valid(self, form):
    self.object = form.save(commit=False)
    self.object.owner = self.request.user
    self.object.save()
    return HttpResponseRedirect(self.get_success_url())

I find a quick check of the original implementation for side-effects on the Classy Class-Based Views Web site, or the Django source-code on GitHub useful for spotting any side effects I need to reproduce in a subclass implementation.

georgebrock
  • 28,393
  • 13
  • 77
  • 72