data cannot be saved in form - python

data cannot be saved in form.I wrote html like
<form action="/app/save" method="POST">
<input id="classname" name="classname">
<input id="score" name="score">
<input id="course" name="course">
<button type="submit">SEND</button>
</form>
in forms.py
from django import forms
from .models import Student
class SaveForm(forms.ModelForm):
class Meta:
model = Student
fields = ("classname", "score", "course")
in views.py
#csrf_exempt
def save(request):
save_form = SaveForm(request.POST or None)
print(save_form.is_valid())
if request.method == "POST" and save_form.is_valid():
item = save_form.save(commit=False)
classname = request.POST.get("classname", "")
score = request.POST.get("score", "")
course = request.POST.get("course", "")
item.classname = classname
item.score = score
item.course = course
item.save()
return render(request, 'index.html')
in models.py
from django.db import models
class Student(models.Model):
classname = models.CharField(max_length=100)
score = models.CharField(max_length=100)
course = models.CharField(max_length=100)
When I run this codes ,put data A in classname& 80 in score&Math in course of html and put SEND button,save method can be called but data cannot be saved.print(save_form.is_valid()) shows False.I really cannot understand why I can't send data.What is wrong in my codes?How should I fix this?

Okay a few things here;
Why is score a charfield? If it's a %, shouldn't it be an int?
Student model doesn't have any foreign keys, so there's really no need to use commit = false in your save.
Creating inputs for each item on your form in html is definitely the long way to do it. The best way to do this in your html is simply to use {{form}}. To do this, you'll need to pass the form as a variable in context in your views.py.
Without being mean, are you very early in to the django beginner tutorial? If so, I would recommend moving forward through that before trying to continue your current project. It'll really help you. Here's what I would suggest as a views.py
def save(request):
if request.method == "POST":
save_form = SaveForm(request.POST)
print(save_form.is_valid())
if(save_form.is_valid()):
save_form.save()
return HttpResponseRedirect('New-destination-URL')
save_form = SaveForm()
context['form'] = save_form
return render(request, context, 'index.html')
and in index.html:
form action="/app/save" method="POST">
{{form}}
</form>

