0

I have an edit view for when a user wants to edit a Post:

def edit(request, id):
    post = get_object_or_404(Post, id=id)
    edit_form = PostForm(request.POST or None, instance=post)
    if edit_form.is_valid():
        instance = edit_form.save(commit=False)
        instance.save(update_fields=['content'])
        return HttpResponseRedirect('/')
    else:
        print(edit_form.errors)
        edit_form = PostForm(instance=post)
    context = {
        'edit_form': edit_form,
        'form_post': post
    }
    return render(request, 'edit.html', context)

When a user edits a Post, I only want them to be able to edit 1 field (content), so i've only rendered that form field in my template (pre-populated with the previous post.content. The other fields are just fields of the object (not a form/can't be edited).

...
<form method="post" action="" enctype="multipart/form-data">{% csrf_token %}    

<h1>{{ form_post.title }}</h1>

<p>{{ edit_form.content}}</p>

<p>{{ form_post.category }}</p>

</form>
...

and here is my Post model:

class Post(models.Model):
    ...
    title = models.TextField(max_length=76)
    content = models.TextField(null=False, default='')
    category = models.CharField(max_length=20, choices=CATEGORY_CHOICES, default='1')

When the edit form is submitted, form_errors returns this:

<ul class="errorlist">
    <li>title<ul class="errorlist"><li>This field is required.</li></ul></li>
    <li>category<ul class="errorlist"><li>This field is required.</li></ul</li>
</ul>

Why is this happening? Doesn't:

instance = edit_form.save(commit=False)
instance.save(update_fields=['content'])

keep the fields from the orignal Post and just change the content field?

Zorgan
  • 8,227
  • 23
  • 106
  • 207
  • why not make the other two fields hidden for the user or if you want to show it to them make them readonly. – Ajay Gupta Feb 28 '17 at 11:31
  • How does readonly work? Do I have to make a seperate Form to make it readonly? – Zorgan Feb 28 '17 at 11:34
  • apply the readonly on form fields using widgets – Ajay Gupta Feb 28 '17 at 11:38
  • http://stackoverflow.com/questions/324477/in-a-django-form-how-do-i-make-a-field-readonly-or-disabled-so-that-it-cannot – Ajay Gupta Feb 28 '17 at 11:40
  • So I have to create a seperate form just to edit the form? Why can't I just grab the Post object, then tell django I only want to edit 1 field and keep the other fields the same? – Zorgan Feb 28 '17 at 11:41
  • The way you tell Django which fields are to be edited is by changing the form class. If the value is missing from the post request, then the form will be invalid - the form doesn't know which fields you rendered on the template. It's too late to set the list of fields to update when you save the form - Django has already validated it by then. – Alasdair Feb 28 '17 at 12:12
  • Yeah that makes sense, thanks. – Zorgan Feb 28 '17 at 12:13

1 Answers1

1

If you only want some of the fields to be editable, you should set fields in your model form. If you use PostForm in another view and cannot edit fields, then create a new form.

class EditPostForm(forms.ModelForm):
    class Meta:
        model = Post
        fields = ['content']

You can subclass PostForm if you prefer:

class EditPostForm(PostForm):
    class Meta(PostForm.Meta):
        fields = ['content']

Then update your edit view to use EditPostForm instead of PostForm.

Alasdair
  • 298,606
  • 55
  • 578
  • 516
  • This is for editing an already existing object, so I need `fields = ['title', 'content', 'category']` as they're all required when the user initially creates the Post. – Zorgan Feb 28 '17 at 11:46
  • If you already use `PostForm` to create the object, then create a new form, e.g. `EditPostForm` for editing the object. – Alasdair Feb 28 '17 at 12:09