I have an issue with a form with a Select input. This input is used to select a user in a list. The list should only contain user from the group currently used.
I found a solution, however I am not completely sure of what am I doing in the form definition (I do not fully understand how works the def __init__
part). And of course, my code is not working : I obtain the right form, with the choices I need, however if a submit data, it's not saved in the database.
I have been able to check if the form is valid (it is not), the error is the following :
Category - Select a valid choice. That choice is not one of the available choices.
(I have the same error for the user field). I can't find my way in this, so if you can help, would be very appreciated!
My models:
class Group(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class User(AbstractUser):
groups = models.ManyToManyField(Group)
current_group = models.ForeignKey(Group, on_delete=models.SET_NULL,blank = True , null = True, related_name="current_group")
class Category(models.Model):
name = models.CharField(max_length=100)
groups = models.ManyToManyField(Group)
def __str__(self):
return self.name
class Expanses(models.Model):
date = models.DateTimeField()
amount = models.DecimalField(decimal_places=2, max_digits=12)
category = models.ForeignKey(Category, on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
comment = models.CharField(max_length=500)
def __str__(self):
return self.amount
My form:
class CreateExpanseForm(forms.ModelForm):
class Meta:
model = Expanses
fields = ['date', 'amount', 'category', 'user','comment']
widgets={'date':DateInput(attrs={'placeholder':'Date', 'class':'form-input', 'type':'date'}),
'amount':TextInput(attrs={'placeholder':'Amount', 'class':'form-input', 'type':'text'}),
'category':Select(attrs={'placeholder':'Category', 'class':'form-select', 'type':'text'}),
'user':Select(attrs={'placeholder':'user', 'class':'form-select', 'type':'text'}),
'comment':TextInput(attrs={'placeholder':'comment', 'class':'form-input', 'type':'text'}),}
def __init__(self, *args, **kwargs):
user_choices = kwargs.pop('user_choices', None)
category_choices = kwargs.pop('category_choices', None)
super().__init__(*args, **kwargs)
if user_choices:
self.fields['user'].choices = user_choices
if category_choices:
self.fields['category'].choices = category_choices
My view:
def SummaryView(request):
createExpanseForm = CreateExpanseForm(user_choices = [(user.username, user.username) for user in request.user.current_group.user_set.all()],
category_choices = [(category.name, category.name) for category in request.user.current_group.category_set.all()])
if request.method == "POST":
if 'createExpanse' in request.POST:
createExpanseForm = CreateExpanseForm(user_choices = [(user.username, user.username) for user in request.user.current_group.user_set.all()],
category_choices = [(category.name, category.name) for category in request.user.current_group.category_set.all()],
data=request.POST)
if createExpanseForm.is_valid():
expanse = createExpanseForm.save()
if expanse is not None:
expanse.group = request.user.current_group
expanse.save()
else:
messages.success(request, "Error!")
context = {'createExpanseForm':createExpanseForm}
return render(request, 'app/summary.html', context)