Django Form is Not saving to Database - python

I have searched the site for a solution, many related questions, but no direct response given. I have 3 apps on my projects, and 2 worked pretty well, except for this app, which is not writing to the database.
Yes, the other 2 apps write to the postgres database, and I can view the table, but this return empty rows, and I don't see any problem. I hope someone can help me, see below my Model, Form and View.py.
MY View.py
from django.shortcuts import render, redirect
from .forms import EngForm
def EngineerList(request):
return render(request, "Engineers/elist.html")
def EngineerForm(request):
if request.method == "GET":
form = EngForm()
return render(request, "Engineers/eform.html", {'form':form})
else:
form = EngForm(request.POST)
if form.is_valid():
form.save()
return redirect('/engineer/') #pointing to urls.py paths
My Forms.py
from django import forms
from .models import Engineers
class EngForm(forms.ModelForm):
class Meta:
model = Engineers
fields = '__all__'
labels = {
'workarea' : 'Zone',
'face' : 'Picture',
}
def __init__(self, *args, **kwargs):
super(EngForm, self).__init__(*args, **kwargs)
self.fields['position'].empty_label='Select'
self.fields['workarea'].empty_label='Select'
self.fields['face'].required = False
My Model.py
from django.db import models
class Engineers(models.Model):
position = (
('NOC', 'NOC'),
('Supervisor', 'Supervisor'),
('Site Manager','Site Manager'),
('Site Engineer', 'Site Engineer'),
)
region = (
('SS','South-South'),('SW','SW'),('SE','SE'),
('NE','NE'),('NW','NW'),('NC','NC'),
)
firstname = models.CharField(max_length=20)
lastname = models.CharField(max_length=20)
email = models.EmailField(max_length=50)
username = models.CharField(max_length=20)
phone = models.IntegerField()
position = models.CharField(max_length=20, choices=position)
workarea = models.CharField(max_length=20, choices=region)
face = models.ImageField(upload_to='', height_field=15, width_field=9)
My HTML
{% extends "Dashboard/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
<form method="POST" action="" autocomplete="off">
{% csrf_token %}
<div class="row">
<div class="col-md-12">
{{form.face|as_crispy_field}}
</div>
<p>
<hr>
<p>
<div class="col-md-6">
{{form.firstname|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.lastname|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.username|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.position|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.phone|as_crispy_field}}
</div>
<div class="col-md-6">
{{form.workarea|as_crispy_field}}
</div>
<div class="col-md-12">
{{form.email|as_crispy_field}}
</div>
</div>
<hr>
<div>
<button type="submit" class="btn btn-success"><i class="fas fa-save"></i> Submit</button>
</div>
</form>
{% endblock content %}
My problem is, the database table is returning empty row.

Solved. Applied #GwynBleidD suggest, I reviewed the doc, and then rearranged the code as such.
def EngineerForm(request):
if request.method == "POST":
form = EngForm(request.POST)
if form.is_valid():
form.save()
return redirect('/engineer/') #pointing to urls.py paths
else:
form = EngForm()
return render(request, "Engineers/eform.html", {'form':form})

Related

why my submit input isn't working in django?

I have a form so an user can ask for a loan and it will tell them if it´s approved or not. The problem is not the logic, it´s the submit input that doesn't work. It will not save the form in the database or show me the errors because of the submit input. Maybe is something wrong with the succes_url? I don't know, but here's my code:
views.py:
#don't worry about the logic part of the form, it's just to show how it´s supposed to work
class LoanRequest(LoginRequiredMixin, generic.CreateView):
form_class = LoanForm
success_url = reverse_lazy('Prestamos')
template_name = 'Prestamos/template/Prestamos/prestamos.html'
def form_valid(self, form):
user = self.request.user
cliente = Cliente.objects.get(user_id = user.id)
if not cliente.approve_loan(form.cleaned_data.get('loan_total')):
form.add_error(field=None, error='loan not approved')
return self.form_invalid(form)
else:
form.instance.customer_id = cliente
super(LoanRequest, self).form_valid(form)
return render(self.request, 'Prestamos/template/Prestamos/prestamos.html', context={'form': form, 'success_msg': 'loan approved!'})
urls.py:
urlpatterns = [
path('prestamos/', views.LoanRequest.as_view(), name = 'prestamos'),
]
forms.py:
class LoanForm(forms.ModelForm):
class Meta:
model = Prestamo #loan in English
fields = ['loan_type', 'loan_total', 'loan_date']
and the template:
<div class="container">
{%if success_msg%}
<p class="alert alert-success">{{success_msg}}</p>
{%endif%}
<form action="" method="POST">
{%csrf_token%}
{%for field in form%}
<div class="form-group">
<label for="{{field.label}}">{{field.label}}</label>
{{field}}
</div>
{%for error in field.errors%}
<p>{{error}}</p>
{%endfor%}
{%endfor%}
<input type="submit" value="request"></input>
</form>
</div>
models.py:
class Prestamo(models.Model):
loan_id = models.AutoField(primary_key=True)
loan_type = models.CharField(max_length=20,
choices = [('PERSONAL', 'PERSONAL'), ('HIPOTECARIO', 'HIPOTECARIO'), ('PRENDARIO', 'PRENDARIO')])
loan_date = models.DateField()
loan_total = models.IntegerField()
customer_id = models.IntegerField()
class Meta:
db_table = 'prestamo'
Well, <input> is an empty tag, it does not contain anything, so don't close it.
Additionally, I'd recommend you to make gaps between template tags, like it should be {% endfor %} not {%endfor%}.
Also, remove the empty action attribute from form, as Django always take current page route if not mentioned or empty string.
Also use novalidate on form for rendering custom errors.
Try this template:
<div class="container">
{% if success_msg %}
<p class="alert alert-success">{{success_msg}}</p>
{% endif %}
<form method="POST" novalidate>
{% csrf_token %}
{% for field in form %}
<div class="form-group">
<label for="{{field.label}}">{{field.label}}</label>
{{field}}
</div>
{% for error in field.errors %}
<p>{{error}}</p>
{% endfor %}
{% endfor %}
<input type="submit" value="request">
</form>
</div>
Edit:
One mistake I could see the name for the view is prestamos and you have mentioned it as Prestamos, which is wrong.
So:
class LoanRequest(LoginRequiredMixin, generic.CreateView):
form_class = LoanForm
success_url = reverse_lazy('prestamos')
template_name = 'Prestamos/template/Prestamos/prestamos.html'

Passing username (and viewing as uneditable in html) in form Django

I have a form where I would like to have a username and production line send along. The thing is that the username should be taken from current logged user (and viewed as uneditable field) but the production line should be selected via dorpdown.
It works by somehow since when I click on "User" dropdown it shows only the logged user.
views:
def order(request):
storage = PartNumber.objects.all()
username = request.user.username
if request.method == 'POST':
order_form = OrderForm(username=username, data=request.POST)
if order_form.is_valid():
order_form.save()
return redirect('order')
elif request.method == 'GET':
order_form = OrderForm(username=username)
return render(request, 'dashboard/order.html', {"form": order_form, "username": username})
forms:
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ('end_user_id', 'production_line_id')
def __init__(self, *args, **kwargs):
username = kwargs.pop('username', None)
super(OrderForm, self).__init__(*args, **kwargs)
self.fields['end_user_id'].queryset = User.objects.filter(username=username)
models:
class Order(models.Model):
end_user_id = models.ForeignKey(User, on_delete=models.CASCADE)
production_line_id = models.OneToOneField(ProductionLine, on_delete=models.CASCADE)
date_ordered = models.DateTimeField(auto_now_add=True, null=True)
date_completed = models.DateTimeField(auto_now=True, null=True)
def __str__(self):
return str(self.status)
html:
{% extends 'dashboard/main.html' %}
{% load static %}
{% load bootstrap %}
{% block content %}
<h3>Zamowienie</h3>
<br>
<!--{{ form|bootstrap }}-->
<form role="form" action="" method="post">
{% csrf_token %}
<div class="form-group">
<label>Uzytkownik </label>
<!--<input class="form-control" placeholder="{{user}}" readonly>-->
{{ form.end_user_id }}
</div>
<br>
<div class="form-group">
<label>Linia produkcyjna </label>
{{ form.production_line_id }}
</div>
<br>
<div class="text-center">
<button type="submit" class="btn btn-primary">Przeslij</button>
</div>
</form>
{% endblock content %}
Now if you look at the html above, the commented line :
<!--<input class="form-control" placeholder="{{user}}" readonly>-->
actually gives me the look I want but doesn't send the username (doesn't work)
I was trying different solutions from different posts that I found here but nothing seems to work for me.
Any ideas ?
You are passing username to the template using the variable username.
In the template you are trying to get the username by using the variable user.
<input class="form-control" placeholder="{{user}}" readonly>
Should be :
<input class="form-control" placeholder="{{username}}" readonly>

