You should ALWAYS validate your form on the server side, client side validation is but a convenience for the user only.
That being said, Django forms has a variable form.errors which shows if certain form fields were incorrect.
{{ form.name_of_field.errors }} can give you each individual error of each field that's incorrectly filled out. See more here:
http://docs.djangoproject.com/en/dev/topics/forms/
Answer from AlbertoPL on Stack Overflowpython - Form validation in django - Stack Overflow
How to validate form field in django? - Stack Overflow
Tutorial: Django Form Validation Guide - Show & Tell - Django Forum
python - Django Form validation overview (quick!) - Stack Overflow
Videos
You should ALWAYS validate your form on the server side, client side validation is but a convenience for the user only.
That being said, Django forms has a variable form.errors which shows if certain form fields were incorrect.
{{ form.name_of_field.errors }} can give you each individual error of each field that's incorrectly filled out. See more here:
http://docs.djangoproject.com/en/dev/topics/forms/
There's a pluggable Django app (django-ajax-forms) that helps validate forms on the client side through JavaScript. But as AlbertoPL says, use client side validation only as a usability measure (e.g. telling a user that his desired username is already taken without reloading the registration page). There are all kind of ways to sidestep client side validation, in most cases as simple as deactivating JavaScript.
Generally speaking: presume all data coming from the outside as faulty until validated.
class Place_A_Bid_Form(forms.Form):
listing = forms.CharField(widget=forms.TextInput(attrs={"type":"hidden"}))
bid = forms.IntegerField(widget=forms.NumberInput(attrs={"class":"form-control"}),
min_value=1)
def __init__(self,biggestBid=0 *args, **kwargs):
super().__init__(*args, **kwargs)
self.biggestBid = biggestBid
def clean_bid(self):
bid = self.cleaned_data["bid"]
if bid < self.biggestBid:
raise ValidationError("""New bid shouldn't be less than starting bid, or
if any bids have been placed then new bid
should be greater than current biggest bid""")
return bid
and then in views.py:
def place_a_bid(request):
if request.method == "POST":
dict = Bid.objects.filter(user=user).aggregate(Max("amount"))
form = Place_A_Bid_Form(biggestBid=dict['amount__max'], data=request.POST)
user = User.objects.get(username=request.user.username)
if form.is_valid():
data = form.cleaned_data
user_obj = User.objects.get(username=request.user.username)
listing_obj = Listing.objects.get(title=data["listing"])
Bid.objects.update_or_create(
user=user_obj,
listing=listing_obj,
amount=data["bid"]
)
return redirect(listing_obj)
Django's IntegerField [Django-doc] can validate a minimum value without any extra logic, you can set the .min_value and add a validator with:
from django.core.validators import MinValueValidator
class Place_A_Bid_Form(forms.Form):
listing = forms.CharField(widget=forms.TextInput(attrs={'type': 'hidden'}))
bid = forms.IntegerField(widget=forms.NumberInput(attrs={'class':'form-control'}))
def __init__(self, *args, **kwargs, min_bid=0):
super().__init__(*args, **kwargs)
bid = self.fields['bid']
min_bid += 1
bid.min_value = min_bid
bid.validators.add(MinValidator(min_bid))
so then you only need to pass the min_bid to the form:
from django.contrib.auth.decorators import login_required
@login_required
def place_a_bid(request):
biggest_bid = Bid.objects.filter(user=request.user).aggregate(
min_bid=Max('amount')
)['min_bid'] or 0
if request.method == 'POST':
form = Place_A_Bid_Form(request.POST, min_bid=biggest_bid)
if form.is_valid():
data = form.cleaned_data
listing_obj = Listing.objects.get(title=data['listing'])
Bid.objects.update_or_create(
user=request.user,
listing=listing_obj,
amount=data['bid']
)
return redirect(listing_obj)
else:
form = Place_A_Bid_Form(min_bid=biggest_bid)
return render(request, 'app_name/name-of-template.html', {'form': form})
This also construct a form in case of a GET request with the biggest bidding as minimum bid. This will also add this as min="biggest-bid" in the HTML so the browser can validate this. This can thus also validate the bid already at client side before submitting the form, but will also properly validate the form at the server side.
It might however be better to pass the listing not through the form, but as a URL parameter.
Note: You can limit views to a view to authenticated users with the
@login_requireddecorator [Django-doc].