The browser (or proxy) sent a request that this server could not understand. KeyError: 'name'. error inside views.py st.name = request.form["name"] - flask

views.py file
#student_blueprints.route("/update/<int:id>", methods=["POST", "GET"])
def update(id):
form = studentform()
st = student.query.filter_by(id=id).first()
if form.validate_on_submit:
st.name = request.form["name"]
st.course = request.form["course"]
db.session.commit()
return redirect(url_for("student.list"))
return render_template("update", form = form)
list.html file which is inside of templates/student
<tbody>
{% for i in range(0,students|length) %}
<tr>
<th scope="row">{{i}}</th>
<td>{{ students[i][1] }}</td>
<td>{{ students[i][2] }}</td>
<td>delete</td>
<td>update</td>
</tr>
{% endfor %}
</tbody>
forms.py
from flask import Flask
from flask_wtf import FlaskForm
from wtforms import StringField, SubmitField,IntegerField
class studentform(FlaskForm):
id = IntegerField("id")
name = StringField("name", name="name")
course = StringField("course",name="course")
submit = SubmitField("Submit")
update.html
<div class="container">
<form method="POST">
{{form.hidden_tag()}}
<div class="mb-3">
{{form.name.label(class="form-label")}}
{{form.name(class="form-control", name="name")}}
</div>
<div class="mb-3">
{{form.course.label(class="form-label")}}
{{form.course(class="form-control", name="course")}}
</div>
{{form.submit(class="btn btn-secondary")}}
</form>
</div>
In the above forms.py file for the name and course attributes i have added parameter called name="name" and name="course" to StringField. I want to access the name and course attribute from forms.py file inside of update method in views.py file as request.form['name'] and request.form['course'] to get their respective values from the form fields. I'm getting The browser (or proxy) sent a request that this server could not understand. KeyError: 'name' I was wondering how i could access the form fields dynamically so that i can do update operation? Thank you so much for your help

Related

why is input from my form not writting to the sqlite3 database in django

