Django form is not valid - django

I am trying to submit a form and it will not pass as is_valid in the view.
The form uses forms.Modelforms which I do not have a lot of experience with.
I checked {{ form.errors }} in the template but didn't get anything back.
I appreciate the time and expertise
Form
class AddSubcategory(forms.ModelForm):
class Meta:
model = Subcategory
fields = ['category']
subcategory_name = forms.CharField(max_length=255)
View
#login_required
#locationed
def add_subcategory(request, location):
subcat_form = AddSubcategory(request.POST)
if subcat_form.is_valid():
submitted_subcat_name = subcat_form.cleaned_data['subcategory_name']
selected_cat = subcat_form.cleaned_data['category']
_, was_created = Subcategory.objects.get_or_create(name=submitted_subcat_name, category=selected_cat)
return HttpResponseRedirect(reverse('manage_cat_subcat', args=(location.slug,)))
else:
cat_form = AddCategory()
subcat_form = AddSubcategory()
return render(request, 'inventory/manage_cat_subcat.html', {'location': location,'cat_form': cat_form,'subcat_form':subcat_form})
Template (form)
<form class="form-inline" action="{% url 'add_subcategory' location.slug %}" method="post">
{% csrf_token %}
{{subcat_form.category}}
{{subcat_form.subcategory_name}}
<button class="btn btn-small" type="submit">Add Subcategory</button>
</form>

You specify in fields that you need id, category and name but you don't put them in your form in your template.
You have only category and subcategory_name.
You can add those two elements in your template OR remove them from the fields list.
Also you don't specify an action for your form, you should give the view where the data from your form should be sent.

Related

why is django returning form.is_valid == false?

