Django form validation is not working. It only prints the following message:
form is not valid!
I am a Django beginner and I am having trouble figuring out why this is happening.
mycode in form.py:
efrom django import forms
from django.contrib.auth.models import User
from django.core.exceptions import ValidationError
from django.forms.widgets import CheckboxSelectMultiple
from blog.models import Category
from wsgiref.validate import validator
class PostForm(forms.Form):
title = forms.CharField(max_length = 100, min_length= 1,)
slug = forms.SlugField(allow_unicode=True)
message = forms.CharField(widget = forms.Textarea)
banner = forms.ImageField()
category = forms.ModelChoiceField(queryset=Category.objects)
authors = forms.ModelChoiceField(queryset=User.objects,
widget=CheckboxSelectMultiple)
def clean(self):
cleaned_data = super(PostForm, self).clean()
slug = cleaned_data['slug']
if not "sepehr" in slug:
raise forms.ValidationError("here we have some errors !")
return cleaned_data
and my code in views:
class HoemView(generic.TemplateView):
template_name = 'blog2/create.html'
def get(self, request):
form = PostForm()
context = {
'form':form
}
return render(request, self.template_name, context)
def post(self, request):
form = PostForm(request.POST, request.FILES)
if form.is_valid():
return HttpResponse('form is valid!')
return HttpResponse('form is not valid!')
All you are seeing is 'form is not valid!' because that is all your view is returning in the HttpResponse.
Change the last line from:
return HttpResponse('form is not valid!')
to:
return HttpResponse(form.errors)
That should show you what your errors are.
Related
Creating a chained drop down following a tutorial. Everything works fine but it is throwing an unnecessary validation error.
It is a basic 3 field form creating a person object with name, country and city.
Views.py
from django.shortcuts import render, redirect, get_object_or_404
from .forms import CustomerForm
from .forms import PersonCreationForm
from .models import Person, City
def store(request):
form = CustomerForm()
context = {'form': form}
return render(request, 'store/store.html', context)
def cart(request):
form = CustomerForm()
context = {'form': form}
return render (request, 'store/cart.html', context)
def checkout(request):
form = CustomerForm()
context = {'form': form}
return render(request, 'store/checkout.html', context)
def signup(request):
context = {}
return render(request, 'store/signup.html', context)
def home(request):
if request.method == 'POST':
form = CustomerForm(request.POST)
if form.is_valid():
pass # does nothing, just trigger the validation
else:
form = CustomerForm()
return render(request, 'shop.html', {'form': form})
def person_create_view(request):
form = PersonCreationForm()
if request.method =='POST':
form = PersonCreationForm(request.POST)
if form.is_valid():
form.save()
return redirect('person_add')
return render(request, 'store/ho.html', {'form': form})
def person_update_view(request, pk):
person = get_object_or_404(Person, pk = pk)
form = PersonCreationForm(instance = person)
if request.method == 'POST':
form = PersonCreationForm(request.POST, instance=person)
if form.is_valid():
form.save()
return redirect('person_change', pk = pk)
return render(request, 'store/ho.html', {'form': form})
#ajax
def load_cities(request):
country_id = request.GET.get('country_id')
cities = City.objects.filter(country_id = country_id)
return render(request, 'store/city_dropdown_list_options.html',{'cities':cities})
Forms.py
from django.forms import ModelForm
from .models import Customer, Person, City
from django import forms
class CustomerForm(ModelForm):
class Meta:
model = Customer
fields = '__all__'
class PersonCreationForm(forms.ModelForm):
class Meta:
model = Person
fields = '__all__'
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['city'].queryset = City.objects.none()
if 'country' in self.data:
try:
country_id = int(self.data.get('country'))
self.fields['city'].queryset = City.objects.filter(country_id = country_id)
except(ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['city'].queryset = self.instance.country.city_set.order_by('name')
In forms.py line 14 where it says-
self.fields['city'].queryset = City.objects.none()
this line is throwing a validation error when I try to submit the form. In the tutorial they add the if/else argument and that solves the problem and error goes away.
error: "Select a valid choice. That choice is not one of the available choices"
In my case the error still shows up. If I ignore it and re select the city and submit, it works just fine.
It is almost like having a pause at that line and the system suddenly realizes that there is more code.
How do I fix this problem. Appreciate any help.
I'm trying to dynamically set the limit_value of the build-in MinValueValidator inside a Django 3.1 ModelForm. The below code works for a fixed limit_value of 10 (see line 21 in views.py).
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class Bid(models.Model):
listing = models.ForeignKey(Listing, on_delete=models.CASCADE, related_name="bids")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="bids")
bid = models.DecimalField(decimal_places=2, max_digits=9)
views.py
from django.contrib.auth import authenticate, login, logout
from django.db import IntegrityError
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
from django.urls import reverse
from django import forms
from .models import User, Listing, Category, Bid
from django.db.models import Max
from decimal import Decimal, DecimalException
from django.core.validators import MaxValueValidator, MinValueValidator
from django.core.exceptions import ValidationError
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(10)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user})
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
However when I try passing a variable via 'my_arg' to the NewBidForm's init method during instantiation of the ModelForm, I get the following error messages:
KeyError: 'my_arg'
List item AttributeError: 'NewBidForm' object has no attribute '_errors'
Below is the modified code in views.py
views.py
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
widgets = {
'user': forms.HiddenInput(),
'listing': forms.HiddenInput(),
}
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['user'].show_hidden_initial=True
self.fields['listing'].show_hidden_initial=True
self.fields['bid'].validators=[MinValueValidator(my_arg)]
def clean(self):
if 'user' in self.changed_data or 'listing' in self.changed_data:
raise forms.ValidationError('Non editable field have changed!')
return self.cleaned_data
def index(request):
listings = Listing.objects.all()
return render(request, "auctions/index.html", {
"listings" : listings,
})
def listing(request, listing_id):
if request.method == 'POST':
data = request.POST
form = NewBidForm(data)
if form.is_valid():
form.save()
return HttpResponseRedirect(reverse("index"))
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
else:
listing = Listing.objects.get(pk=listing_id)
bids = Bid.objects.filter(listing=listing)
if bids:
highest_bid = bids.aggregate(Max('bid'))['bid__max']
else:
highest_bid = listing.starting_bid
form = NewBidForm(initial={'listing':listing,'user':request.user}, my_arg=12)
return render(request, "auctions/listing.html", {
"listing" : listing,
"highest_bid" : highest_bid,
"form" : form
})
Can anyone tell me how to pass a variable to the init method inside the ModelForm during instantiation?
An alternative solution for changing the limit_value of the build in MinValueValidator at runtime would also be acceptable. However, i don't like to redefine fromfields in the ModelForm.
BR, Konrad
Below code examples show the answer to my question.
Model form class
class NewBidForm(forms.ModelForm):
class Meta:
model = Bid
fields = '__all__'
def __init__(self, *args, **kwargs):
my_arg = kwargs.pop('my_arg')
super(NewBidForm, self).__init__(*args, **kwargs)
self.fields['bid'].validators=[MinValueValidator(my_arg)]
Then every time a form object is instantiated make sure to pass in the my_variable like so:
form = NewBidForm(my_arg=my_variable)
My mistake was to instantiate the form at two locations in my code but only passing the argument in one of the instances.
I
from django import forms
from .models import Blog
I just rewrite code this point,
from ↓:
# class BlogPost(forms.ModelForm):
# class Meta:
# model = Blog
# fields = ['title', 'body']
to ↓:
class BlogPost(forms.Form):
email = forms.EmailField()
files = forms.FileField()
url = forms.URLField()
words = forms.CharField(max_length=200)
max_number = forms.ChoiceField(choices=[('1','one'), ('2','two'),('3','three')])
and views.py file is here ↓:
from django.shortcuts import render, get_object_or_404, redirect
from .models import Blog
from django.utils import timezone
from .form import BlogPost
from django.views.decorators.http import require_http_methods
# Create your views here.
def home(request):
blogs = Blog.objects #쿼리셋
return render(request, 'home.html', {'blogs'`enter code here`:blogs})
def detail(request, blog_id):
details = get_object_or_404(Blog, pk=blog_id)
return render(request, 'detail.html', {'details':details})
def new(request):
return render(request, 'new.html')
def create(request):
blog = Blog()
blog.title = request.GET['title']
blog.body = request.GET['body']
blog.pub_date = timezone.datetime.now()
blog.save()
return redirect('/blog/'+str(blog.id)) #이 URL로 넘기세요 처리된 정보를
def blogpost(request):
if request.method =='POST':
form = BlogPost(request.POST)
if form.is_valid():
post = form.save(commit=False)
# post.pub_date = timezone.now()
post.save()
return redirect('home')
else:
form = BlogPost()
return render(request, 'newblog.html',{'form':form})
I don't know why I only rewrite 'form.py' file, but vscode program says "The view blogapp.views.blogpost didn't return an HttpResponse object. It returned None instead."
what should I do?? help..
def blogpost(request):
if request.method =='POST':
form = BlogPost(request.POST)
if form.is_valid():
post = form.save(commit=False)
# post.pub_date = timezone.now()
post.save()
return redirect('home')
else:
form = BlogPost()
return render(request, 'newblog.html',{'form':form})
You don't have a return statement on here due to your if statement and indentation.
Write it like:
def blogpost(request):
if request.method =='POST':
form = BlogPost(request.POST)
if form.is_valid():
post = form.save(commit=False)
# post.pub_date = timezone.now()
post.save()
return redirect('home')
else:
form = BlogPost()
return render(request, 'newblog.html',{'form':form})
And it should work.
I am new to django, I migrated my models, the database is working fine, i can see the data that I added by the manage.py shell. But I cant add Data from my webApp. When I wrote text on the fields and press the submit button it gave me this error NOT NULL constraint failed: sms_post.author_id
Thanks for helping..
models.py files
from django.db import models
from django.contrib.auth.models import User
THE_GENDER = [
("Monsieur", "Monsieur"),
("Madame", "Madame")
]
class Post(models.Model):
name = models.CharField(max_length=100)
email = models.CharField(max_length=100)
gender = models.CharField(max_length=8, choices=THE_GENDER)
number = models.CharField(max_length=100)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.name
forms.py files
from django import forms
from .models import Post
from crispy_forms.helper import FormHelper
class post_form(forms.ModelForm):
def __init__(self, *args, **kwargs):
super(post_form, self).__init__(*args, **kwargs)
self.helper = FormHelper(self)
class Meta:
model = Post
fields = ["name", "email", "gender", "number"]
views.py files
from django.shortcuts import render
from django.http import HttpResponse
from .forms import post_form
from django.contrib.auth.decorators import login_required
#login_required
def home(request):
form = post_form(request.POST or None)
if form.is_valid():
form.save()
context = {
"form": form
}
return render(request, "sms/home.html", context)
You did not set the author of the instance in your for to a User object. You can do this with:
from django.shortcuts import redirect
#login_required
def home(request):
if request.method == 'POST':
form = post_form(request.POST)
if form.is_valid():
form.instance.author = request.user
form.save()
return redirect('name-of-view')
else:
form = post_form()
context = {
'form': form
}
return render(request, 'sms/home.html', context)
In order to implement the Post/Redirect/Get pattern [wiki], in case of a successful POST request, you should make a redirect, for example to the same view. You thus can here replace 'name-of-view' with the name of a view to redirect to.
I am making a form using Django 2.0.x and Python 3.6 and I am getting an error
I'm not sure what's going on, can someone help me out? Thanks!
Product/forms.py
from django import forms
from .models import Product
class ProductForm(forms.ModelForm):
title = forms.CharField(label='',
widget=forms.TextInput(attrs={"placeholder": "Your title"}))
description = forms.CharField(
required=False,
widget=forms.Textarea())
class Meta:
model = Product
fields = [
'title',
'description',
]
Product/views.py
from django.shortcuts import *
from django.http import *
from .models import Product
from .forms import ProductForm
import hashlib
# Create your views here.
def home_view(request,slug,*args,**kwargs):
form= ProductForm(request.POST or None)
try:
productobject=Product.objects.get(id=1)
except Product.DoesNotExist:
raise Http404
if form.is_valid():
newProduct=Product.objects.create(
title = "jose",
description=ProductForm.cleaned_data.get["description"]
)
if newProduct:
return HttpResponseRedirect("/)
else:
newProduct = ProductForm()
context= {
"sampletext": "text",
"form": form,
"productobject":productobject,
}
return render(request, "home.html",context)
The code is giving me this error
type object 'ProductForm' has no attribute 'cleaned_data'
You fetch the cleaned_data from the ProductForm class, not from the form object that is an instance of ProductForm.
You can thus fix it by using form instead, like:
def home_view(request,slug,*args,**kwargs):
form= ProductForm(request.POST or None)
try:
productobject=Product.objects.get(id=1)
except Product.DoesNotExist:
raise Http404
if form.is_valid():
newProduct=Product.objects.create(
title = "jose",
description=form.cleaned_data.get["description"]
)
if newProduct:
return HttpResponseRedirect("/")
else:
newProduct = ProductForm()
context= {
"sampletext": "text",
"form": form,
"productobject":productobject,
}
return render(request, "home.html",context)
But that being said, the workflow is not idiomatic. For example if newProduct will always succeed, regardless whether this is a valid newProduct or not. The Product.objects.create(..) however can raise an exception. A more idiomatic workflow is:
def home_view(request,slug,*args,**kwargs):
try:
productobject=Product.objects.get(id=1)
except Product.DoesNotExist:
raise Http404
if request.method = 'POST':
form = ProductForm(request.POST)
if form.is_valid():
form.instance.title = "jose"
form.save()
return redirect('home') # name of the view
else:
form = ProductForm()
context= {
"sampletext": "text",
"form": form,
"productobject":productobject,
}
return render(request, "home.html",context)