I would like to update my list after adding some inputs through a form but i cannot see my updated list. I see the existing items in my list ,but when i add a new item it does not appear on the list. I can manually add it using the admin pannel and view it in the list(a whole different path),but not with the form i created to take input and update the list. I was able to query my database and input from the form is not getting written to the database, that's why its not displaying any changes.Below is my code
models.py
class BlogPost(models.Model):
notes = models.CharField(max_length = 1000000000000000000000000000)
date = models.DateTimeField(auto_now_add=True)
done = models.BooleanField(default=False)
def __str__(self):
return self.notes
form.py
from blog.models import BlogPost
class BlogForm(forms.ModelForm):
class Meta:
model = BlogPost
fields = ['notes', 'done',]
views.py
from django.shortcuts import render,redirect
from django.http import HttpResponse,HttpResponseRedirect,HttpRequest
from blog.models import BlogPost
from blog.form import BlogForm
def home(request):
context = {
'welcome_text': 'Welcome to the home page. View some more stuff soon'
}
return render(request,'home.html', context)
def blogpost(request):
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
blog.html
{%extends 'base.html' %}
{% block title%}
<title> Blog </title>
{% endblock title%}
{%block content %}
<div class="container">
<br>
{%for message in messages%}
{{message}}
{% endfor %}
<form method = 'POST'>
{% csrf_token %}
<div class="form-group">
<input type="text" class="form-control" name = 'blog' placeholder = 'new blog' >
</div>
<button type="submit" class="btn btn-primary">Add Blog</button>
</form>
<br>
<table class="table table-hover table-dark">
<thead>
<tr>
<th scope="col">Blog </th>
<th scope="col">Done</th>
<th scope="col">Date</th>
<th scope="col">Edit</th>
<th scope="col">Delete</th>
</tr>
</thead>
<tbody>
{% for item in the_blogs %}
{% if item.done %}
<tr class="table-success">
<td >{{item.notes}}</td>
<td >Not-Completed</td>
<td>{{item.date}}</td>
<td>edit</td>
<td>delete</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>
</div>
{%endblock content%}
if you need more information regarding this, here is a link to my GitHub repository with more code.
https://github.com/wfidelis/Django-App
You have to correct the code indentation and the get call part, pass the form to context object and call it with double curly brackets on templates, also add an action attribute to the template.
def blogpost(request):
all_blogs = BlogPost.objects.all()
if request.method == "POST":
form = BlogForm(request.POST)
if form.is_valid():
if form.save():
message.success(request, "the task was added")
return redirect('blogpost')
else:
form = BlogForm()
return render(request, 'blog.html',{'form': form, 'the_blogs': all_blogs } )
<form method='POST' action="">{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="btn btn-primary">Add Blog</button>
<form/>
When you add a blog, don't redirect, try rendering the page with the new list the same as how you did it here:
all_blogs = BlogPost.objects.all
return render(request, 'blog.html',{'the_blogs': all_blogs } )
or try returning new object created as JSON format to the front-end (as a response of the POST request) and front-end will add it to the HTML with jQuery or JS

Django Error "XXXForm" object has no attribute "XXX"

I use Django to build a web app and when I submit a form, I got error:
AttributeError at /CustomerInfo/
'CustomerForm' object has no attribute 'first_name'
The project name is zqxt_views and app name is calc.
I create a file named forms.py in the calc folder, see below:
calc/forms.py:
from django import forms
class CustomerForm(forms.Form):
customer_id = forms.IntegerField(label="Customer ID")
first_name = forms.CharField(label="First Name", max_length=30)
last_name = forms.CharField(label="Last Name", max_length=30)
calc/views.py:
# -*- coding: utf-8 -*-
#from __future__ import unicode_literals
#from django.shortcuts import render
from django.shortcuts import render
from django.http import HttpResponse
from django.http import HttpResponseRedirect
import MySQLdb
from calc.models import Customer
from calc.forms import CustomerForm
from django.db import connection
...
def show_save_customer(request):
# if this is a POST request we need to process the form database
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = CustomerForm(request.POST)
cursor = connection.cursor()
query = """ insert into customers (first_name, last_name) values (%s, %s) """
cursor.execute(query, [form.first_name, form.last_name])
# check whether it's valid:
if form.is_valid():
#process the data
return HttpResponseRedirect('AddressTableMaintain/');
else:
form = CustomerForm()
return render(request, 'CustomerInfo.html', {'form': form})
# Create your views here.
the form page like below:
calc/templates/CustomerInfo.html:
{% extends 'base.html' %}
{% block title %} Add and Show Customer details {% endblock %}
{% block content %}
<style>
table, th, td {
border: 1px solid black;
border-collapse: collapse;
}
</style>
<form action="{% url 'show_save_customer' %}" method="post">
{% csrf_token %}
<table width="50%" align="center">
<tr>
<td>Customer ID</td>
<td>
{{ form.customer_id }}
</td>
</tr>
<tr>
<td>First Name</td>
<td>
{{ form.first_name }}
</td>
</tr>
<tr>
<td>Last Name</td>
<td>
{{ form.last_name }}
</td>
</tr>
<tr>
<td colspan="2" align="center"><input type="submit" value = "OK" /></td>
</tr>
</table>
</form>
{% endblock %}
After I fill out some data and click the OK button, I always the error mentioned at the beginning, can someone tell me what's wrong with my code?
Indeed, forms do not expose their fields as attributes. You need to access the data via form.cleaned_data - which you should do after you have called form.is_valid().
form = CustomerForm(request.POST)
cursor = connection.cursor()
# check whether it's valid:
if form.is_valid():
query = """ insert into customers (first_name, last_name) values (%s, %s) """
cursor.execute(query, [form.cleaned_data['first_name'], form.cleaned_data['last_name']])
return HttpResponseRedirect('AddressTableMaintain/');
Note also however, unless you have a really good reason you should avoid raw SQL queries and use the Django model layer for your queries. In this case a ModelForm would be even more suitable as it would create and save the instance for you with a simple form.save().
Also note, you do anything on the form to show errors when the form is invalid. There are various ways of doing this, but at the very least you should put {{ form.errors }} in there somewhere.

Having an edit form and a detail view on the same page

I am currently trying to get an edit form working on the same page as a detail view in Django.
I am currently trying out the way as recommended on the docs (i.e. using FormMixin). So, my view looks like this:
class ProductiveMinutesDetail(FormMixin, DetailView):
model = models.ProductiveMinutes
pk_url_kwarg = 'productiveminutes_pk'
form_class = forms.EditForm
def get_success_url(self):
return reverse_lazy('productiveminutes_list')
def get_context_data(self, **kwargs):
context = super(ProductiveMinutesDetail, self).get_context_data(**kwargs)
context['form'] = forms.EditForm(initial={'post': self.object})
return context
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
form.save()
return super(ProductiveMinutesDetail, self).form_valid(form)
And my form looks like this:
from django import forms
from . import models
class EditForm(forms.ModelForm):
class Meta:
model = models.ProductiveMinutes
fields = ('name', 'description',)
The model I am using is this:
class Scenario(models.Model):
name = models.CharField(max_length=200)
class ProductiveMinutes(models.Model):
scenario = models.OneToOneField(Scenario)
name = models.CharField(max_length=200)
amount = models.DecimalField(max_digits=50, decimal_places=2)
description = models.CharField(max_length=200)
Using this I can get the form to render on the page but I know I am doing something wrong as the fields are empty when I would like them to be populated with the data that is already present.
Another piece of complexity is that this form should not be editing the amount field of the model just the name and description. The amount value is edited separately from the detail view of this page.
So, I guess my main question is how can I get the form to be populated with the data for the models fields that is already present and then edit it. Ideally functionality like that of the generic UpdateView that Django provides.
I am using Django version 1.10
Any help with this would be much appreciated
Thanks for your time
UPDATE:
My template looks like this:
{% extends 'pages/dashboard.html' %}
{% load i18n humanize crispy_forms_tags %}
{% block content %}
<div>
<h1 class="text-center">Productive Minutes: {{ productiveminutes.name }}</h1>
<div class="row">
<div class="col"></div>
<div class="col-md-8 col-lg-8">
<h3>Edit productive minutes: {{ productiveminutes.name }}</h3>
<form role="form" method="post">
{% csrf_token %}
{{ form|crispy }}
<button class="primaryAction btn btn-primary pull-right" type="submit">{% trans "Submit" %}</button>
</form>
</div>
<div class="col"></div>
</div>
<hr>
<div class="row">
<div class="col"></div>
<div class="col-md-8 col-lg-8">
<h3>Data Records</h3>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="thead-default">
<tr>
<th>ID</th>
<th>Productive Minutes</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ productiveminutes.id }}</td>
<td>{{ productiveminutes.amount|intcomma }}</td>
<td>
<i class="fa fa-pencil"></i>
<i class="fa fa-trash"></i>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="col"></div>
</div>
</div>
{% endblock content %}
The example in the docs is for displaying detail for an object and having a separate contact form.
In your case, it sound like you want to display the ProductiveMinutesDetail object, and have a form that allows you to update some of the fields of that same object. In that case, you should just use UpdateView.
class ProductiveMinutesUpdate(UpdateView):
model = models.ProductiveMinutes
pk_url_kwarg = 'productiveminutes_pk'
form_class = forms.EditForm
success_url = reverse('productiveminutes_list')
def get_context_data(self, **kwargs):
context = super(ProductiveMinutesUpdate, self).get_context_data(**kwargs)
# Refresh the object from the database in case the form validation changed it
object = self.get_object()
context['object'] = context['productiveminutes'] = object
return context