Everytime I use this form I get form.is_valid() == False . When I do print(form.errors) I get :
<ul class="errorlist"><li>reservation_code<ul class="errorlist"><li>Client with this Reservation code already exists.</li></ul></li></ul>
But the whole point of the form is to get the details of the reservation, by entering an already existing reservation code. So how can I change this so the form returns valid?
Here is the view:
def reservationView(request):
if request.method == "GET":
return render(request,'aplikacija/reservations.html')
else:
form = ReservationForm(request.POST)
if form.is_valid():
code = form.cleaned_data['reservation_code']
try:
client = Client.objects.filter(reservation_code=code)
tour = client.tour.destination
client.delete()
return render(request,'aplikacija/reservations.html',{'infoMsg':f'You have successfully cancelled your trip to {tour}'})
except:
form = ReservationForm()
return render(request,'aplikacija/cancelReservation.html',{'form':form,'infoMsg':'INVALID RESERVATION CODE'})
else:
form = ReservationForm()
print(form.errors)
return render(request,'aplikacija/cancelReservation.html',{'form':form,'infoMsg':'FORM INVALID'})
This is the model :
class Client(models.Model):
name = models.CharField(max_length=256)
surname = models.CharField(max_length=256)
email = models.CharField(max_length=256)
number_of_guests =models.IntegerField()
tour = models.ForeignKey(Tour,on_delete=models.CASCADE)
total_price = models.DecimalField(decimal_places=2,max_digits=15,default=0)
reservation_code = models.CharField(max_length=50,unique=True)
This is the form class :
class ReservationForm(forms.ModelForm):
class Meta:
model = Client
fields = ('reservation_code',)
widgets = {
'reservation_code':forms.TextInput(attrs={'class':'clientFormField'})
}
And here is the template :
{% extends 'aplikacija/base.html' %}
{% block content %}
<h2 id="mostPopularTitle">Please enter your reservation code</h2>
<form method="POST" action="{% url 'reservation_details' %}" class="contactFormTab clientForm">
{{infoMsg}}
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn">Get reservation details</button>
</form>
{% endblock %}
Does anyone have an idea why the form is always returning invalid?
For this problem as you said
the whole point of the form is to get the details of the reservation,
by entering an already existing reservation code
You are doing it on a wrong way. If you want to get the details based on the reservation_code you need to change some logic.
There is no point on creating a ModelForm but you can use simply Form if you want.
You can change your form method from POST to GET.
<form action="{% url 'reservation_details' %}" class="contactFormTab clientForm">
{{infoMsg}}
<input type='text' name='reservation_code' placeholder='Reservation Code'>
<button type="submit" class="btn">Get reservation details</button>
</form>
Now in the view.
def reservation_view(request):
reservation_code = request.GET.get('reservation_code')
client = Clinet.objects.get(reservation_code=reservation_code)
return render(request, 'your_template', {'client':client}
Now in the template you can get the client details with this reservation_code
{{clinet.name}} {{client.surname}}

Check the form input value to existing value in Django

In in my database there are some emails those should be checked with the form value which is entered in email field
models.py
class Friend(models.Model):
email = models.EmailField(max_length=100)
forms.py
class FriendForm(forms.ModelForm):
class Meta:
model = Friend
fields = ['email']
views.py
def check(request):
if request.method == "POST":
form = FriendForm(request.POST)
if form.is_valid():
queryset = Friend.objects.all
return render(request,"two.html",{"queryset":queryset})
else:
form = FriendForm()
return render(request, 'emaill.html', {'form': form})
emaill.html
<body>
<form method="POST">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" name="Submit">
</form>
</body>
two.html
<body>
<h1>found</h1>
{% for obj in queryset %}
{{obj.email}} </br>
{% endfor %}
</body>
when user submited any email that should be checked with models email that means with existing one if matches in should render to two.html it should show connect
if mail does not match with mail that is in database it should show no such mail
Okay, I understand what you are trying to do. You are doing an email search.
def check(request):
if request.method == "POST":
form = FriendForm(request.POST)
if form.is_valid():
email = form.cleaned_data("email")
try:
friend = Friend.objects.get(email=email)
return render(request,"email1.html",
{"friend":friend})
except Friend.DoesNotExist:
return render(request, "email1.html", {"form":form})
If you are interested in connecting them, then you should use the get method of the ModelManager (objects). That will return a single object if it exists.
In your template. As you can see I have saved some typing on an extra template by using conditions in the template.
{% if form %}
#display your form
{% else %}
#display the friend as you want
{% endif %}
I recommend you go slow and do more reading of the documentation. I am here. Note that I changed your queryset to friend. queryset is misleading as it points that you want multiple objects. So in your template you cant iterate, instead you display friend without iterating.
{{ friend }}

How to get a Django ModelForm to redirect to another ModelForm on submit?

I have a template which displays a certain ModelForm at one of the URLs of my Django site. The ModelForm is based on a model with two fields,
class ActionCode(models.Model):
action_code = models.CharField(blank=False, max_length=10,
verbose_name="Action Code")
description = models.TextField(blank=True)
class Meta:
unique_together = ('action_code',)
I would like my ModelForm to give the user only the first field (Action Code), then when it is submitted, verify if the value entered already exists or not. If it doesn't already exist, I want to redirect the user to be able to enter a Description for that Action Code (the second field in my model). So I wrote a second ModelForm which uses the Description field of the model, and I would like my first form to redirect to the second form after validating that the data is new. Ideally then, the Description would be linked to this specific piece of data and both would go into the same Django database table (hence them coming from the same model). However, when I enter a new piece of data and hit Submit, the site simply stays at the /action_code/ URL and displays a Submit button, and nothing else. How do I get the first form to redirect to the second form, and what is the best way to make sure it only does so if the data is new?
Here are my urls.py:
url(r'^action_code/', action_code_form, name="actioncode"),
url(r'descr_form/', code_description_form, name='description'),
Here are my two forms in `forms.py':
class ActionCodeForm(ModelForm):
class Meta:
model = ActionCode
fields = ('action_code',)
class ActionCodeDescriptionForm(ModelForm):
class Meta:
model = ActionCode
fields = ('description',)
Here is my views.py:
def action_code_form(request):
form = ActionCodeForm()
description_form = ActionCodeDescriptionForm
if request.method == 'POST':
form = ActionCodeForm(request.POST)
if form.is_valid():
action_code = form.cleaned_data['action_code']
form.save()
return render(request, 'description_form.html',
{'form': description_form})
return render(request, 'action_code_form.html', {'form': form})
def code_description_form(request):
form = ActionCodeDescriptionForm()
if request.method == 'POST':
form = ActionCodeDescriptionForm(request.POST)
if form.is_valid():
form.save()
return render(request, 'description_form.html', {'descr_form': form})
And my templates:
action_code_form.html:
<form method="post" action="">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type="submit" value="Submit"/>
</form>
description_form.html:
<form method="post" action="">
{% csrf_token %}
<table>
{{ descr_form }}
</table>
<input type="submit" value="Submit"/>
</form>
Forms don't redirect to anything. It's the view's responsibility to do the redirect.
You need two views, with two URLs; when the first form submission is successful, the view should redirect to the second URL.

Django ModelForm with ManyToManyField wont save to DB

I`m using Django 1.9 with the following:
views.py:
def a_new(request):
# submit button
if request.method == "POST":
form = AForm(request.POST)
if form.is_valid():
post = form.save(commit=False)
post.save()
return redirect('ui:config-list')
# first visit
else:
form = AForm()
template = 'api/test_template.html'
context = RequestContext(request, {'form': form})
return render_to_response(template, context)
forms.py:
class AForm(forms.ModelForm):
b= forms.ModelMultipleChoiceField(
queryset=B.objects.all(),
widget=FilteredSelectMultiple("b", is_stacked=False)
)
class Meta:
model = A
fields = ('name', 'b', )
test_template.html
...
<form role="form" class="form-inline" action="" method="post" enctype="multipart/form-data">
{% csrf_token %}
<div>
{{ form.name }}
{{ form.b }}
</div>
<div class="dl-horizontal">
<button type="submit" class="btn btn-success">Save</button>
</div>
</form>
models.py:
class A(models.Model):
name = models.CharField(max_length=100)
b = models.ManyToManyField(B, null=True, blank=True, name='b')
...
The problem is that when I use the Save button - only the name field is created in the item. The b item, that the widget is being used on, is just not being saved to the DB with the new item A created(it does show error if I leave the b field empty so I guess its checking it too).
What can be the problem?
See the documentation about using commit=False when you have a many-to-many field.
Note that there is no reason for you to be using commit=False here though. Remove it, and the second save, and Django will save your values directly.
b is ManyToManyField, it does on saved on the table A. In a different table the relation between A and B is maintained.
If you have an M2M field and do save(commit=False) you need to call this at the end:
form.save_m2m()
See the docs.

Django imageField not validating - Why?

I have a model:
class PartnerPrefs(models.Model):
partner = models.ForeignKey(Partner)
theme = models.IntegerField()
email = models.EmailField()
logo_file = models.ImageField(upload_to='logos/')
And my forms:
class PartnerPrefsForm(ModelForm):
theme = forms.ChoiceField(
choices=THEME_CHOICE,
widget=forms.Select(),
initial='1',
)
class Meta:
model = PartnerPrefs
exclude = ('partner',)
And my views:
...
if request.method == 'POST':
prefsform = PartnerPrefsForm(request.FILES, request.POST)
if prefsform.is_valid():
# do stuff
And finally my template:
<form enctype='multipart/form-data' form action='.' method='post'>
{% csrf_token %}
{{ prefsform.as_p }}
<input type="submit" value="Submit" />
</form>
Whenever I submit the form all field come back with This field is required.... If I eliminate the ImageField from the form, then it works fine. I cannot find what the problem is.
The issue turned out to be the order in which request.POST and request.FILES are passed to the from. request.POST must go first.