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/
Related
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)
I started to learn Django today, but I am stuck at using forms. I have created two forms: /contact and /blog-new. The form at the Contact page is working fine, but the one at /blog-new is redirecting me to the home page after the submission button is pressed and no information is printed in the terminal nor saved in the database.
Code on Github
I appreciate if someone can explain to me what I did wrong as I cannot figure it out. Thank you!
mysite/blog/forms.py
from django import forms
from .models import BlogPost
class BlogPostModelForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['title', 'slug', 'content']
mysite/blog/views.py
from .forms import BlogPostModelForm
def blog_post_create_view(request):
# create objects
# ? use a form
# request.user -> return something
form = BlogPostModelForm(request.POST or None)
if form.is_valid():
print(form.cleaned_data)
form.save()
form = BlogPostModelForm()
template_name = 'form.html'
context = {'form': form}
return render(request, template_name, context)
mysite/blog/models.py
from django.db import models
# Create your models here.
class BlogPost(models.Model):
title = models.TextField()
slug = models.SlugField(unique=True)
content = models.TextField(null=True, blank=True)
mysite/mysite/urls.py
from blog.views import (
blog_post_create_view,
)
urlpatterns = [
..
path('blog-new', blog_post_create_view),
..
]
mysite/templates/form.html
{% extends "base.html" %}
{% block content %}
{% if title %}
<h1>{{ title }}</h1>
{% endif %}
<form method='POST' action='.'> {% csrf_token %}
{{ form.as_p }}
<button type='submit'>Send</button>
</form>
{% endblock %}
You need to point to right url in action attribute of form.
<form action="/blog-new/" method="post">
{% csrf_token %}
{{ form }}
<input type="submit" value="Submit">
</form>
I think it's not necessary in your case but you could also refactor your view to match the docs.
from django.http import HttpResponseRedirect
from django.shortcuts import render
from .forms import SomeForm
def some_view(request):
# if this is a POST request we need to process the form data
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = SomeForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
# ...
# redirect to a new URL:
return HttpResponseRedirect('/thanks/')
# if a GET (or any other method) we'll create a blank form
else:
form = SomeForm()
return render(request, 'template_name.html', {'form': form})
You need to point to right url in action attribute of form.
That was not actually the solution but something that helped me to figure out what was wrong.
It is not necessary to point to /blog-new/ as . for action will point to the same page, but I have tried with /blog-new/ as action URL and I was surprised to see that /blog-new/ page doesn't exist.
The bug was in mysite/mysite/urls.py for missing a /:
path('blog-new', blog_post_create_view),
It is funny (and annoying) how a symbol like / missing from your code will mess up everything and make you spend hours trying to find a solution as simple as that.
Thank you for your time spend to have a look over my code and try to help me!
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>
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.
I have a form where user just uploads an image,but problem is when I choose an image and press button to submit. It says This field is required.on the page although I have already pointed the image. And that's all it does.I checked if it was actually submitted but no, it was not.What could be the problem ?
Models.py
class pic(models.Model):
username = "anonymous"
picpost = models.ImageField(upload_to='anon_pics')
creation_date = models.DateTimeField(auto_now_add=True)
forms.py
from django import forms
from .models import pic
class PicForm(forms.ModelForm):
class Meta:
model = pic
fields = [
"picpost"
]
view.py
def pic_create(request):
form = PicForm(request.POST or None)
if form.is_valid():
instance = form.save(commit=False)
instance.save()
context = {
"form" : form,
}
return render(request, "create_pic.html", context)
create_pic.html
<body>
<form method='POST' action=''>{% csrf_token %}
{{ form.as_p }}
<input type='submit' value='Upload Picture' />
</form>
</body>
Any help is highly appreciated.Thank you very much!
There are two issues here.
Firstly, your view needs to pass request.FILES as well as request.POST to the form.
Secondly, your form element in the template needs to include enctype="multipart/form-data".