Django - UpdateView with inline formsets trying to save duplicate records?

I have an Expense model and an ExpenseLineItem model. Just like a typical expense/invoice, one expense can have several line items to make up the total cost of an invoice. I'm trying to use class based views to create and update expenses. I've successfully coded the CreateView to make a new expense with multiple expense line items.
My problem is when I try and update an existing Expense which already has several expense line items. Here's my code below, and I can't figure out what the issue is. The mixins (TitleMixin, CancelSuccessMixin, SelectedApartment)are mine and work fine.
I'm getting an error that, I believe, means that it's trying to save a new copy of the ExpenseLineItems but fails since those already exist. Almost like I'm not providing an instance argument.
What am I doing wrong?
forms.py
class ExpenseForm(ModelForm):
class Meta:
model = Expense
fields = ['apart', 'inv_num', 'vendor', 'due_date']
ExpenseLineItemFormset = inlineformset_factory(Expense, ExpenseLineItem, fields=('description', 'account', 'amt'), can_delete=False)
Here's my ExpenseUpdate view:
class ExpenseUpdate(TitleMixin, CancelSuccessMixin, SelectedApartment, UpdateView):
model = Expense
form_class = ExpenseForm
template_name = 'accounting/expense.html'
def get(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(instance = self.object)
return self.render_to_response(self.get_context_data(form = form, expense_line_item_form = expense_line_item_form))
def post(self, request, *args, **kwargs):
self.object = self.get_object()
form_class = self.get_form_class()
form = self.get_form(form_class)
expense_line_item_form = ExpenseLineItemFormset(self.request.POST, instance=self.object)
if (form.is_valid() and expense_line_item_form.is_valid()):
return self.form_valid(form, expense_line_item_form)
return self.form_invalid(form, expense_line_item_form)
def form_valid(self, form, expense_line_item_form):
self.object = form.save()
expense_line_item_form.instance = self.object
expense_line_item_form.save()
return HttpResponseRedirect(self.get_success_url())
def form_invalid(self, form, expense_line_item_form):
return self.render_to_response(self.get_context_data(form=form, expense_line_item_form=expense_line_item_form))
Error code I get:
MultiValueDictKeyError at /stuff/2/accounting/update-expense/25/
"u'expenselineitem_set-0-id'"
Request Method: POST
Request URL: http://localhost:8000/stuff/2/accounting/update-expense/25/
Django Version: 1.8.3
Exception Type: MultiValueDictKeyError
Exception Value:
"u'expenselineitem_set-0-id'"
Exception Location: /usr/local/lib/python2.7/dist-packages/django/utils/datastructures.py in __getitem__, line 322
Edit: Relevant part of my template:
<form class="form-horizontal" action="" method="post">
{% csrf_token %}
{% load widget_tweaks %}
<div class="row">
<div class="col-md-12">
<table class="table table-tight">
<thead>
<th>Description</th>
<th class="text-right">Account</th>
<th class="text-right">Amount</th>
</thead>
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.description|attr:'cols:29' }}</td>
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div class="col-md-12 text-right">
Cancel
<input class="btn btn-success btn-lg" type="submit" value="Post" />
</div>
<br><br>
</form>
EDIT -- Working Form Template I thought I would add the working version of my template, should someone else need it:
<tbody>
{{ expense_line_item_form.management_form }}
{% for eli in expense_line_item_form %}
<tr>
<td>{{ eli.id }} {{ eli.description|attr:'cols:29' }}</td> <!-- <<==== Here's where I simply added {{ eli.id }}. That's all I changed :) -->
<td class="text-right">{{ eli.account }}</td>
<td class="text-right">{{ eli.amt }}</td>
</tr>
{% endfor %}
</tbody>
You need to include the form id for each form in the formset (it won't be shown to the user, as it is rendered as a hidden input). Without that form, the value is missing from the POST data, and you get a KeyError as you are seeing.
From the formset docs:
Notice how we need to explicitly render {{ form.id }}. This ensures that the model formset, in the POST case, will work correctly. (This example assumes a primary key named id. If you’ve explicitly defined your own primary key that isn’t called id, make sure it gets rendered.)
In your case, you are looping through the formset with {% for eli in expense_line_item_form %}, so you need to include {{ eli.id }}.

author = models.ForeignKey('auth.User', null=True, blank=False) trouble

I have a table where I save data(description, x, y, result and creation date) and until now everything works.
I thought then to add a column with the author for each saved line eg:
DES| X | Y | RESULT |CREATION DATE| AUTHOR |
hi | 3| 1 | 4 | 24/02/2015 | username |
then I added in models.py auth:
from django.db import models
from django.utils import timezone
from simpleapp.oper import add_divide
from django.conf import settings
class ElementiTab(models.Model):
author = models.ForeignKey('auth.User', null=True, blank=False)
des = models.CharField(max_length=30)
x = models.FloatField()
y = models.FloatField()
res = models.FloatField(default=0)
created_date = models.DateTimeField(default=timezone.now)
def save(self, *args, **kwargs):
self.res = add_divide(self.x, self.y)
super(ElementiTab, self).save(*args, **kwargs)
def __str__(self):
return self.des
UPDATE:
forms.py
from django import forms
from .models import ElementiTab
class ElementiTabForm(forms.ModelForm):
class Meta:
model = ElementiTab
fields = ('des', 'x', 'y')
views.py
#login_required
def tabval(request):
# if this is a POST request we need to process the form data
valori = ElementiTab.objects.filter().order_by('-created_date')
if request.method == 'POST':
# create a form instance and populate it with data from the request:
form = ElementiTabForm(request.POST)
# check whether it's valid:
if form.is_valid():
# process the data in form.cleaned_data as required
form.save()
# if a GET (or any other method) we'll create a blank form
else:
form = ElementiTabForm()
return render(request, 'simpleapp/simpleapp.html', {'form': form, 'valori': valori})
#user_passes_test(lambda u: u.is_superuser)
def delete(request, id):
valori_to_delete = get_object_or_404(ElementiTab, pk=id).delete()
return redirect(tabval)
simpleapp.html
{% extends 'registration/base_reg.html' %}
{% block title %}SimpleApp-tabval{% endblock %}
{%block content%}
<h4>TABELLA CON DATI</h4>
<form action="/simpleapp/" method="post">
{% csrf_token %}
{{ form.as_table }}
<input type="submit" value="LIST" />
</form>
<form action="/simpleapp/" method="DELETE">
{% csrf_token %}
<input type="submit" name="canc" value="RESET" />
</form>
<br />
<br />
<div class="table-responsive">
<table class="table table-bordered">
<tr class="info">
<td width="15%" align="center"> NOME</td>
<td width="15%" align="center"> X </td>
<td width="15%" align="center"> Y </td>
<td width="15%" align="center"> RISULTATO </td>
<td width="15%" align="center"> DATA CREAZIONE </td>
<td width="15%" align="center"> AUTORE </td>
{% for elementi in valori %}
<div class="elementi">
<tr>
<td>{{elementi.des}}</td>
<td>{{elementi.x}}</td>
<td>{{elementi.y}}</td>
<td>{{elementi.res}}</td>
<td>{{elementi.created_date}}</td>
<td>{{elementi.author}}</td>
<td width="1%">
{% if user.is_superuser %}
Delete
{% else %}
<span style='font-size: small'>Only Admin</span>
{% endif %}
</td>
</div>
{% endfor %}
</table>
</div>
{% endblock content %}
The fact is that the admin page displays a drop-down menu from which I (as administrator) can choose one of the registered user and so I add them both in the table of my app and in the db.
How can I make this process automatic? I.e. after the login, you put data in the table and once saved the data, also the username is saved and should not be the administrator to set it.
I searched a similar question here but I have not found one to help me to solve my problem.
I updated my answere, i misenderstood your question.
Change this in your view
if form.is_valid():
# Creating the object without commiting to database
obj = form.save(commit=False)
# Setting the user from request
obj.author = request.user
# Commiting to the database
obj.save()