I've looked through a bunch of the other posts - but I can't find anything quite fitting to my scenario. I've got a bit of data that is coming across in the POST but then when I save the form - the data is not appearing in the database.
I'm a bit perplexed as to why this is and I've tried various things, but none of them really seem to apply to my situation. Most have to do with the data not being posted, my data is posted, it's just not saving.
I've got the following model:
class Payment(models.Model):
METHODS = (
("Cash", "Cash"),
("Check", "Check"),
("Credit Card", "Credit Card")
)
amount = models.DecimalField(decimal_places=2, max_digits=6)
method = models.CharField(
max_length=15,
choices=METHODS,
default="Credit Card"
)
stripe_id = models.CharField(max_length=255, blank=True, null=True)
check_number = models.IntegerField(blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
Here is my PaymentForm:
class PaymentForm(forms.ModelForm):
method = forms.CharField(
max_length=25,
widget=forms.TextInput(attrs={
"class": "form-control",
"readonly": "True",
})
)
amount = forms.DecimalField(
decimal_places=2,
max_digits=6,
widget=forms.TextInput(attrs={
"class": "form-control",
"readonly": "True",
})
)
stripe_id = forms.CharField(
widget=forms.HiddenInput(),
required=False
)
check_number = forms.IntegerField(
widget=forms.TextInput(attrs={"class": "form-control"}),
required=False
)
class Meta:
model = Payment
fields = (
'amount',
'method',
'stripe_id',
'check_number',
)
def clean_check_number(self):
method = self.cleaned_data["method"]
check_number = self.cleaned_data["check_number"]
if method == "Check" and not check_number:
raise forms.ValidationError("Check number is required.")
Here is my view.py function that relates to the POST:
if request.method == "POST":
# Create a copy of the POST data so we can input data for CC payments
post_data = request.POST.copy()
# Set the PaymentForm with the copied data (muteable)
# required for some of the stripe stuff we do
payment_form = PaymentForm(post_data)
if 'stripeToken' in request.POST:
# This is wrapped in extensive try/catch in reality but I left
# it out for brevity
charge = stripe.Charge.create(
amount=stripe_cost,
currency="usd",
description="Payment",
source=request.POST["stripeToken"],
receipt_email=request.POST["stripeEmail"],
)
# add things to the form that aren't there
# from the stripe reply
payment_form.data['method'] = "Credit Card"
payment_form.data['stripe_id'] = charge["id"]
# This part works fine
if payment_form.is_valid():
# either a non-stripe payment
# or the next step after the stripe stuff is don
payment_form.save(commit=False)
print(payment_form.data)
payment = payment_form.save()
# The data saves to the DB, but the check_number is empty!
messages.success(request, "Thank you for your payment!")
return redirect("my_app:index")
That print statement after the form is valid prints out like this:
<QueryDict: {'csrfmiddlewaretoken': ['3blahblahblah'], 'amount': ['9.10'], 'method': ['Check'], 'check_number': ['123455'], 'stripe_id': ['']}>
The issue I'm having is this: when a user selects Check as payment and saves the payment (with a check number) the check number isn't saving to the database.
As we can see, the request.POST data shows all the data there (including check number) - but in the database the check_number is not being stored when the .save() is running.
What might make that happen and how do I ammend that?
check_number = forms.IntegerField( .... )from the form and you just use the default model form implementation of the field?check_numberstill comes across inrequest.POST- but does not save to the database.blank=True, null=Truein the model and then create a run a new migration? Besides that I have no idea...