How to pass data from form in template to django views? - django

So I have this little project with messages and comments and i don't know how to save particular comment to particular message. Does anybody know how can i get message.id from template and send it to views.py?
{% for message in messages_all %}
<ul>
<li>#{{message.host}}</li>
<li>{{message.body}}</li>
</ul>
{% for comment in comments_all %}
{% if comment.message == message %}
<ul>
<li>{{comment.body}}</li>
</ul>
{% endif %}
{% endfor %}
{% if request.user.is_authenticated %}
<form method="POST">
{% csrf_token %}
{{form}}
<input type="submit" value="Dodaj komentarz">
</form>
{% endif %}
<hr>
{% endfor %}
views.py
def home(request):
form = AddComments()
if request.method == 'POST':
form = AddComments(request.POST)
messages_all = Message.objects.all()
comments_all = Comments.objects.all()
context = {
'messages_all':messages_all,
'comments_all':comments_all,
'form':form
}
return render(request,'base/home.html', context)

def home(request):
form = AddComments()
if request.method == 'POST':
form = AddComments(request.POST)
if form.is_valid():
form.save()
return redirect('<your current view url>')
messages_all = Message.objects.all()
comments_all = Comments.objects.all()
context = {
'messages_all':messages_all,
'comments_all':comments_all,
'form':form
}
return render(request,'base/home.html', context)

Related

Save list of forms Django

i've managed how to display a list of determined forms, without using formsets. But now i'm strugling to save the data from the form.
This is my template:
{% extends 'base.html' %}
{% block main %}
<div class="container">
<div class="container-form">
<form method="POST" enctype="multipart/form-data" action="{% url 'adjust_values' contract.id %}">
{% csrf_token %}
{% for form in items_forms %}
{{ form }}
{% endfor %}
<button type="submit" class="btn-confirm">Confirm</button>
</form>
</div>
<div class="container-descript">
<h2 class="h2-containter">Adjust your prices!</h2>
<img src="https://i.ibb.co/pX0bq35/Illustration.png" class="img-form">
</div>
</div>
{% endblock %}
This is my views.py
#login_required
def adjust_values(request, id):
contract = get_object_or_404(ClientContract.objects.filter(user=request.user), pk=id)
contract_items = contract.items.all()
items_forms = []
for item in contract_items:
items_forms.append(
ItemForm(request.POST or None, instance=item)
)
my_forms = all([form.is_valid() for form in items_forms])
form = ItemForm()
if my_forms and form.is_valid():
for form in items_forms:
form.save(commit=False)
form.save()
else:
print(form.errors)
context = {'contract': contract, 'form':form, 'items_forms': items_forms}
return render(request, 'item_formset.html', context)
Now i really do not know what i need to do to save the data from the forms. Is there any way to save the data using this structure for iteration trough forms?

how to display a form in function based view