ValueError at /addtodo/: Not able to add new items in todo-list

I've tried to run this to-do app many times, first I wrote my own code, but it gave a lot of errors so I followed multiple tutorials, and read the documentation.
First, I tried to submit data using html forms only(i.e.without making a forms.py file), but it didn't return anything and just kept redirecting to my todo page; although I was able to add new items through the admin-site, but my form didn't return anything.
Second, I redid the entire project, removed the 'due_date' field (because it was causing problems) and created ModelForm in forms.py
I found out the main problem lies somewhere in my views.py file, with my AddTodo function.
I made changes in my function multiple times following instructions from here, here, and here when I was writing the views for html forms only.
In my models.py file:
from django.db import models
# Create your models here.
class TodoItem(models.Model):
task = models.CharField(max_length = 100)
category = models.CharField(max_length = 30)
description = models.TextField()
def __str__(self):
return self.task
In my forms.py file
from django.forms import ModelForm
from .models import TodoItem
class TodoItemForm(ModelForm):
class Meta(object):
model = TodoItem
fields = ["task","category","description"]
In my project urls.py file
from django.contrib import admin
from django.urls import path
from todo_app import views
urlpatterns = [
path('admin/', admin.site.urls),
path('todo/',views.TodoView,name = 'todo'),
path('addtodo/',views.AddTodo,name = 'addtodo'),
path('deletetodo/<int:todo_id>/',views.DeleteTodo,name = 'deletetodo'),
]
In my index.html template
<div class="card-body">
<p>Please fill the form to enter a new task:</p>
<form action='/addtodo/' method="POST">
{% csrf_token %}
{{ form }}
<div class = "form-group">
<label for="task">Task/To-do item</label>
<input class = "form-control" type="text" id="task" placeholder="Add a new task">
</div>
<div class = "form-group">
<label for="category">Category</label>
<input class = "form-control" type="text" id="category" placeholder="Give your task a label">
</div>
<div class = "form-group">
<label for="description">Description</label>
<textarea class = "form-control" id="description" rows="3" placeholder="Details of your task"></textarea>
</div>
<input class = 'btn btn-warning btn-lg' type="submit" value="Add">
</form>
</div>
<div class="col-lg-8 d-none d-lg-block" id = 'task-list'>
<h1>This is my ToDo List!</h1>
<ul>
{% for todo_items in all_items %}
<li class = 'p-1 pl-3 mb-2' style="background: rgba(255, 255, 204,0.3); border-radius: 5px;" class="clearfix">
<span class="float-left mr-5">{{ todo_items.task }}</span>
<form action="/deletetodo/{{ todo_items.id }}/" class = "float-right mx-2" method="POST" style ="display: inline;">
{% csrf_token %}
<input type="submit" class = 'btn btn-info btn-sm' value="Delete">
</form>
<span class="float-right p-1" style="background-color: rgba(204, 51, 255,0.7); border-radius: 5px;; font-size: small;">{{ todo_items.category }}</span>
<br>
<span style="font-size: small; color: rgb(255, 255, 102);"><strong>Details</strong> : {{ todo_items.description }}</span>
</li>
{% endfor %}
</ul>
</div>
And for my views.py file
from django.shortcuts import render
from django.http import HttpResponse,HttpResponseRedirect
from todo_app.models import TodoItem
from todo_app.forms import TodoItemForm
# Create your views here.
def TodoView(request):
all_todo_items = TodoItem.objects.all()
return render(request,'index.html',{'all_items':all_todo_items})
def AddTodo(request):
if request.method == 'POST':
form = TodoItemForm(request.POST)
all_todo_items = TodoItem.objects.all()
if form.is_valid():
new_item = form.save(commit = False)
new_item.save()
return HttpResponseRedirect('/todo/')
else:
all_todo_items = TodoItem.objects.all()
form = TodoItemForm()
return HttpResponseRedirect('/todo/')
def DeleteTodo(request,todo_id):
item_to_delete = TodoItem.objects.get(id=todo_id)
item_to_delete.delete()
return HttpResponseRedirect('/todo/')
If I comment out the else section in AddTodo i get
ValueError at /addtodo/ The view todo_app.views.AddTodo didn't return an HttpResponse object. It returned None instead.
But with it, i'm only redirected to my todo page without having a new item in my list.
If i create views for simple html forms e.g.
if request.method == 'POST':
task = request.POST.get('task')
category = request.POST.get('category')
description = request.POST.get('description')
new_item = TodoItem(task=task,category=category,description=description)
new_item.save()
return HttpResponseRedirect('/todo/')
else:
return HttpResponseRedirect('/todo/')
I get the same problem.
Kindly point out my mistakes, I'll really appreciate it.
You have to render your template and pass it you form like in
return render(request, 'index.html', {'form': form})
instead of redirecting.
Because that's what runs in the else (the GET, not the POST). You don't redirect the GET branch. Otherwise the template with the form is not rendered. You do that upon form submit success on the POST branch.

