so after a user complained an error message, I discovered that my bank account field was not validating a length validator (WTForm). I disabled the length validator and implemented it myself. The error I therefore received was AttributeError: 'NoneType' object has no attribute 'length' and if I tried, AttributeError: 'NoneType' object has no attribute 'isdigit'. Clearly something was wrong. I have countless other forms all that behave perfectly, except this one. I cannot FOR THE LIFE of me, understand why this is. Everything seems to be setup properly. Here is my code:
Form
class onboard_form(FlaskForm):
full_name = StringField('Full Name (as it appears on your bank account)', validators=[
InputRequired(message='Please enter a valid name.')])
sort_codeone = StringField('Sort Code', validators=[(InputRequired(
message='Please enter a valid sort code.'))])
sort_codetwo = StringField('...', validators=[
InputRequired(message="Please enter a valid sort code.")])
sort_codethree = StringField('...', validators=[
InputRequired(message='Please enter a valid sort code.')])
account_number = StringField('Account Number', validators=[
InputRequired(message='Please enter a valid account number.')])
comfirm_account_number = StringField('Confirm Account Number', validators=[
InputRequired(message='Please enter a valid account number.')])
terms = BooleanField("I understand that I am responsible for providing a valid bank account.", validators=[
InputRequired(message='Please accept the terms and conditions.')])
def validate(self, extra_validators=None):
if super().validate(extra_validators):
# Check is sort code is valid
if not ((self.sort_codeone.data).isdigit() and (self.sort_codetwo.data).isdigit() and (self.sort_codethree.data).isdigit()):
self.sort_codeone.errors.append(
'Please enter a valid sort code.')
return False
if (((self.sort_codeone.data).length() != 2) or ((self.sort_codetwo.data).length() != 2) or ((self.sort_codethree.data).length() != 2)):
self.sort_codeone.errors.append(
'Please enter a valid sort code.')
return False
# Check account number is valid
if ((self.account_number.data).length != 8):
self.account_number.errors.append(
'Please enter a valid account number.')
return False
if ((self.account_number.data) != (self.comfirm_account_number).data):
self.comfirm_account_number.errors.append(
"Please enter the same value as above.")
else:
return True
Page that calls it
#app.route('/onboard', methods=["GET", "POST"])
#login_required
def onboard():
name = Users.get_by_id(session["user_id"]).first_name + " " + Users.get_by_id(session["user_id"]).last_name
form = onboard_form()
form.full_name.default = name
form.process()
if request.method == "POST":
print(form.sort_codeone)
if form.validate_on_submit():
sort_code = form.sort_code_1.data + "-" + \
form.sort_code_2.data + "-" + form.sort_code_3.data
Users.update(bank_full_name=form.full_name.data, bank_sort_code=sort_code,
bank_account_number=form.account_number.data).where(Users.id == session["user_id"]).execute()
return redirect('/newevent')
else:
print(form.errors)
return render_template('bank-details.html', form=form)
else:
return render_template('bank-details.html', form=form)
Html Template
{% extends "layout.html" %}
{% block title %}
Enter Bank Details
{% endblock %}
{% block main %}
<h3 class="py-5 text-4xl text-center">Onboard</h3>
<p class="text-center">To start adding events, please enter your bank details so that people can buy tickets from you!
</p>
<form id="form" action="/onboard" method="post" class="px-8 pt-6 pb-8 mb-4 rounded">
{{ form.csrf_token }}
<div class="text-center mb-4">
{{ form.full_name.label(class="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.full_name(class_="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5", placeholder="John Smith") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.full_name.errors[0] }}</p>
</div>
<div class="flex justify-center">
<div class="mb-4 px-2">
{{ form.sort_codeone.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codeone(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="67") }}
</div>
<div class="mb-4 px-2">
<p class="text-xl pt-8">-</p>
</div>
<div class="mb-4 px-2">
{{ form.sort_codetwo.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codetwo(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="34") }}
</div>
<div class="mb-4 px-2">
<p class="text-xl pt-8">-</p>
</div>
<div class="mb-4 px-2">
{{ form.sort_codethree.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.sort_codethree(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="75") }}
</div>
</div>
<p class="text-center mb-4 text-sm text-red-600 dark:text-red-500">{{ form.sort_codeone.errors[0] }}</p>
<div class="text-center mb-4 px-2">
{{ form.account_number.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.account_number(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="12345678") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.account_number.errors[0] }}</p>
</div>
<div class="text-center mb-4 px-2">
{{ form.comfirm_account_number.label(class_="block mb-2 text-sm font-medium text-gray-900") }}
{{ form.comfirm_account_number(class_="w-full bg-gray-50 border border-gray-300 text-sm leading-tight text-gray-700 border rounded appearance-none focus:ring-blue-500 focus:border-blue-500 block p-2.5", placeholder="12345678") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.comfirm_account_number.errors[0] }}</p>
</div>
<div class="py-3 flex items-center mb-4">
{{ form.terms(class_="w-4 h-4 text-blue-600 bg-gray-100 rounded border-gray-300 focus:ring-sky-500") }}
{{ form.terms.label(class="ml-3 text-sm font-medium text-gray-900") }}
<p class="mt-2 text-sm text-red-600 dark:text-red-500">{{ form.terms.errors[0] }}</p>
</div>
<br>
<div class="mb-6 text-center">
<button
class="text-white bg-sky-700 hover:bg-sky-800 focus:ring-4 focus:ring-sky-300 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center"
type="submit">
Confirm
</button>
</div>
</form>
{% endblock %}
Again, I have countless other forms and I don't understand what's wrong here!
I figured it out, I had an extra line:
form.process()
Why I honestly don't know how it got there but it wiped the form. Very strange
Related
enter code heremodels
class Transactions(models.Model):
user=models.ForeignKey(CustomUser,related_name='accounts',on_delete=models.CASCADE, blank=True) recipient_account_type = models.CharField(max_length=230) recipient_name = models.CharField(max_length=100) recipient_acount_number = models.PositiveIntegerField() recipient_routing_number = models.PositiveIntegerField() recipient_bank_name = models.CharField(max_length=200) recipient_swift_code = models.CharField(max_length=100) recipient_sending_amount = models.DecimalField(max_digits=15, decimal_places=2) transaction_date = models.DateTimeField(auto_now_add=True) transaction_ID =models.IntegerField(default=ID) description = models.CharField(max_length=1000)
forms
class TransactionForm(forms.ModelForm):
class Meta:
model = Transactions
fields = ['recipient_account_type','recipient_name','recipient_acount_number',
'recipient_routing_number','recipient_bank_name','recipient_swift_code','recipient_sending_amount','description',]
Widget = forms.TextInput(attrs={'autofocus':'autofocus','size':'40', 'font-size':'xx-large'})
views
#login_required(login_url='/login/')
def send(request):
posts =Transactions.objects.filter(user=request.user)
form = TransactionForm()
if request.method=="POST":
form = TransactionForm(request.POST, request.FILES)
if form.is_valid():
form.save()
return redirect('/success/')
else:
print(form.errors)
# messages.error(request, 'Failed, Resend')
context = {'form':form,'posts':posts}
return render(request, 'index_user/send-money.html', context)
**template**
{% extends 'about/user-base.html' %}
{% load crispy_forms_tags %}
{% load static %}
{% load humanize %}
{% block content %}
<!-- Content
============================================= -->
<div id="content" class="py-4">
<div class="container">
<div class="row mt-4 mb-5">
<div class="col-lg-11 mx-auto">
<div class="row widget-steps">
<div class="col-12 step active">
<div class="step-name">Details</div>
</div>
</div>
</div>
</div>
<h2 class="fw-400 text-center mt-3">Send Money</h2>
<p class="lead text-center mb-4">Send your money at anytime, anywhere in the world.</p>
<div class="row">
<div class="col-md-18 col-lg-7 col-xl-6 mx-auto bg-primary">
<div class="bg-white shadow-sm rounded p-3 pt-sm-4 pb-sm-5 px-sm-5 mb-4">
<hr class="mx-n3 mx-sm-n5 mb-4">
<div class="bg-white shadow-sm rounded p- pt-sm-5 pb-sm-5 px-sm-5 mb-4 bg-secondary">
<div class="text-center bg-primary p-4 rounded mb-4">
<h3 class="text-10 text-white fw-400">${{user.account_balance|intcomma}}</h3>
<p class="text-white">Available Balance</p>
{% comment %} Withdraw Full Amount </div> {% endcomment %}
<!-- Send Money Form
============================ -->
<p style="color: red; font-size:large">
{% if messages %}
{% for message in messages %}
{{message}}
{% endfor %}
{% endif %}
</p>
<center style="background-color: #007bff;">
<form id="form-send-money" method="POST" action="" class="bg-success" >
{% csrf_token %}
<div class="mb-3 pb-sm-5 px-sm-5">
{% comment %} <label for="withdrawto" class="form-label">Withdraw From</label> {% endcomment %}
<br>
{% comment %} <select id="withdrawto" class="form-select px-sm-4 pb-sm-1" name="">
<option value="">FNMB Bank - {{user.account_number}}</option>
</select> {% endcomment %}
</div>
<div id="id_long_desk" class="mb-3 px-sm-4 pb-sm-9">
<label for="emailID" class="form-label">Recipient Full Name</label>
<br>
{{form.recipient_name}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Account Number</label>
<br>
{{form.recipient_acount_number}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Bank Name</label>
<br>
{{form.recipient_bank_name}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Routing Number</label>
<br>
{{form.recipient_routing_number}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Swift Code</label>
<br>
{{form.recipient_swift_code}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Account Type</label>
<br>
{{form.recipient_account_type}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Recipient Sending Amount</label>
<br>
{{form.recipient_sending_amount}}
</div>
<div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Description</label>
<br>
{{form.description}}
</div>
{% comment %} <div class="mb-3 px-sm-4 pb-sm-1">
<label for="emailID" class="form-label">Fees</label>
<br>
$ {{form.fees}}
</div> {% endcomment %}
<!-- <p>Transfer Fees <span class="float-end"> 12.21 USD</span></p> -->
<hr>
<div class="d-grid"><button class="submit btn btn bg-white">Send</button></div>
<hr>
</form>
</center>
<!-- Send Money Form end -->
</div>
</div>
</div>
</div>
</div>
<!-- Content end -->
{% endblock %}
Have you checked whether your form is valid with something like the following?
if form.is_valid():
obj = form.save()
else:
# errror handling? debug with form.errors...
If your code does look like above, please add more info (like the form handling method as a whole)
Trying to create an app that saves sales in different sateges for my team(similar to an ecommerce)
however the form to add the account info is not saving the data...
I review different options and use formset as well no changes.
model.py
TYPE=(
('delegated','Delegated'),
('not_delegated','Not Delegated')
)
class Account(models.Model):
agent_profile=models.ForeignKey(AgentProfile, on_delete= CASCADE)
account_name=models.CharField(max_length=120)
opp_type=models.CharField(max_length=20, choices=TYPE, default='not_delegated')
bp_id=models.IntegerField()
mdm_id=models.CharField(max_length=50, null=True,blank=True)
AM=models.CharField(max_length=50,null=True,blank=True)
def __str__(self):
return str(self.agent_profile)
forms.py
from django.forms import ModelForm
from .models import Account
class AccountForm(ModelForm):
class Meta:
model=Account
fields=[
#'agent_profile',
'account_name',
'opp_type',
'bp_id',
'mdm_id',
'AM'
]
views.py
def confirm_account_create_view(request):
form=AccountForm(request.POST or None)
context = {
"form": form
}
next_ = request.GET.get('next')
next_post = request.POST.get('next')
redirect_path = next_ or next_post or None
if form.is_valid():
instance=form.save(commit=False)
agent_profile, agent_profile_created = AgentProfile.objects.new_or_get(request)
if agent_profile is not None:
opp_type = request.POST.get('delegate_opp', 'not_delegated_opp')
instance.agent_profile = agent_profile
instance.opp_type = opp_type
instance.save()
request.session[opp_type + "_opp_id"] = instance.id
print(opp_type + "_opp_id")
else:
print("Please verify Form")
return redirect("opps:confirm")
if is_safe_url(redirect_path, request.get_host()):
return redirect(redirect_path)
return redirect("opps:confirm")
urls.py (main app)
path('orders/confirm/account', confirm_account_create_view, name='create_account'),
form page(HTML)
{% csrf_token %}
{% if next_url %}
{% endif %}
{% if opp_type %}
<input type='hidden' name='opp_type' value='{{ opp_type }}' />
{% endif %}
{{ form.as_p }}
<button type='submit' class='btn btn-default'>Submit</button>
</form>
confirm page(HTML)
{% extends "base.html" %}
{% load static %}
{% block content %}
{{ object.order_id }} --{{object.opp}}
<div class="pb-9 mb-7 text-center border-b border-black border-opacity-5">
<h2 class="mb-7 lg:mt-6 text-3xl font-heading font-medium">Confirm Info</h2>
</div>
<h2 class="mb-7 lg:mt-6 text-3xl font-heading font-medium">Account</h2>
<div class='row'>
<div class="flex items-center justify-between py-4 px-10 mb-3 leading-8 bg-white bg-opacity-50 font-heading font-medium rounded-3xl">
{% if not object.delegated_opp %}
{% url "create_account" as confirm_account_create_view%}
{% include 'accounts/form.html' with form=delegated_form ext_url=request.build_absolute_uri action_url=confirm_account_create_view opp_type='not_delegated_opp' %}
</div>
<div class="flex items-center justify-between py-4 px-10 mb-3 leading-8 bg-white bg-opacity-50 font-heading font-medium rounded-3xl">
{% elif not object.not_delegated_opp %}
{% url "create_account" as confirm_account_create_view%}
{% include 'accounts/form.html' with form=delegated_form ext_url=request.build_absolute_uri action_url=confirm_account_create_view opp_type='not_delegated_opp' %}
</div>
</div>
{%else%}
<div>
<h2 class="mb-7 lg:mt-6 text-3xl font-heading font-medium">Order summary</h2>
<div class="flex items-center justify-between py-4 px-10 mb-3 leading-8 bg-white bg-opacity-50 font-heading font-medium rounded-3xl">
<span>Subtotal</span>
<span class="flex items-center text-xl">
<span class="mr-2 text-base">$</span>
<span>{{object.opp.subtotal}}</span>
</span>
</div>
<div class="flex items-center justify-between py-4 px-10 mb-3 leading-8 bg-white bg-opacity-50 font-heading font-medium rounded-3xl">
<span>Discount</span>
<span class="flex items-center text-xl">
<span class="mr-2 text-base">$</span>
<span>{{object.discount}}</span>
</span>
</div>
<div class="flex items-center justify-between py-4 px-10 mb-14 leading-8 bg-white font-heading font-medium rounded-3xl">
<span>Total</span>
<span class="flex items-center text-xl text-blue-500">
<span class="mr-2 text-base">$</span>
<span>{{object.total}}</span>
</span>
</div>
<a class="inline-block w-full py-5 lg:py-3 px-10 text-lg leading-6 lg:leading-7 text-white font-medium tracking-tighter font-heading text-center bg-blue-500 hover:bg-blue-600 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 rounded-xl" href="#">Save Opp</a>
</div>
</div>
</div>
<div class="md:w-96"><a class="block py-5 px-10 w-full text-xl leading-6 font-medium tracking-tighter font-heading text-center bg-white hover:bg-gray-50 focus:ring-2 focus:ring-blue-500 focus:ring-opacity-50 rounded-xl" href="#">Back to top</a></div>
</div>
</section>
{% endif %}
{% endblock content %}
I type AM by mistake instead of am at a model level and form level.
Once I changed it to :
am=models.CharField(max_length=50,null=True,blank=True)
It began to work properly
I know that this question have been asked many times and I already checked many solutions but can not find an explanation to the weird behavior of saving form in this case
as in production saving image is working on my pc and not in my colleagues, in local as well it is working if I change the position of the form save (more below, if more up it does not work)
here the related forms to the template I am working with:
class ProfilePageTitleForm(ModelForm):
class Meta:
model = ProfilePage
fields = [
"title",
]
class ProfilePageDetailsForm(ModelForm):
intro = forms.CharField(
required=True,
widget=forms.Textarea(
attrs={
"class": "max-w-md w-full bg-gray-100 border border-gray-200 "
"rounded-lg text-base outline-none focus:border-blue-600 p-4"
}
),
label=_("Personal introduction"),
help_text=_("maximum number of characters: 80 characters"),
max_length=80,
)
class Meta:
model = ProfilePage
fields = [
"avatar",
"school",
"location",
"intro",
]
here they are separated as I used the title in another template separately
related views
#login_required
def profile_details(request: HttpRequest, pk: int = None) -> HttpResponse:
profile = ProfilePage.objects.get(pk=pk)
user = profile.user
titleprofilepage_form = ProfilePageTitleForm(instance=profile)
profilepage_form = ProfilePageDetailsForm(instance=profile)
if user == request.user or request.user.has_perm("userprofile.manager_permissions"):
if request.method == "POST":
profilepage_form = ProfilePageDetailsForm(
request.POST, request.FILES, instance=profile
)
titleprofilepage_form = ProfilePageTitleForm(request.POST, instance=profile)
if (
profilepage_form.is_valid()
and titleprofilepage_form.is_valid()
):
titleprofilepage_form.save()
profilepage_form.save()
return redirect(profile.get_full_url())
else:
messages.error(
request,
_("You have no permissions to edit this page"),
)
return redirect("/")
context = {
"user": user,
"profilepage_form": profilepage_form,
"titleprofilepage_form": titleprofilepage_form,
}
return render(request, "account/profile_details.html", context)
here if I put profilepage_form.save() in the line upper, the image do not save
the related template
{% extends "base.html" %}
{% load i18n wagtailcore_tags static %}
{% block content %}
<h1 class="text-3xl font-bold mt-7 mb-9 lg:mt-14">{% translate "edit profile" %}</h1>
<form action="" method="post" enctype="multipart/form-data" novalidate>
{# using novalidate to cancel the browser validation and use our form validations #}
{% csrf_token %}
<label for="id_avatar" class="block text-sm font-bold mb-2">
{% translate "profile picture" %}
<span class="pl-2 text-pink-repeat">*</span>
</label>
<div class="flex items-center w-68 overflow-hidden">
<div id="avatar_image" class="w-24 h-24 rounded-half bg-cover bg-center flex-shrink-0" style="background-image:url({{ user.get_user_avatar }})"></div>
<label for="id_avatar" class="flex items-center h-8 px-4 mx-6 text-xs bg-gray-200 rounded-full text-blue-400 cursor-pointer hover:bg-gray-400 flex-shrink-0 w-34 text-center">
{% translate "upload image" %}
</label>
{{ profilepage_form.avatar }}
{% if profilepage_form.avatar.errors %}
<div class="text-red-700 px-4 py-3" role="alert">
<strong>{{ profilepage_form.avatar.errors|escape }}</strong>
</div>
{% endif %}
</div>
<label for="id_title" class="block text-sm font-bold mb-2 mt-10">
{% translate "nick name" %}
<span class="pl-2 text-pink-repeat">*</span>
</label>
{{ titleprofilepage_form.title }}
{% if titleprofilepage_form.title.errors %}
<div class="text-red-700 px-4 py-3" role="alert">
<strong>{{ titleprofilepage_form.title.errors|escape }}</strong>
</div>
{% endif %}
<label for="id_location" class="block text-sm font-bold mb-2 mt-10">
{% translate "address" %}
</label>
{{ profilepage_form.location }}
{% if profilepage_form.location.errors %}
<div class="text-red-700 px-4 py-3" role="alert">
<strong>{{ profilepage_form.location.errors|escape }}</strong>
</div>
{% endif %}
<label for="id_school" class="block text-sm font-bold mb-2 mt-10">
{% translate "what you want to do" %}
</label>
{{ profilepage_form.school }}
{% if profilepage_form.school.errors %}
<div class="text-red-700 px-4 py-3" role="alert">
<strong>{{ profilepage_form.school.errors|escape }}</strong>
</div>
{% endif %}
<label for="id_intro" class="block text-sm font-bold mb-2 mt-10">
{% translate "self introduction" %}
<span class="pl-2 text-pink-repeat">*</span>
</label>
{{ profilepage_form.intro }}
{% if profilepage_form.intro.errors %}
<div class="text-red-700 px-4 py-3" role="alert">
<strong>{{ profilepage_form.intro.errors|escape }}</strong>
</div>
{% endif %}
<span class="helptext block text-sm mt-2">{% translate "Maximum number of characters : 80" %}</span>
<input type="submit" class="button mt-8 flex items-center justify-center text-sm font-bold shadow-md btn-goblue hover:bg-blue-499 active:bg-blue-800 active:shadow-none h-10 w-32 cursor-pointer" value="{% translate 'save' %}" data-button="load">
</form>
{% block footer %}
{% include "footer.html" %}
{% endblock %}
{% endblock %}
{% block extra_js %}
{{ block.super }}
<script type="text/javascript" src="{% static 'js/account_registration.js' %}"></script>
{% endblock %}
my questions are:
1- why changing the order between titleprofilepage_form.save() and profilepage_form.save() in views.py affects the behavior of saving picture (as written now in the file, it saves the image in local)
2- why I was able to save the image on local, in production on my computer but not in my colleague's computer (already cleaned cache)
New Update:
through the comment of Iain Shelvington was able to understand the importance of order as the title form is overriding the profilepage form and used a unique form for the same model
about the difference in production it is because using a user who has a different picture in the different village which is the problem in profile.user.get_user_avatar, I am closing this issue as it has been resolved
I have a payment form that is made up of various elements.
Here my problem is that the card for a new stripe user isn't registered until after form submission.
I know that if my form has a newly added Address, I can use form.is_valid() but that doesn't apply if my address is one that is saved already. But is there a way I can set the card using stripe.PaymentMethod.list after the form is submitted, regardless of if the Django form is part of it?
form
<form method="POST" id="subscription-form" data-secret="{{client_secret}}">
{% csrf_token %}
<label class="block uppercase text-gray-600 text-xs font-bold mb-2">Payment Details</label>
{% if payment_methods %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="add-new-card"
value="add-new-card" onclick="addCard()" {%if payment_methods %} {%else%}checked="checked" {%endif%}
required>
<label class="form-check-label" for="add-new-card">
Add new payment method
</label>
<div id="new-card" style="display: none;">
<label class="block uppercase text-gray-600 text-xs mb-2" for="cardholder-name">
Name on Card
</label>
<input id="cardholder-name"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
value="{{customer.name}}" detype="text">
<!-- placeholder for Elements -->
<label class="block uppercase text-gray-600 text-xs mb-2" for="card-element">
Card Details
</label>
<div id="card-element"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-result"></div>
<div id="card-errors" class="my-2" role="alert"></div>
</div>
</div>
{% if saved_customer %}
{% for method in payment_methods %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="{{method.card}}"
value="{{method.id}}" onclick="hideCard()" {% if forloop.first %} checked="checked" {%endif%}>
<label class="form-check-label" for="{{method.card}}">
{{method.card.brand}} ending in {{method.card.last4}}
</label>
</div>
{% endfor %}
{% endif %}
{% else %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="payment-methods" id="add-new-card"
value="add-new-card" checked="checked"
required>
<label class="form-check-label" for="add-new-card">
Add new payment method
</label>
<div id="new-card">
<label class="block uppercase text-gray-600 text-xs mb-2" for="cardholder-name">
Name on Card
</label>
<input id="cardholder-name"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150"
value="{{customer.name}}" detype="text">
<!-- placeholder for Elements -->
<label class="block uppercase text-gray-600 text-xs mb-2" for="card-element">
Card Details
</label>
<div id="card-element"
class="mb-2 border-0 px-3 py-3 placeholder-gray-300 text-gray-600 bg-white rounded text-sm shadow focus:outline-none focus:ring w-full ease-linear transition-all duration-150">
<!-- A Stripe Element will be inserted here. -->
</div>
<div id="card-result"></div>
<div id="card-errors" class="my-2" role="alert"></div>
</div>
</div>
{% endif %}
<label class="block uppercase text-gray-600 text-xs font-bold mb-2">Address</label>
<div id="address-list">
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="addresses" id="new-address" value="new-address"
onclick="showAddress()" {%if addresses%} {%else%}checked="checked" {%endif%}>
<label class="form-check-label" for="new-address">
New Address
</label>
<span id="address-form"></span>
</div>
{% for address in addresses %}
<div class="form-check my-3 bg-gray-200 p-2 rounded-md">
<input class="form-check-input" type="radio" name="addresses" id="{{address.id}}"
value="{{address.id}}" onclick="hideAddress()" {% if forloop.first %} checked="checked"
{%endif%} required>
<label class="form-check-label" for="{{address.id}}">
{{address.name}} - {{address.line_1}}
</label>
</div>
{% endfor %}
</div>
<input type="hidden" id="email" name='email' value='{{customer.email}}'>
<div>
<p class="text-xs">By confirming, you agree that you will be charged immediately, and then monthly for
this product until cancelled</p>
<button id="submit" type="submit"
class="w-full mt-2 bg-blue-300 text-blue-900 font-medium rounded p-3">Confirm
and Pay</button>
</div>
</form>
view
#login_required
def subscription_new(request, product):
stripe.api_key = STRIPE_SECRET_KEY
title = "New Subscription for " + product
product = Product.objects.get(slug=product)
customer = Customer.objects.get(user=request.user.id)
addresses = Address.objects.filter(customer=customer)
current_day = datetime.date.today().day
# maintain order day in short months
if current_day > 28:
current_day = 1
stripe_amount = str(int(round(product.price, 2) * 100))
context = {
'title' : title,
'product' : product,
'customer' : customer,
'addresses' : addresses,
'current_day' : current_day,
'STRIPE_PUBLIC_KEY' : STRIPE_PUBLIC_KEY,
}
card = request.POST.get('payment-methods')
if customer.stripe_id:
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
context['saved_customer'] = True
context['payment_methods'] = payment_methods
else:
print('no stripe id ')
new_customer = stripe.Customer.create(name=customer.name, email=customer.email)
customer.stripe_id = new_customer.id
customer.save()
context['saved_customer'] = False
intent = stripe.SetupIntent.create(customer=customer.stripe_id)
client_secret = intent.client_secret
context['client_secret'] = client_secret
if request.method == 'POST':
print("method is post")
address = request.POST.get('addresses')
if address == 'new-address':
form = AddressForm(request.POST)
address = form.save(commit=False)
address.customer = customer
address.save()
else:
address = Address.objects.get(id=address)
if customer.stripe_id:
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
print("customer has id")
if card == "add-new-card":
payment_methods = stripe.PaymentMethod.list(
customer=customer.stripe_id,
type="card",
)
new_card = payment_methods.data[0]
# context['client_secret'] = client_secret
subscription = Subscription.objects.create(customer=customer, product=product, address=address, renewal_day=current_day, payment_method=new_card.id)
msg = 'Subscription created'
else:
subscription = Subscription.objects.create(customer=customer, product=product, address=address, renewal_day=current_day, payment_method=card)
msg = 'Subscription created'
messages.success(request, msg)
# If method is not post
else:
form = AddressForm()
context['form'] = form
return render(request, 'accounts/subscription_new.html', context)
Assuming AddressForm is a ModelForm, you can use it on an existing instance of a model as well:
address = Address.objects.get(id=address_id)
form = AddressForm(request.POST, instance=address)
Also, you can take other actions before saving the form. If you want the stripe payment method to be registered in order to save the form, register it first, then save the form.
If you want to customize the data stored on the address by AddressForm, just override the save method and modify self.instance before you call super().save().
Alternatively, just edit the Address object outside of the context of the form. There's nothing requiring database updates to happen inside a form save method
In the below form If I uncomment "Product" field my form is not working.I think there is something wrong with my html file. I am not including whole model code only the neccessary code.
lead/models.py
class Lead(models.Model):
description = models.TextField(blank=True, null=True)
assigned_to = models.ManyToManyField(User, related_name='lead_assigned_users')
account_name = models.CharField(max_length=255, null=True, blank=True)
tags = models.ManyToManyField(Tags, blank=True)
contacts = models.ManyToManyField(Contact, related_name="lead_contacts")
ctype = models.CharField(default=None,max_length=20, choices=TYPE, blank=True, null=True)
product = models.CharField(default=None,max_length=255, blank=False, null=True)
common/models.py
class Products(models.Model):
name = models.CharField(max_length=50,null=False,blank=False)
def __str__(self):
return self.name
lead/view.py
#login_required
def create_lead(request):
template_name = "create_lead.html"
if request.POST:
form = LeadForm(request.POST, request.FILES, assigned_to=users)
if form.is_valid():
lead_obj = form.save(commit=False)
lead_obj.created_by = request.user
lead_obj.save()
if request.POST.get('tags', ''):
tags = request.POST.get("tags")
splitted_tags = tags.split(",")
for t in splitted_tags:
tag = Tags.objects.filter(name=t)
if tag:
tag = tag[0]
else:
tag = Tags.objects.create(name=t)
lead_obj.tags.add(tag)
if request.POST.getlist('assigned_to', []):
lead_obj.assigned_to.add(*request.POST.getlist('assigned_to'))
assigned_to_list = request.POST.getlist('assigned_to')
if request.POST.getlist('products', []):
lead_obj.product.add(*request.POST.getlist('products'))
products = request.POST.getlist('products')
if request.POST.getlist('teams', []):
user_ids = Teams.objects.filter(id__in=request.POST.getlist('teams')).values_list('users', flat=True)
assinged_to_users_ids = lead_obj.assigned_to.all().values_list('id', flat=True)
for user_id in user_ids:
if user_id not in assinged_to_users_ids:
lead_obj.assigned_to.add(user_id)
current_site = get_current_site(request)
recipients = list(lead_obj.assigned_to.all().values_list('id', flat=True))
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
if request.FILES.get('lead_attachment'):
attachment = Attachments()
attachment.created_by = request.user
attachment.file_name = request.FILES.get(
'lead_attachment').name
attachment.lead = lead_obj
attachment.attachment = request.FILES.get('lead_attachment')
attachment.save()
if request.POST.get('status') == "converted":
account_object = Account.objects.create(
created_by=request.user, name=lead_obj.account_name,
email=lead_obj.email, phone=lead_obj.phone,
description=request.POST.get('description'),
website=request.POST.get('website'),
)
account_object.billing_address_line = lead_obj.address_line
account_object.billing_street = lead_obj.street
account_object.billing_city = lead_obj.city
account_object.billing_state = lead_obj.state
account_object.billing_postcode = lead_obj.postcode
account_object.billing_country = lead_obj.country
for tag in lead_obj.tags.all():
account_object.tags.add(tag)
if request.POST.getlist('assigned_to', []):
# account_object.assigned_to.add(*request.POST.getlist('assigned_to'))
assigned_to_list = request.POST.getlist('assigned_to')
current_site = get_current_site(request)
recipients = assigned_to_list
send_email_to_assigned_user.delay(recipients, lead_obj.id, domain=current_site.domain,
protocol=request.scheme)
account_object.save()
success_url = reverse('leads:list')
if request.POST.get("savenewform"):
success_url = reverse("leads:add_lead")
return JsonResponse({'error': False, 'success_url': success_url})
return JsonResponse({'error': True, 'errors': form.errors})
context = {}
context["lead_form"] = form
context["accounts"] = Account.objects.filter(status="open")
context["users"] = users
context["countries"] = COUNTRIES
context["status"] = LEAD_STATUS
context["source"] = LEAD_SOURCE
context["ctype"] = TYPE
context["product"] = Products.objects.all()
context["assignedto_list"] = [int(i) for i in request.POST.getlist('assigned_to', []) if i]
return render(request, template_name, context)
create_lead.html
<form id="lead_form" method="POST" action="" novalidate enctype="multipart/form-data">
<div class="overview_form_block row marl justify-content-center">
<div class="col-md-9">
<div class="card">
<div class="card-body">
<div class="card-title text-center">
{% if lead_obj %}EDIT{% else %}CREATE{% endif %} LEAD
</div>
<div class="row marl no-gutters">
<div class="col-md-4">
<div class="filter_col col-md-12">
<div class="form-group">
<div class="row">
<div class="filter_col col-md-6">
<label for="exampleInputEmail1" class="name" >First Name{% if lead_form.first_name.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.first_name }}
<span class="error error_message" id="error_id_first_name">{{ lead_form.first_name.errors }}</span>
</div>
<div class="filter_col col-md-6">
<label for="exampleInputEmail1" class="name" >Last Name{% if lead_form.last_name.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.last_name }}
<span class="error error_message" id="error_id_last_name">{{ lead_form.last_name.errors }}</span>
</div>
</div>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1" {% if request.POST.status == "converted" %} class="required" {% endif %}>Account Name{% if lead_form.account_name.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.account_name }}
<span class="error error_message" id="error_id_account_name">{{ lead_form.account_name.errors }}</span>
{% if error %}
<span class="error error_message" id="error_id_}">{{ error }}</span>
{% endif %}
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Title{% if lead_form.title.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.title }}
<span class="error error_message" id="error_id_title">{{ lead_form.title.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group ">
<label for="exampleInputEmail1">Phone{% if lead_form.phone.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.phone }}
<span class="error error_message" id="error_id_phone">{{ lead_form.phone.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group ">
<label for="exampleInputEmail1" class="required">Email Address{% if lead_form.email.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.email }}
<span class="error error_message" id="error_id_email">{{ lead_form.email.errors }}</span>
{% if error %}
<span class="error error_message" id="error_id_}">{{ error }}</span>
{% endif %}
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Attachment</label>
<input type="file" name="lead_attachment" id="lead_attachment">
{% if lead_obj.lead_attachment.count %}
{% for attachment in lead_obj.lead_attachment.all %}
<div id="attachment{{attachment.id}}" class="mt-2">
<a target="_blank" href="{{ attachment.attachment.url }}">{{ attachment.file_name }}</a>
{% if not attachment.created_by.role == 'ADMIN' or attachment.created_by.role == request.user.role %}
<a class="action btn primary_btn" onclick="remove_attachment({{attachment.id}})">X</a>
{% endif %}
</div>
{% endfor %}
{% endif %}
<span class="error"></span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Website{% if lead_form.website.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.website }}
<span class="error error_message" id="error_id_website">{{ lead_form.website.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1" >Description{% if lead_form.description.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.description }}
<span class="error error_message" id="error_id_description">{{ lead_form.description.errors }}</span>
</div>
</div>
{% if request.user.is_superuser or request.user.role == 'ADMIN' %}
<div class="filter_col col-12">
<div class="form-group">
<label for="id_sattus">Teams{% if lead_form.teams.field.required %}<span
class="error">*</span>{% endif %}</label>
{{ lead_form.teams }}
<span class="error" id="id__teams">{{ lead_form.teams.errors }}</span>
</div>
</div>
{% endif %}
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Assigned Users</label>
<select class="assigned_users form-control" name="assigned_to" multiple="multiple">
{% for user in users %}
<option value="{{user.id}}" {% if user in lead_obj.assigned_to.all or user.id in assignedto_list %} selected="" {% endif %}>{{user.email}}</option>
{% endfor %}
</select>
<span class="error error_message" id="error_id_assigned_to">{{ lead_form.assigned_to.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1"/>Status{% if lead_form.status.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.status }}
<span class="error error_message" id="error_id_status">{{ lead_form.status.errors }}</span>
</div>
</div>
</div>
<div class="col-md-4">
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1"/>Source{% if lead_form.source.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.source }}
<span class="error error_message" id="error_id_source">{{ lead_form.source.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1" >Address</label>
{{ lead_form.address_line }}
<span class="error error_message" id="error_id_address_line">{{ lead_form.address_line.errors }}</span>
</div>
{{ lead_form.street }}
<span class="error error_message" id="error_id_street">{{ lead_form.street.errors }}</span>
<div class="row" style="margin-top:10px;">
<div class="col-md-4">
{{ lead_form.city }}
<span class="error error_message" id="error_id_city">{{ lead_form.city.errors }}</span>
</div>
<div class="col-md-4">
{{ lead_form.state }}
<span class="error error_message" id="error_id_state">{{ lead_form.state.errors }}</span>
</div>
<div class="col-md-4">
{{ lead_form.postcode }}
<span class="error error_message" id="error_id_postcode">{{ lead_form.postcode.errors }}</span>
</div>
<div class="col-md-12" style="margin-top:10px;">
{{ lead_form.country }}
<span class="error error_message" id="error_id_country">{{ lead_form.country.errors }}</span>
</div>
</div>
</div>
<br>
<div class="filter_col col-12">
<div class="form-group">
<label>Tags</label>
<div class="txt-box-div" id="tag-div"><input type="text" name="tags" id="tags_1" value="{% for t in lead_obj.tags.all %}{{t.name}}, {% endfor %}" class="tags"/>
</div>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1"/>Type{% if lead_form.ctype.field.required %}<span class="error">*</span>{% endif %}</label>
{{ lead_form.ctype }}
<span class="error error_message" id="error_id_type">{{ lead_form.ctype.errors }}</span>
</div>
</div>
<div class="filter_col col-md-12">
<div class="form-group">
<label for="exampleInputEmail1">Products</label>
<select class="assigned_users form-control" name="products" multiple="multiple">
{% for pro in product %}
<option value="{{user.id}}" {% if pro in lead_obj.product.all %} selected="" {% endif %}>{{pro.name}}</option>
{% endfor %}
</select>
<span class="error error_message" id="error_id_products">{{ lead_form.product.errors }}</span>
</div>
</div>
</div>
<div class="col-md-12">
<div class="row marl buttons_row text-center form_btn_row">
<button class="btn btn-default save" type="submit" id="submit_btn">Save</button>
{% if not lead_obj %}
<button class="btn btn-success save savenew" type="submit">Save & New</button>
{% endif %}
Cancel
</div>
</div>
</div>
</div>
</div>`enter code here`
</div>
<input type="hidden" id="save_new_form" name="savenewform">
</div>
</form>
my ajax code
$('form#lead_form').ajaxForm({
type:'POST',
dataType:'json',
url: ".",
data:$('#lead_form').serialize(),
beforeSubmit: disableButton,
beforeSend: function() {
var percentVal = '0%';
bar.width(percentVal);
percent.html(percentVal);
},
uploadProgress: function(event, position, total, percentComplete) {
var percentVal = percentComplete + '%';
bar.width(percentVal);
if (percentVal == '100%'){
percent.html('Uploading ...')
}
else{
percent.html(percentVal);
}
},
success: function(data) {
if(data.error){
$('#progress_bar').hide()
$('.error_message').html('')
for (var key in data.errors) {
$('#error_id_'+key).html("<p>" + data.errors[key][0] + "</p>");
};
$('#submit_btn').removeAttr('disabled')
}
else{
window.location = data.success_url;
}
}
});
The form should be submitted successfully but, it's not working and not giving me an error.