Trying to Edit Existing Post; Can't Get Form to Display

37 views
Skip to first unread message

DF

unread,
May 18, 2012, 5:22:27 PM5/18/12
to django...@googlegroups.com
Newbie question. I have an application where registered users can submit stories. The posting and display works great but I wanted users to have the ability to edit any of their stories. The goal would be for a user to find a list of their stories on their profile page, choose one that they would like to edit, and then retrieve the form they initially submitted with the current information filled in to make the necessary edits.

I composed a view, url and template to achieve this. The page displays, the story number from the url appears in the address bar but the form is nowhere to be found. I can't figure out if what I'm doing is an error in the template or the view (I'm thinking the former but can't be sure).

Here is the model:

class Story(models.Model):
    objects = StoryManager()
    title = models.CharField(max_length=100)
    topic = models.CharField(max_length=50)
    copy = models.TextField()
    author = models.ForeignKey(User, related_name="stories")
    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)
    pic = models.ImageField(upload_to='pictures', blank=True)
    caption = models.CharField(max_length=100)

    def __unicode__(self):
        return " %s" % (self.title)

Here is the form:

class StoryForm(forms.ModelForm):
    class Meta:
        model = Story
        exclude = ('author',)

    def __init__(self, author, *args, **kwargs):
        super(StoryForm, self).__init__(*args, **kwargs)
        self.author = author


    def save(self, commit=True):
        self.instance.author = self.author
        return super(StoryForm, self).save(commit)

Here are the submit and edit views:

@login_required
def submit_story(request):
    story_form = None
    if request.method =="POST":
        story_form = StoryForm(request.user, data=request.POST, files=request.FILES)
        if story_form.is_valid():
            new_story = story_form.save(commit=True)
            return HttpResponseRedirect("/report/all/")

    return render_to_response("report/report.html", {'form': story_form or StoryForm(request.user) }, context_instance=RequestContext(request))

@login_required
def edit_story (request, story_id):
    story_form = None
    if story_id:
        story_form = get_object_or_404(Story, pk=story_id)
        if story_form.author != request.user:
            return HttpResponse("You can only edit your own stories!")

    if request.method == 'POST':
        story_form = StoryForm(request.user, data=request.POST, files=request.FILES)
        if story_form.is_valid():
            story_form.save(commit=True)
            return HttpResponse("/profiles/user_profile")
    #else:
        #story_form = StoryForm(instance=story_form)

    return render_to_response('report/storyedit.html', {'form': story_form or StoryForm(request.user) }, context_instance=RequestContext(request))


The urls:

    url(r'^report/$', 'project.report.views.submit_story', name='write_story'),
    url(r'^detail/(?P<story_id>\d*)/edit/$', 'project.report.views.edit_story', )

And the edit template:

{% extends 'base.html' %}
{% load report %}
{% block page_title %}Edit Story{% endblock %}
{% block headline %}Edit Story{% endblock %}
{% block content %}

    <div class="row">
        <div class="span12">
            <div class="page-header">
                <h2>Edit your story, <a href="{% url profiles_profile_detail user.username %}">{{user.username}}!</a></h2>
            </div>

            <form action="" class="form form-horizontal" method="post" enctype="multipart/form-data">

                <fieldset>
                    {% generic_form form %}
                    <div class="form-actions">
                        <input type="submit" value="Submit" class="btn btn-primary"/>
                    </div>
                </fieldset>
            </form>
        </div>
    </div>
{% endblock %}


This is likely a stupid error but hours of scratching my head led me to seek some guidance. Any help welcomed and appreciated. Trying very hard to learn.


Jonathan Baker

unread,
May 18, 2012, 5:37:44 PM5/18/12
to django...@googlegroups.com
The lines:
    #else:
        #story_form = StoryForm(instance=story_form)
...appear to be handling the GET request, and they're commented out.



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/arNGcd_FldoJ.
To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.



--
Jonathan D. Baker
Developer
http://jonathandbaker.com

DF

unread,
May 18, 2012, 6:52:27 PM5/18/12
to django...@googlegroups.com
Thanks. This worked:

else:
        story_form = StoryForm(request.user, instance=story_form)


One problem: it just adds a new version of the story instead of updating the previous version. So "editing" just creates multiple versions instead of actually editing the existing story.

Is there a way to remedy this?
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

Jonathan Baker

