4

I need to set the user that is creating the post in the add view:

@login_required 
def add(request):
    if request.method == 'POST':
        form = BusinessForm(request.POST)
        form.user_id = request.user.id
        if form.is_valid():
            form.save()
            return HttpResponseRedirect(reverse('listing.views.detail'), args=(f.id))
    else:
        form = BusinessForm()
    return render_to_response('business/add.html', {'form':form},
        context_instance=RequestContext(request))

I assign the user id form.user_id = request.user.id but when saving, it still gives me an error Column user_id cannot be null

Am I doing something wrong? Thanks

EDIT:

I am excluding the user from the form in the model:

class BusinessForm(ModelForm):
    class Meta:
        model = Business
        exclude = ('user',)

Could that be causing the problem?? How can I work around this?

EDIT 2:

Edited my BusinessForm() class as suggested but did not work:

class BusinessForm(ModelForm):
    class Meta:
        model = Business
        exclude = ('user',)
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        return super(BusinessForm, self).__init__(*args, **kwargs)

    def save(self, *args, **kwargs):
        kwargs['commit']=False
        obj = super(BusinessForm, self).save(*args, **kwargs)
        if self.request:
            obj.user = self.request.user
        obj.save()

Business model

class Business(models.Model):
    name = models.CharField(max_length=200)
    user = models.ForeignKey(User, unique=False)
    description = models.TextField()
    category = models.ForeignKey(Category)
    address = models.CharField(max_length=200)
    phone_number = models.CharField(max_length=10)
    website = models.URLField()
    image = models.ImageField(upload_to='business_pictures',blank=True)
AlexBrand
  • 11,971
  • 20
  • 87
  • 132
  • I don't think that excluding a field should cause a problem, checkout [this](http://www.b-list.org/weblog/2006/nov/02/django-tips-auto-populated-fields/) for an example of how to achieve what you want – T I Dec 25 '11 at 23:25

2 Answers2

12

You don't have to use init or save overrides for this.

You're just setting an attribute on your form and the form doesn't do anything with it. It doesn't magically behave like a model instance (your form wouldn't have a user_id attribute).

Since your form is a ModelForm, you can simply call save on it with commit=False to get the unsaved instance, set the user, then call save on the instance.

 if request.method == 'POST':
    form = BusinessForm(request.POST)
    if form.is_valid():
        business = form.save(commit=False)
        business.user = request.user
        business.save()
Yuji 'Tomita' Tomita
  • 115,817
  • 29
  • 282
  • 245
  • 3
    You sure? That should not happen. Use the original ModelForm with only the Meta class and no init/save overrides. – Yuji 'Tomita' Tomita Dec 26 '11 at 01:08
  • Yes. Wouldn't this fail the validation? Since it does not have a user Id? – AlexBrand Dec 26 '11 at 01:23
  • 1
    The reason you've excluded the user is to bypass validation. No problem! – Yuji 'Tomita' Tomita Dec 26 '11 at 01:26
  • This comment needs to be posted somewhere in giant big letters. I wasted a good two hours trying to modify my `__init__` and `save` methods so I could simply set the user_id in the model to request.user.id. The logic is so obvious once you point it out. Thanks – Cole Feb 19 '13 at 21:36
  • 1
    @Cole, I added that you don't need to override init or save in the first line! – Yuji 'Tomita' Tomita Feb 19 '13 at 22:57
  • @Yuji Unfortunately, this particular StackOverflow answer does not appear as high in google search results, leading no doubt many people down a particularly unnecessary rat hole. What should have always been obvious to me is that when you `save(commit=False)`, you get a model object. An a model object is so much more useful than a form object, and so much easier to understand, because they are such a big part of Django. Forms seem to be more of an environmental hazard. Thanks again for your awesome answer. – Cole Feb 20 '13 at 14:29
0

this seems to be exactly what your looking for.

Community
  • 1
  • 1
T I
  • 9,785
  • 4
  • 29
  • 51
  • Tried and doesn't seem to work... I added the __init__ and save methods to the BusinessForm(ModelForm) class – AlexBrand Dec 26 '11 at 00:35
  • Is your user_id field related to the user model (https://docs.djangoproject.com/en/dev/ref/models/fields/#foreignkey), also in your `Business` model is the member user_id or user? – T I Dec 26 '11 at 00:54
  • added business model to question – AlexBrand Dec 26 '11 at 00:58
  • so then I think originally where you have form.user_id = request.user.id it should be form.user = request.user.id (maybe without the `.id`) – T I Dec 26 '11 at 01:04
  • @TomIngram the user model field would only exist on the model instance - not a django form. Setting attributes won't fail, but it won't do anything. – Yuji 'Tomita' Tomita Dec 26 '11 at 01:12
  • @YujiTomita hi and thanks, your comment has just made something click in my head. For clarity a call to an (un)committed save on a form returns it's 'supporting model', and a forms properties are only 'representative' of the 'supporting model' not the model object's actual properties? – T I Dec 26 '11 at 01:48
  • Hey Tom, calling save with commit or not on a ModelForm will always return a model instance. A form doesn't contain attributes that reflect the form / model fields at all. They are not represented as direct properties at all -- the form fields exist in form.fields and the validated data in form.cleaned_data. The forms will not know to do anything with attributes assigned to it e.g. form.fieldname = 'foobar'. I'm on a smartphone so excuse the formatting - hope that clears it up for you! – Yuji 'Tomita' Tomita Dec 26 '11 at 04:04