You do it wrong, you have to handle both situations - when you are on page at first time, and time when form is filled with data.
Try to change your views to this :
if request.method == "POST":
save_form = SaveForm(request.POST)
...
else:
save_form = SaveForm()
return render(request, 'index.html', {'save_form': save_form)
and then try to put this in template:
<form action="/app/save" method="POST">
{{ save_form.as_p }}
<button type="submit">SEND</button>
</form>

Related

Django Form not updating data in the model

this is my first Django project and I am stuck. If not a solution, but just a hint on what I am doing wrong will be truly appreciated.
I have a model with one attribute set as Null by default and I want to use a Form to update that attribute with the ID taken from another model.
These are the 2 models:
models.py
class Squad(models.Model):
squad_name = models.CharField(max_length=20)
def __str__(self):
return self.squad_name
class AvailablePlayer(models.Model):
player_name = models.CharField(max_length=25)
squad = models.ForeignKey(Squad, on_delete=models.CASCADE, blank=True, null=True)
def __str__(self):
return self.player_name
This is the form:
forms.py
class AddSquadToPlayerForm(forms.Form):
# squad the player will be added to
squad_to_player = forms.ModelMultipleChoiceField(queryset=None)
def __init__(self, *args, **kwargs):
super(AddSquadToPlayerForm, self).__init__()
self.fields['squad_to_player'].queryset = AvailablePlayer.objects.all()
This is the view file, where I think something is missing/wrong:
views.py
def add_player_to_squad(request, squad_id):
# player = AvailablePlayer.objects.get(id=squad_id)
squad = Squad.objects.get(id=squad_id)
if request.method == "POST":
form = AddPlayerToSquadForm(request.POST)
if form.is_valid():
form.squad = form.cleaned_data['id']
form.save()
return redirect('fanta_soccer_app:squad', squad_id=squad_id)
else:
form = AddPlayerToSquadForm(queryset=AvailablePlayer.objects.all())
context = {"squad": squad, "form": form}
return render(request, 'fanta_soccer_app/add_player.html', context)
And finally, this is html file
add_player.html
<body>
<p>Add a new player to the Squad:</p>
<p>{{ squad }}</p>
<form action="{% url 'fanta_soccer_app:add_player' squad.id %}" method="POST">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<button name="submit" type="submit" >Add player</button>
</form>
</body>
The rendered html shows correctly a form with a drop down menu correctly populated with the objects in the database from the "AvailablePlayer" model, however when selecting one and clicking on "Add", nothing happens, and selected player is not added to the DB.
Thank you in advance for your time.
EDIT: the code in views.py has been modified according to a comment
ADDITIONAL INFO: to confirm the db is working, if I manually add the squad_id to one of the AvailablePlayer(s) in the DB, it will be correctly listed in the squad details view.
Based off the docs I think where you are going wrong is that you are trying to update an existing value, which requires you to pass an instance keyword argument to form.save().
So I think you need to do something like this:
if form.is_valid():
a = Squad.objects.get(id=squad_id)
form = AddSquadToPlayerForm(request.POST, instance=a)
form.squad = form.cleaned_data['id']
form.save()
I managed to fix it by myself, and sharing here the solution:
I changed the form field from ModelMultipleChoiceField to ModelChoiceField. ModelMultipleChoiceField is for ManyToMany relationships model fields, while mine is a ForeignKey. I have also removed the init method:
squad_to_player = forms.ModelChoiceField(queryset=AvailablePlayer.objects.all())
The view was pretty messed up, as I was aware of, but after fixing the above, I started to have error logs, so I could eventually come up with the following solution:
view.py
def add_player_to_squad(request, squad_id):
squad = Squad.objects.get(id=squad_id)
if request.method == "POST":
form = AddPlayerToSquadForm(request.POST)
if form.is_valid():
player_to_sign = form.cleaned_data['squad_to_player']
player_to_sign.squad = squad
player_to_sign.save()
return redirect('fanta_soccer_app:squad', squad_id=squad_id)
else:
form = AddPlayerToSquadForm()
context = {"squad": squad, "form": form}
return render(request, 'fanta_soccer_app/add_player.html', context)

Trying to create new object by HTML Form, Django,. HttpResponse object. It returned None instead

I am trying to create a new object Book using HTML form but I get HttpResponse None.
I find almost the same case here: Django ModelForm with foreign key
but my code still doesn't work. I can't find what is wrong.
models.py
class Author(models.Model):
""" Author's class - defines an book's author """
name = models.CharField(max_length=140)
def __str__(self):
return self.name
class Book(models.Model):
""" Book class - defines a book """
title = models.CharField(max_length=140)
author = models.ForeignKey("Author", on_delete=models.CASCADE)
read = models.BooleanField(default=False)
forms.py
class BookForm(forms.ModelForm):
title = forms.CharField(max_length=200)
author = forms.ModelChoiceField(queryset=Author.objects.all())
class Meta:
model = Book
fields = ["title", "author", "read"]
class AuthorForm(forms.ModelForm):
class Meta:
model = Author
fields = ["name"]
books.html
<form class="form-inline my-2 my-lg-0" method="POST">
{% csrf_token %}
<input class="form-control mr-sm-2" type="text" placeholder="Title" aria-label="addbook" name="title">
<input class="form-control mr-sm-2" type="text" placeholder="Author" aria-label="addbook" name="author">
<button class="btn btn-outline-secondary my-2 my-sm-0" type="submit">Add New Book</button>
</form>
views.py
def books(request):
if request.method == 'POST':
form = BookForm(request.POST or None)
if form.is_valid():
form.save(commit=True)
all_books = Book.objects.all
all_authors = Author.objects.all
return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors})
else:
all_books = Book.objects.all
all_authors = Author.objects.all
return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors})
I guess something is wrong with views.py or books.html.
I read a big part of Django documentation but still doesn't find an answer that will help me in my case.
You have several issues in your view, but the biggest problem is that you have no code for the case when the form is not valid. You need to have the render call at the same level as the if statement, not within it.
Also, you need to redirect after a success, not render. Finally, you should only set the books and authors once; and all is a method, it needs to be called.
def books(request):
if request.method == 'POST':
form = BookForm(request.POST)
if form.is_valid():
form.save()
return redirect('somewhere') # could be back to the same URL
else:
form = BookForm()
all_books = Book.objects.all()
all_authors = Author.objects.all()
return render(request, 'books.html', {'all_books': all_books, 'all_authors':all_authors, 'form': form})
(Note, your form is probably not valid because you require the read field but don't include it on your template. You should use the form object itself to render the fields, as well as the errors. Once again, all this is in the documentation.)

Django form missing fields

I'm trying to get a simple form working. Oddly, other forms I wrote in this app are working fine, but this one wont show the fields. Can anyone tell me what I'm missing? Here are the files
views.py:
def newnote(request, record_id):
if request.method == 'POST':
form = NoteForm(request.POST)
if form.is_valid():
form.save()
return HttpResponseRedirect('/tracker/all/')
else:
form = NoteForm()
return render(request, 'tracker/noteform.html', {'form': form})
models.py
class Note(models.Model):
record = models.ForeignKey(Record, on_delete=models.CASCADE)
note_text = models.CharField('Notes', max_length=2000)
note_date = models.DateField('Date Entered')
forms.py
class NoteForm(forms.Form):
class Meta:
model = Note
fields = ['note_text',
'note_date'
]
template (noteform.html)
<form action="/tracker/newnote/" method="post">
<div id="fields">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit" />
</div>
</form>
One other note, I have commented out the div id called "fields", to rule out CSS as the issue.
Your form is based on form.Form, which doesn't know anything about models, doesn't expect a Meta class, and expects all its fields to be declared manually - since you have not declared any fields, nothing will show on the template.
It should inherit forms.ModelForm instead.

Django: How to create a form using inline_formset with a many to one relationship with user

I am trying to set up a form using Django's inlineformset_factory. The model is set up in a many to one relationship, each user will have many cases. I want the user to add a case.
I have followed the general outline from this site
models.py
class Case(models.Model):
date_due = models.DateField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
forms.py
CaseFormset = inlineformset_factory(User,Case,
fields=('date_due',),
can_delete = True)
class CaseForm(forms.ModelForm):
class Meta:
model = Case
fields = ('date_due',)
views.py
#login_required
def add_case(request):
if request.method == 'POST':
form = CaseForm(request.POST)
if form.is_valid():
case = form.save(commit = False)
case_formset = CaseFormset(request.POST, instance = case)
if case_formset.is_valid():
case.save()
case_formset.save()
return redirect('index')
else:
print(form.errors)
else:
form = CaseForm()
case_formset = CaseFormset(instance = Case())
return render(request, 'cases/add_case.html',
{'form':form, 'case_formset':case_formset})
add_case.html
<!DOCTYPE html>
{% load staticfiles %}
<html>
<head>
<body>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
{{ case_formset.as_p }}
{{ case_formset.management_form }}
<button type="submit">Save changes</button>
</form>
</body>
</head>
</html>
I am getting a
Exception Type: ValidationError
Exception Value:
['ManagementForm data is missing or has been tampered with']
Reading the docs it looks like I need to add the management_form to the formset, which I have done. I am not sure where else I am going wrong.
I also tried a different approach from the docs
It looks slightly different than the above and tried to create a formset using the user as an instance. I am not sure which approach is preferable.
I have two questions.
Why I am I getting the above error?
Should I be setting the formset to an instance of user instead of case?
Thanks
I figured it out!
In views.py I needed to add case.user = request.user
So views.py looks like
#login_required
def add_case(request):
if request.method == 'POST':
form = CaseForm(request.POST)
if form.is_valid():
case = form.save(commit=False)
case.user = request.user
case_formset = CaseFormset(request.POST, instance = case)
if case_formset.is_valid():
case.save()
case_formset.save()
return redirect('index')
else:
print(form.errors)
else:
form = CaseForm()
case_formset = CaseFormset(instance = Case())
return render(request, 'cases/add_case.html',
{'form':form, 'case_formset':case_formset})

Django Form, User input fields not rendering in template

Django newb here, but I'm learning.
Problem Statement
Input fields not rendering in html template.
Output in Browser
True
| Submit Button |
Relevant Code
forms.py
from django import forms
from django.db import models
class PostNotes(forms.Form):
clientid = models.IntegerField()
notetext = models.CharField(max_length=1000)
-
views.py
def post_form_notes(request):
if request.method == 'GET':
sawit = True
form = PostNotes(initial={'notetext':'This is a sample note'})
else:
sawit = False
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
'sawit': sawit,
})
-
post_form_notes.html
{{ sawit }}
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Submit" />
</form>
Troubleshooting Already Done
I have backed out a fair amount of the code (specifically if I see a
POST) request from the browser. No change.
I have also included a variable to ensure I am seeing the GET request and also the template variables are working. I get output of True.
Simplified the Form Class as much as possible.
I modified the forms.py to use the model I already had for the DB.
forms.py:
from django.forms import ModelForm
from clientadmin.models import notes
class PostNotes(ModelForm):
class Meta:
model = notes
fields = ['notedate', 'notetext']
I also modified the views.py to not set an initial value, so the function uses the following instead of what was asked.
models.py:
def post_form_notes(request):
if request.method == 'GET':
form = PostNotes()
else:
pass
return render(request, 'clientadmin/post_form_notes.html', {
'form': form,
})
Hope this helps someone that was having the same problem I was...
Reference the following URL for further information: https://docs.djangoproject.com/en/1.10/topics/forms/modelforms/

Categories

Resources