Search code examples
pythondjangomodelform

Django model form doesn't populate when instance=object is set


I'm trying to populate a ModelForm with existing data if it exists or create a new instance if not. I've read the django docs and several questions here on Stack Overflow but I can't figure out why my form doesn't populate with the existing data. I'm sure I'm missing something simple, any help would be appreciated.

In forms.py:

from django.forms import ModelForm, Textarea
from .models import Batch

class BatchForm(ModelForm):
    class Meta:
        model = Batch
        fields = ('recipe', 'date', 'original_gravity', 'final_gravity', 'gravity_units', 'notes')
        widgets = {'notes': Textarea(attrs={'cols': 40, 'rows': 10})}

in views.py: (notice the instance=batch argument, this should pre-populate the form correct?)

def batch_entry(request, batch_id):
    if int(batch_id) > 0:
        batch = get_object_or_404(Batch, id=batch_id)
        form = BatchForm(request.POST, instance=batch)
        context = {'BatchForm': form, 'batch': batch }
    else:
        form = BatchForm()
        context = {'BatchForm': form, 'batch': None }
    return render(request, 'logger/batch_entry.html', context)

the batch_entry.html template:

{% if batch.id > 0 %}
<h1>{{batch.date}}</h1>
<h3>{{batch.recipe}}</h3>
<form action="{% url 'logger:batch_entry' batch.id %}" method="post">
  {% csrf_token %}
  <table>
  {{BatchForm.as_table}}
  </table>
  <input type="submit" value="Submit">
</form>
{% else %}
<h1>New Batch</h1>
<form action="{% url 'logger:batch_entry' 0 %}" method="post">
  {% csrf_token %}
  <table>
  {{BatchForm.as_table}}
  </table>
  <input type="submit" value="Submit">
</form>
{% endif %}
<form action="{% url 'logger:index' %}" method="post">
  {% csrf_token %}
  <input type="submit" value="Return to Index">
</form>

Solution

  • Because you're also passing request.POST. That is supposed to contain the submitted data, which would naturally override the values already in the instance; but since you're doing that on a GET, the POST data is empty, so your form is displayed empty.

    Only pass request.POST into the form when the request is actually a POST.