I have got an error when I tried to display a form in function-based view in Django. I could display it in another HTML file and users can make their comments to the blog. But, I think it can be more convenient for users if they can make a comment on the same blog-detail HTML file, so I wanna implement it.
When I tried, this error showed up. "NoReverseMatch at /blogs/blog/30/
Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']"
Any comments can help me and thanks for your time in advance!!
Here are the codes I wrote...
from django import forms
from .models import Comment
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('user', 'text',)
#views.py
#login_required
def blog(request, pk):
blog = get_object_or_404(Blog, pk=pk)
form = CommentForm()
# if request.method == 'POST':
# form = CommentForm(request.POST)
# if form.is_valid():
# comment = form.save(commit=False)
# comment.blog = blog
# comment.save()
# return redirect('blog', pk=blog.pk)
# else:
# form = CommentForm()
if blog.link_1 is not None and blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
elif blog.link_1 is not None or blog.link_2 is not None:
link_1 = blog.link_1
link_2 = blog.link_2
context = {
'blog': blog,
'link_1': link_1,
'link_2': link_2,
'form': form,
}
else:
context = {
'blog': blog,
'form': form,
}
return render(request, 'blog/blog.html', context)
#login_required
def add_comment(request, pk):
blog = get_object_or_404(Blog, pk=pk)
if request.method == 'POST':
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.blog = blog
comment.save()
return redirect('blog', pk=blog.pk)
else:
form = CommentForm()
context = {
'form': form,
}
return render(request, 'blog/blog.html', context)
#urls.py
path('blog/<int:pk>/', views.blog, name='blog'),
path('blog/<int:pk>/comment/', views.add_comment, name='add_comment'),
#blog.html
{% extends 'base.html' %}
{% block title %}|{{ blog.title }}{% endblock %}
{% block content %}
<div class="header-bar">
← 戻る
</div>
<div class="body-container">
<div class="created-edit-delete">
<p>
{% if request.user == blog.user %}
あなたが{{ blog.created }}に作成</p>
{% else %}
{{ blog.user }}が{{ blog.created }}に作成</p>
{% endif %}
<div class="icons">
{% if request.user == blog.user %}
{% endif %}
</div>
</div>
<h1>{{ blog.title }}</h1>
<p class="blog-content">{{ blog.content_1 }}</p>
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_2 }}</p>
{% endif %}
{% if blog.content_2 %}
<p class="blog-content">{{ blog.content_3 }}</p>
{% endif %}
<div class="ref-links">
{% if link_1 %}
参考リンク
{% endif %}
{% if link_2 %}
参考リンク
{% endif %}
</div>
<hr>
<div class="comment-area">
<div class="comment-form">
<h2>New comment</h2>
<form action="{% url 'add_comment' blog.id %}" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button">追加</button>
</form>
</div>
<div class="comment-all">
{% for comment in blog.comments.all %}
<div class="comment">
<div class="date">{{ comment.created }}</div>
<strong>{{ comment.user }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
</div>
</div>
</div>
{% endblock %}
You have called blog URL here ← 戻る and forgot to pass id inside your URL that's why it's showing this error
NoReverseMatch at /blogs/blog/30/ Reverse for 'blog' with no arguments not found. 1 pattern(s) tried: ['blogs/blog/(?P[0-9]+)/$']
you have to pass id here like this
← 戻る

Django form keeps complaining required field

The form submits but immediately says this field is required... although it was filled out. What am I doing wrong
In my view:
def fileupload(request):
if request.user.is_authenticated and request.user.is_staff:
if request.method == 'POST':
form = UploadFileForm(request.POST, request.FILES)
if form.is_valid():
handle_uploaded_file(request.FILES.getlist('file_field'))
return HttpResponseRedirect('/fileupload/')
else:
form = UploadFileForm()
return render(request, 'fileupload.j2.html', {'form': form})
return HttpResponseForbidden('<h1>403 Forbidden</h1>')
with this form:
class UploadFileForm(forms.Form):
kit_number = forms.CharField(label="Kit number", max_length=100, required=True, help_text='Required.')
file_field = forms.FileField(label='Upload kit result')
and template:
{% extends "menu.j2.html" %}
{% block content %}
{% if request.user.is_authenticated and request.user.is_staff %}
<h3>File upload</h3><br><br>
<form action="/fileupload/" method="post">
{% csrf_token %}
<div class="form-group">
<table>
{{ form.as_table() }}
</table>
</div>
<input id="button" class="btn" type="submit" value="Sent">
</form>
{% else %}
You are not authorized to see this page
{% endif %}
{% endblock %}
You forgot to set the form enctype.
<form action="/fileupload/" method="post" enctype="multipart/form-data">

MultiValueDictKeyError at /physicians/3/update/ "u'form-1-id'"; Saving formsets

im trying to save all the forms from my formset and it doesnt pass the validation. here is my code
def UpdatePhysician(request,id):
physician = get_object_or_404(Physician, id=id)
SpecialtyFormset = modelformset_factory(PhysicianSpecialties, fields=('specialty',),max_num=1, labels=None, )
formset = SpecialtyFormset(queryset=PhysicianSpecialties.objects.filter(employee_academic_degree__employee__pk=physician.employee.id))
if request.method == "POST":
formset = SpecialtyFormset(request.POST,)
for form in formset:
print(form)
if (formset.is_valid()):
for form in formset:
form.save()
return HttpResponse('yesh')
else:
return HttpResponse('nope')
return render(request, 'UpdatePhysician.html', {
'formset': formset,
})
it throws me an error like this
"MultiValueDictKeyError at /physicians/3/update/
"u'form-1-id'""
EDIT
I noticed when i have just 1 object in the formset it saves the record perfectly
My template is
{% extends 'prescription_menu.html' %}
{% load bootstrap3 %}
{% load crispy_forms_tags %}
{% block css %}
<link rel="stylesheet" type="text/css" href="{{ STATIC_URL }}site/css/select2.css"/>
{% endblock %}
{% block title %}Physicians{% endblock title %}
{% block container %}
{% csrf_token %}
<form method="POST">
<div class="row">
<div class="col-md-offset-2 col-md-8">
{{ formset.management_form }}
{% for form in formset %}
{% crispy form %}
{% endfor %}
<input type="submit" name="Save" value="Save" class="btn btn-primary" id="submit-id-save">
</div>
</div>
</form>
{% endblock container %}
I noticed that when i saved just 1 record it pass the validation, so it wasnt the formset, was something in post, so I realized that when each form renders the first one follow the layout from the form crispy layout, but the next one renders wrapped on form tags, so i made a special layout class at the bottom of my view to gives layout to my formset and is the following
class SpecialtyFormsetHelper(FormHelper):
def __init__(self, *args, **kwargs):
super(SpecialtyFormsetHelper, self).__init__(*args, **kwargs)
self.form_tag = False
self.render_required_fields = True
and the final code is the following:
def UpdatePhysician(request,id):
physician = get_object_or_404(Physician, id=id)
SpecialtyFormset = modelformset_factory(PhysicianSpecialties, fields=('specialty',),max_num=1,)
formset = SpecialtyFormset(queryset=PhysicianSpecialties.objects.filter(employee_academic_degree__employee__pk=physician.employee.id))
helper = SpecialtyFormsetHelper()
if request.method == "POST":
formset = SpecialtyFormset(request.POST,)
for form in formset:
print(form)
if formset.is_valid():
for form in formset:
form.save()
return HttpResponse('yesh')
else:
return HttpResponse('nope')
return render(request, 'UpdatePhysician.html', {
'formset': formset,
'helper': helper,
})
and i just add helper to the template render
like this:
{{ formset.management_form }}
{% for form in formset %}
{% crispy form helper %}
{% endfor %}
Thank You Alasdair for your help :), you were very helpful