Django save data from forms to database

Hi i am relatively new to Django. I am currently trying to store values into database. Timesheet.html is basically my form and i have tried to do the validation but it doesn't work. I have searched everything i can but the data being filled out wont be saved into database. Is there anywhere to check that the checkbox has been ticked before user can submit it ?
timesheet.html
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
<input id="sid" type="field" name="studentid">
</div>
</div>
<div class="sub-content">
<div>
<p>Student Name: {{timesheet.studentName}}</p>
<input id="sname" type="field" name="studentname">
</div>
</div>
<div class="sub-content">
<div>
<p>Start Date: {{timesheet.startDate}}</p>
<input id="sdate" type="date" name="startdate">
</div>
</div>
<div class="sub-content">
<div>
<p>End Date: {{timesheet.endDate}}</p>
<input id="edate" type="date" name="enddate">
</div>
</div>
</div>
<div class="end-content">
<div class="center-align">
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
<input id="agree" type="checkbox" name="checkbox" class="tick-att">
</div>
<br>
<div class="align-right">
<input type="submit" class="button" name="submit" value="submit" >
</div>
</div>
</div>
</form>
models.py
class Timesheet(models.Model):
studentID = models.CharField("Student ID", max_length=8, primary_key=True, default="")
studentName = models.CharField("Student Name", max_length=500, default="")
startDate = models.DateField("Start Date", max_length=8)
endDate = models.DateField("End Date", max_length=8)
def __str__(self):
return self.studentID
class TimesheetForm(forms.ModelForm):
class Meta:
model = Timesheet
fields = '__all__'
views.py
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save(commit=False)
timesheet.studentID = request.POST.get('studentID')
timesheet.studentName = request.POST.get('studentName')
timesheet.startDate = request.POST.get('startDate')
timesheet.endDate = request.POST.get('endDate')
timesheet.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
#if the form is not valid, redirect the student to the same page
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
There are lots of very strange things here.
Firstly, there is no need to set the fields manually on save. That is exactly what form.save() does in the first place. (And if you ever did need to set something manually, you should always get it from form.cleaned_data rather than request.POST.)
Secondly, you re-instantiate the form if it fails validation. That means that the users can never see the errors that are preventing it from validating.
Thirdly, you should show errors in the template. Along with that, you should let Django itself output your fields so that they are automatically prepopulated when the form is invalid.
Finally, you should add your checkbox as a field on the form, so that it is validated along with everything else.
class TimesheetForm(forms.ModelForm):
checkbox = forms.BooleanField()
class Meta:
model = Timesheet
fields = '__all__'
...
def timesheet(request):
if request.method == "POST":
form = TimesheetForm(request.POST)
if form.is_valid():
timesheet = form.save()
return HttpResponseRedirect(reverse('hrfinance/timesheet.html'))
else:
form = TimesheetForm()
return render(request, 'hrfinance/timesheet.html', {'form': form})
...
<form method="POST" onsubmit="return validation()" action="">
{% csrf_token %}
{{ form.errors }}
<div class="content-wrapper">
<div class="sub-content">
<div>
<p>Student ID: {{timesheet.studentID}}</p>
{{ form.studentID }}
</div>
</div>
</div>
.... etc...
<div class="checklist">
<p>By checking this box I agree that I have satisfied all requirements to continue receiving my scholarship
allowance.</p>
{{ form.checkbox }}
</div>