unread,
May 18, 2012, 7:01:25 PM5/18/12
to django...@googlegroups.com
Hmmm... I don't think you need to pass 'request.user' in as an argument. Also, you want to be sure that the 'instance' you pass as an argument to the model form is the model record you want to update. For instance:

def edit_story(request, story_id)
    story = get_object_or_404(Story, pk=story_id)
    if request.method == 'POST':
        story_form = StoryForm(request.POST, request.FILES, instance=story)
        if story_form.is_valid():
            story_form.save()
            return HttpResponseRedirect("/profiles/user_profile")
    else: # GET request
        story_form = StoryForm(instance=story)
    return render_to_response('report/storyedit.html', {'form': story_form}, context_instance=RequestContext(request))



To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/pct7yxxnacEJ.

To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

DF

unread,
May 18, 2012, 7:19:04 PM5/18/12
to django...@googlegroups.com
Thanks. I get this error using that code:

TypeError at /report/detail/30/edit/

__init__() takes at least 2 arguments (1 given)
This is referring to this line:

      story_form = StoryForm(instance=story)

I added a "story_id" argument to this, which brought up the form, but when I submitted it, it returned the form with errors listing all the fields as empty.

This is far trickier than I thought.

Jonathan Baker

unread,
May 19, 2012, 11:41:51 AM5/19/12
to django...@googlegroups.com
OK, I spent some more time with this. Firstly, I've included a different way to populate the author field. With this update, the ModelForm only needs the following:

# forms.py
class StoryForm(forms.ModelForm):
    class Meta:
        model = Story
        exclude = ('author',)

Next I simplified your views a little bit. When dealing with the .save() method of a ModelForm, commit=True is the default. This allows you to use commit=False, and then manually adjust attributes of the object, and then save it when you're done. This is a great opportunity to save the author field.

# views.py
@login_required
def submit_story(request):
    if request.method =="POST":
        story_form = StoryForm(request.POST, request.FILES)
        if story_form.is_valid():
            new_story = story_form.save(commit=false)
            new_story.author = request.user
            new_story.save()
            return HttpResponseRedirect("/report/all/")
    else: # GET request
        story_form = StoryForm()
    return render_to_response("report/report.html", {'form': story_form}, context_instance=RequestContext(request))

@login_required
def edit_story(request, story_id)
    story = get_object_or_404(Story, pk=story_id, author=request.user)
    if request.method == 'POST':
        story_form = StoryForm(request.POST, request.FILES, instance=story)
        if story_form.is_valid():
            story_form.save()
            return HttpResponseRedirect("/profiles/user_profile")
    else: # GET request
        story_form = StoryForm(instance=story)
    return render_to_response('report/storyedit.html', {'form': story_form}, context_instance=RequestContext(request))

I hope this helps a little.
Jonathan


To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/NSVmlvziOvMJ.

To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

DF

unread,
May 19, 2012, 7:04:25 PM5/19/12
to django...@googlegroups.com
Perfect! That worked!

Thank you so much! I was stumped. Your revisions were much simpler and easy to understand as well. I really appreciate when I can learn something, especially a more straightforward process that is less complex and achieves the same desired results.

Thank you, again!

Jonathan Baker

unread,
May 19, 2012, 7:20:15 PM5/19/12
to django...@googlegroups.com
You're welcome. The simple and easy to understand code is one of the main reasons I switched to Python/Django from PHP/Drupal :D Cheers.

To view this discussion on the web visit https://groups.google.com/d/msg/django-users/-/LLOsJ_b89-kJ.

To post to this group, send email to django...@googlegroups.com.
To unsubscribe from this group, send email to django-users...@googlegroups.com.

For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

bruno desthuilliers

unread,
May 21, 2012, 7:47:33 AM5/21/12
to Django users
On May 19, 5:41 pm, Jonathan Baker <jonathandavidba...@gmail.com>
wrote:

Just a note about best practises:

>
> # views.py

(snip)

>             return HttpResponseRedirect("/report/all/")

Better to use named urls and django.core.urlresolvers.reverse, this
avoids quite a lot of pain and trouble when you have to change your
urls schemes.

My 2 cents...

DF

unread,
May 21, 2012, 2:04:04 PM5/21/12
to django...@googlegroups.com
Thanks for that insight. It's always good to reinforce best practices for newcomers like myself.
Reply all
Reply to author
Forward
0 new messages