Q:

Django ModelForm's field returns id instead of value

Here is my related models:
class Post(models.Model):
    subtitle = models.ForeignKey('Subtitle')

class Subtitle(models.Model):
      name = models.CharField(max_length=30)
      def __unicode__(self):
          return self.name

and modelform:
class AddLink(ModelForm):
      subtitle = forms.CharField(label='Subreddit')
      class Meta:
          model = Post
          fields = ('subtitle')

related view:
@login_required(login_url='/login/')
123 def edit_link(request, post_id):
124     get_post = Post.objects.get(id=post_id)
125     if request.method == 'POST':
126         form = AddLink(request.POST, instance=get_post)
127         if form.is_valid():
128             form.save()
129             return HttpResponseRedirect('/')
130     else:
131         form = AddLink(instance=get_post)
132 
133     context = { 'form': form, 'post': get_post, }
134     template_name = 'edit_post.html'
135     return render_to_response(template_name, context,
136             context_instance=RequestContext(request))

and template page:
  1 <form action="" method="post">
  2     {% csrf_token %}
  3     {{ form.as_p }}
  4     <input type="submit" value="save" />
  5 </form>

In this way ; in template , it returns id of subtitle field. not its name.
i want to serve subtitle name in a textbox. ModelChoiceField doesn't provide what i want.

A:

First, remove you're going to need to remove fields from your ModelForm definition. As it is no the data you want.
class AddLink(ModelForm):
  subtitle = forms.CharField(label='Subreddit')
  class Meta:
      model = Post

Then, you need to populate your initial form data.
@login_required(login_url='/login/')
def edit_link(request, post_id):
    get_post = Post.objects.get(id=post_id)
    if request.method == 'POST':
         form = AddLink(request.POST, instance=get_post)
         if form.is_valid():
             form.save()
             return HttpResponseRedirect('/')
     else:
         # this line changed
         form = AddLink(instance=get_post, initial={ 'subtitle': get_post.subtitle.name })     
     context = { 'form': form, 'post': get_post, }
     template_name = 'edit_post.html'
     return render_to_response(template_name, context,
             context_instance=RequestContext(request))

Also, you should probably add a save() method to your model.
def save(self, commit=True):
    post = super(AddLink, self).save(commit=False)
    subtitle_name = self.cleaned_data['subtitle']
    if post.subtitle:
        post.subtitle.name = subtitle_name
    else:
        post.subtitle = new Subtitle(name=subtitle_name)
    post.subtitle.save()
    post.save()
    return post

EDIT: made a change in code base on comment.