How can I get data from a form model into a database in Django

I am trying to get data from a model form and then put it into a database. I have figured out how to make the form, but when clicking the submit button it doesn't seem to be put anywhere in my database. Am I doing anything wrong or am I not looking in the correct place in the database.
forms.py
from django import forms
from sxsw.models import Account
class AccountForm(forms.ModelForm):
class Meta:
model = Account
fields = ['firstName', 'lastName', 'email']
views.py
from django.shortcuts import render
from django.shortcuts import redirect
from .forms import AccountForm
from .models import Account
def sxsw(request):
if request.method == 'POST':
form = AccountForm(request.POST)
if form.is_valid():
form.save()
else:
print form.errors
else:
form = AccountForm()
return render(request, 'sxsw/sxsw.html', {'form': form})
def formSubmitted(request):
return render(request, 'sxsw/formSubmitted.html',{})
models.py
from __future__ import unicode_literals
from django.db import models
# Create your models here.
class Account(models.Model):
firstName = models.CharField(max_length = 50)
lastName = models.CharField(max_length = 50)
email = models.EmailField()
def __unicode__(self):
return self.firstName
class Module(models.Model):
author = models.ForeignKey(Account, on_delete = models.CASCADE)
nameOfModule = models.CharField(max_length = 150) #arbitrary number
moduleFile = models.FileField(upload_to = 'uploads/')#Not exactly sure about the upload_to thing
public = models.BooleanField()
def __unicode__(self):
return self.nameOfModule
sxsw.html
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron text-center">
<h3>SXSW Form</h3>
</div>
</div>
<div align="center">
<h1>New Form</h1>
<form role='form' action="/sxsw/formSubmitted/" method="post">
{% csrf_token %}
{{ form.as_p }}
<button type="submit">Submit</button>
</form>
</div>
</div>
{% endblock %}
formSubmitted.html
{% extends "base.html" %}
{% block content %}
<div class="container-fluid">
<div class="jumbotron text-center">
<h3>Form Successfully submitted</h3>
</div>
</div>
<div align="center">
Submit Another Response
</div>
</div>
{% endblock %}
Your form is posting to what I presume is the wrong url
<form role='form' action="/sxsw/formSubmitted/" method="post">
should use the url for the sxsw view
<form role='form' action="/sxsw/" method="post">
Once submitted, you'll likely want to redirect to the submitted view
return redirect('/sxsw/formSubmitted/') # Preferably use the url pattern name here
It looks like your form's action is set to /sxsw/formSubmitted/ that always simply return the submitted page, instead of the url that will call the sxsw view where the form's save method is called.

Categories

Resources