inlineformset_factory modify page throwing errors

My problem:
MultiValueDictKeyError at /classroom-update/1
"u'student_set-0-id'"
My view:
#login_required
def classroom_update(request, pk):
classroom = get_object_or_404(Classroom, pk=pk)
students = classroom.student_set.all()
StudentFormSet = inlineformset_factory(Classroom, Student,form=StudentForm, can_delete=False, extra=0)
if request.method == 'POST':
classroom_form = ClassroomForm(request.POST)
student_formset = StudentFormSet(request.POST)
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False)
classroom.user = request.user
classroom.save()
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom
student.save()
return HttpResponseRedirect('/') # Redirect to a 'success' page
else:
classroom_form = ClassroomForm(instance=classroom)
student_formset = StudentFormSet(instance=classroom)
# For CSRF protection
# See http://docs.djangoproject.com/en/dev/ref/contrib/csrf/
c = {'classroom_form': classroom_form,
'student_formset': student_formset,
}
c.update(csrf(request))
return render_to_response('reports/modify_classroom.html', c)
...and my template code
{% extends 'reports/base.html' %}
{% load crispy_forms_tags %}
{% block head %}
<title>Early Screening Project</title>
{% endblock %}
{% block content %}
<div class="row">
<div class='large-12 columns'>
<form action="" method="POST">{% csrf_token %}
<div class="section">
{% crispy classroom_form %}
</div>
{{ student_formset.management_form|crispy }}
{% for form in student_formset.forms %}
<div class="item">
{% crispy form %}
</div>
{% endfor %}
<input type="submit" value="Submit" class='button' />
</form>
</div>
</div>
{% endblock %}
Thanks for the help!
In Template:
{% for form in student_formset.forms %}
{{ form.id }} #Here , you have to pass form id
<div class="item">
{% crispy form %}
</div>
{% endfor %}
Check it :Django docs
Cheers
--- Update:
You also have to pass the management form
{{ formset.management_form }}
--Response to comment:
I had the same error too , here is the fix:
classroom = get_object_or_404(Classroom, pk=pk)
#.....
if request.method == 'POST':
classroom_form = ClassroomForm(request.POST , instance=classroom)
#This is an Update View , missing to add instance , will result a new entry.
student_formset = StudentFormSet(request.POST, instance = classroom)
#passing the instance here would solve the list index out of range
if classroom_form.is_valid() and student_formset.is_valid():
classroom = classroom_form.save(commit=False)
classroom.user = request.user
classroom.save()
for form in student_formset.forms:
student = form.save(commit=False)
student.classroom = classroom
student.save()
return HttpResponseRedirect('/') # Redirect to a 'success' page