I have a formset that will not save. When I print the error to python, it shows:
<tr>
<th><label for="id_account">Account:</label></th>
<td>
<ul class="errorlist"><li>This field is required.</li></ul>
<select name="account" class="mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50" required id="id_account">
<option value="" selected>---------</option>
<optgroup label="Cash and Equivalents">
<option value="8b0a698b-c1cb-4eb8-b50c-dd7033207c19">Chase</option>
<option value="e5250016-76ba-42a5-a4db-d450e4b05c05">Discover</option>
<option value="3a920dc2-225f-4fa6-b67d-303e4107c658">Wells Fargo</option>
</optgroup>
<optgroup label="Investments">
<option value="c30d4b2e-2ca9-4bb2-a4ea-198699b4d408">Vanguard</option>
<option value="499fadc6-f5ce-4c13-9c4a-06e1394c34c4">Fidelity</option>
</optgroup>
<optgroup label="Retirement Accounts">
<option value="fe55b367-9f39-440f-98aa-ac49fe7299ef">Fidelity 401(k)</option>
<option value="18eb4069-a883-4229-8ad3-2342eb39a845">Price IRA</option>
</optgroup>
<optgroup label="Other Items">
<option value="51f400ac-f21b-43c3-917c-703ceb146429">Vehicles</option>
</optgroup>
</select>
</td>
</tr>
<tr>
<th><label for="id_date">Date:</label></th>
<td>
<ul class="errorlist"><li>This field is required.</li></ul>
<input type="date" name="date" class="mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50" required id="id_date">
</td>
</tr>
<tr>
<th><label for="id_amount">Amount:</label></th>
<td>
<ul class="errorlist"><li>This field is required.</li></ul>
<input type="number" name="amount" class="mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50" required step="0.01" id="id_amount">
</td>
</tr>
My models look like this:
from django.db import models
from django.core.validators import MaxValueValidator, MinValueValidator
import uuid
class Category(models.Model): # categories are used to organize what an account is for (cash, debts, investments, etc.)
CATEGORTY_TYPE_CHOCIES = (
('Asset', 'Asset'),
('Liability', 'Liability'),
)
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, primary_key=True)
category_type = models.CharField(max_length=9, choices=CATEGORTY_TYPE_CHOCIES, null=False, blank=False) # is this category an asset or liability
category_name = models.CharField(null=False, blank=False, max_length=255, unique=True)
category_description = models.TextField(null=True, blank=True)
sort_code = models.IntegerField(null=False, blank=False, unique=True, validators=[MinValueValidator(0), MaxValueValidator(300)])
active = models.BooleanField(default=True) # is this category still actively being used
def __str__(self):
return str(self.category_name)
class Account(models.Model):
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, primary_key=True)
category = models.ForeignKey(Category, on_delete=models.PROTECT, null=False, blank=False) # what category does this account belong under
account_name = models.CharField(null=False, blank=False, max_length=255, unique=True)
account_description = models.TextField(null=True, blank=True)
active = models.BooleanField(default=True) # is this account still actively being used
def __str__(self):
return str(self.account_name)
class NetWorthEntry(models.Model): # point in time entry of an accounts value
id = models.UUIDField(default=uuid.uuid4, unique=True, editable=False, primary_key=True)
account = models.ForeignKey(Account, on_delete=models.PROTECT, null=False, blank=False) # what account does this entry belong under
date = models.DateField(null=False, blank=False) # what date was this entry for
amount = models.DecimalField(max_digits=12, decimal_places=2, null=False, blank=False) #how much is the account on the date for the entry
class Meta:
constraints = [
models.UniqueConstraint(fields=['account', 'date'], name='unique_account_date')
]
def __str__(self):
return str(self.account.account_name + " - " + str(self.date))
My form looks like this:
from django import forms
from django.db.models import Q
from django.forms import ModelForm
from .models import Category, Account, NetWorthEntry
from cashflow.functions import GroupedModelChoiceField
class SingleNetWorthEntryForm(ModelForm):
account = GroupedModelChoiceField(queryset=Account.objects.filter(Q(active=True) & Q(category__active=True)).order_by('category__sort_code', 'account_name'), choices_groupby='category', widget=forms.Select(attrs={'class': 'mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50', 'required': True}), label='Account')
class Meta:
model = NetWorthEntry
fields = [
'account',
'date',
'amount',
]
labels = {
'account': 'Account',
'date': 'Date',
'amount': 'Amount',
}
widgets = {
'account': forms.Select(attrs={'class': 'mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50', 'required': True}),
'date': forms.DateInput(attrs={'type':'date', 'class': 'mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50', 'required': True}),
'amount': forms.NumberInput(attrs={'class': 'mb-5 w-full px-3 py-3 border-2 border-blue-500 rounded focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50', 'required': True}),
}
My view looks like this:
@login_required
def NetWorthGroupEntryCreate(request):
context = {}
active_accounts = Account.objects.filter(Q(active=True) & Q(category__active=True)).order_by('category__sort_code', 'account_name') # only show/allow accounts/categories that are active in net worth entry form
initial = []
todays_date = datetime.today().strftime('%Y-%m-%d')
for account in active_accounts:
initial.append({'account': account, 'date': todays_date})
GroupEntryFormSet = formset_factory(SingleNetWorthEntryForm, extra=0)
formset = GroupEntryFormSet(initial=initial)
if request.method == 'POST':
form = SingleNetWorthEntryForm(request.POST)
if form.is_valid():
form.save()
return reverse('networth-entries')
context['formset'] = formset
return render(request, 'networth/group-entry-create.html', context)
My template looks like this:
{% extends 'base.html' %}
{% load static %}
{% block content %}
<section class="pt-10">
<div class="mb-10">
<h1 class="text-4xl text-center">Create a New Net Worth Group Entry</h1>
</div>
<div class="flex justify-center">
<form method="POST">
{% csrf_token %}
{{ formset.as_p }}
<button class="px-6 py-3 font-medium text-white bg-blue-500 hover:bg-blue-600 rounded transition duration-200" type="submit">Create Net Worth Entry</button>
</form>
</div>
</section>
{% endblock content %}
When I try to submit the formset, it just reloads the page becuase the “form.is_valid()” is not true. However, I am confused why it is not valid. When I print the “request.POST” to python, it shows:
QueryDict: {
"csrfmiddlewaretoken": [
"uTFNG3nA5FgUvAmCxVaisod5yHHT7E2o0JU67Cm2NHiJS7QjEDVnr0RFWvW4qIBn"
],
"form-TOTAL_FORMS": ["16"],
"form-INITIAL_FORMS": ["16"],
"form-MIN_NUM_FORMS": ["0"],
"form-MAX_NUM_FORMS": ["1000"],
"form-0-account": ["8b0a698b-c1cb-4eb8-b50c-dd7033207c19"],
"form-0-date": ["2024-07-07"],
"form-0-amount": ["12"],
"form-1-account": ["e5250016-76ba-42a5-a4db-d450e4b05c05"],
"form-1-date": ["2024-07-07"],
"form-1-amount": ["12"],
"form-2-account": ["3a920dc2-225f-4fa6-b67d-303e4107c658"],
"form-2-date": ["2024-07-07"],
"form-2-amount": ["12"],
"form-3-account": ["be97cac3-fa3d-493f-b913-a1a8dd3a6a86"],
"form-3-date": ["2024-07-07"],
"form-3-amount": ["12"],
"form-4-account": ["68f59857-c35f-4789-aeda-67524c5bb803"],
"form-4-date": ["2024-07-07"],
"form-4-amount": ["12"],
"form-5-account": ["0b902375-f3de-4b8d-97a6-0ab0c0190b72"],
"form-5-date": ["2024-07-07"],
"form-5-amount": ["12"],
"form-6-account": ["488ee534-ee68-4531-9b21-e7e2993766d3"],
"form-6-date": ["2024-07-07"],
"form-6-amount": ["12"],
"form-7-account": ["842fda74-49f6-4ab1-9c75-32ef6173110d"],
"form-7-date": ["2024-07-07"],
"form-7-amount": ["12"],
"form-8-account": ["5356957d-46e4-4534-8b03-73739c7cf257"],
"form-8-date": ["2024-07-07"],
"form-8-amount": ["12"],
"form-9-account": ["c30d4b2e-2ca9-4bb2-a4ea-198699b4d408"],
"form-9-date": ["2024-07-07"],
"form-9-amount": ["12"],
"form-10-account": ["499fadc6-f5ce-4c13-9c4a-06e1394c34c4"],
"form-10-date": ["2024-07-07"],
"form-10-amount": ["12"],
"form-11-account": ["fe55b367-9f39-440f-98aa-ac49fe7299ef"],
"form-11-date": ["2024-07-07"],
"form-11-amount": ["12"],
"form-12-account": ["18eb4069-a883-4229-8ad3-2342eb39a845"],
"form-12-date": ["2024-07-07"],
"form-12-amount": ["12"],
"form-13-account": ["34628569-c19a-4cdc-8ef4-3cca4fb2f7a3"],
"form-13-date": ["2024-07-07"],
"form-13-amount": ["12"],
"form-14-account": ["fbb3ecc0-1d4e-417c-9fa0-5aaa83976862"],
"form-14-date": ["2024-07-07"],
"form-14-amount": ["12"],
"form-15-account": ["51f400ac-f21b-43c3-917c-703ceb146429"],
"form-15-date": ["2024-07-07"],
"form-15-amount": ["12"],
}
This shows that the request contains all the forms I am submitting (16 in total) and that none are missing as the error at the top of this post says.
Any help would be appreciated. Thank you