Why Not
Why Not

Reputation: 611

Saving Django User in Form

I'm currently working on my first Django app, which allows registered users to submit content through a basic form.

It works thus far with one caveat: when the form is displayed, the user ("Author") is presented with a drop-down list of all users instead of automatically populating that field with the user's name. This is obviously not acceptable.

This goal is to have the registered user's name automatically populate the form. I've seen some various potential solutions to similar problems, but nothing that addresses anything this specific.

I attempted setting the Author field in the model to "unique=True," but that resulted in a database error when migrating it.

Any insight would be greatly appreciated:

Model:

class Story(models.Model):
    title = models.CharField(max_length=100)
    topic = models.CharField(max_length=50)
    copy = models.TextField()
    author = models.ForeignKey(User)
    zip_code = models.CharField(max_length=10)
    latitude = models.FloatField(blank=False, null=False)
    longitude = models.FloatField(blank=False, null=False)
    date = models.DateTimeField(auto_now=True, auto_now_add=True)   
    def __unicode__(self):
         return " %s" % (self.title)

Form:

class StoryForm(forms.ModelForm):
class Meta:
    model = Story

View:

@login_required
 def submit_story(request):
if request.method == "GET":
    story_form = StoryForm()
    return render_to_response("report/report.html",
                             {'form': story_form},
                              context_instance=RequestContext(request))
elif request.method =="POST":
    story_form = StoryForm(request.POST) 
    if story_form.is_valid():
        new_story = Story()
        new_story.title = story_form.cleaned_data["title"]
        new_story.topic = story_form.cleaned_data["topic"]
        new_story.copy = story_form.cleaned_data["copy"]
        new_story.author = request.user
        new_story.zip_code = story_form.cleaned_data["zip_code"]
        new_story.latitude = story_form.cleaned_data["latitude"]
        new_story.longitude = story_form.cleaned_data["longitude"]
        new_story.save()
        return HttpResponseRedirect("/report/all/")
    else:
        story_form = StoryForm()
        return render_to_response("report/report.html",
                                {'form': story_form},
                                 context_instance=RequestContext(Request))

EDIT: I think I found the relatively simple answer: I just removed the 'author" field from the form and kept the view the same. I was able to post under the registered user's name this way. I think this works, unless something I'm unaware of (which is plenty) is incorrect or bad protocol.

Upvotes: 1

Views: 279

Answers (1)

Nitzan Tomer
Nitzan Tomer

Reputation: 164357

I managed to do something similar:

Base class for all models who are associated with a user:

class UserOwnedModel(models.Model):
    user = models.ForeignKey(User, editable=True)

    class Meta:
        abstract = True

Base class for all forms who are associated with a user:

class UserOwnedForm(forms.ModelForm):
    exclude = ["user", ]

    def __init__(self, user, data=None, *arguments, **keywords):
        if data:
            data['user'] = user.id
            forms.ModelForm.__init__(self, data=data, *arguments, **keywords)

I'm not sure if it's the best solution (and will be glad for any input or suggestions) but it works for me. This of course completely removes the user field from the form, so if you need to display the user name, you'll have to play with the code.


EDIT

Also, instead of this:

new_story = Story()
new_story.title = story_form.cleaned_data["title"]
new_story.topic = story_form.cleaned_data["topic"]
new_story.copy = story_form.cleaned_data["copy"]
new_story.author = request.user
new_story.zip_code = story_form.cleaned_data["zip_code"]
new_story.latitude = story_form.cleaned_data["latitude"]
new_story.longitude = story_form.cleaned_data["longitude"]
new_story.save()

You can do this:

new_story = story_form.save()

EDIT 2

Something like this:

class Story(UserOwnedModel):
    title = models.CharField(max_length=100)
    topic = models.CharField(max_length=50)
    copy = models.TextField()
    zip_code = models.CharField(max_length=10)
    latitude = models.FloatField(blank=False, null=False)
    longitude = models.FloatField(blank=False, null=False)
    date = models.DateTimeField(auto_now=True, auto_now_add=True)   
    def __unicode__(self):
         return " %s" % (self.title)

class StoryForm(UserOwnedForm):
    class Meta:
        model = Story

@login_required
def submit_story(request):
    if request.method == "GET":
        story_form = StoryForm(user=request.user)
    ....
    elif request.method =="POST":
        story_form = StoryForm(data=request.POST, user=request.user)
        if story_form.is_valid():
            new_story = story_form.save()
            .....
        else:
            story_form = StoryForm(user=request.user)
            ....

I also changed my initial code a bit.

Upvotes: 2

Related Questions