Django deletes previous entry when submiting new one - python

Title is pretty self-explanatory the thing is when I try to submit a new entry django deletes the previous one. I think that the problem is in the delete function because when I disable it I can sumbit as many entries as I want. Here are my files:
Form.py
class FinancesForm(forms.Form):
description = forms.CharField(max_length = 50)
value = forms.DecimalField(max_digits = 10, decimal_places = 2)
Models.py
class Finances(models.Model):
date = models.DateField(auto_now = True)
description = models.CharField(max_length = 50)
value = models.DecimalField(max_digits = 10, decimal_places = 2)
total = models.DecimalField(max_digits = 10, decimal_places = 2, null = True)
Views.py
#login_required
def finances(request):
if request.method == 'POST':
form = FinancesForm(request.POST)
if form.is_valid():
newEntry = Finances()
newEntry.description = form.cleaned_data['description']
newEntry.value = form.cleaned_data['value']
if Finances.objects.all().aggregate(Sum('value')).values()[0] == None:
newEntry.total = newEntry.value;
else:
newEntry.total = Finances.objects.all().aggregate(Sum('value')).values()[0] + newEntry.value
newEntry.save()
return HttpResponseRedirect(reverse('finances'))
form = Finances()
entries = Finances.objects.all()
total = Finances.objects.all().aggregate(Sum('value')).values()[0]
return render(request, 'coop/finances.html', {'entries': entries, 'form':form, 'total': total})
#login_required
def fdelete(request):
if request.method != 'POST':
raise HTTP404
entryId = request.POST.get('entry', None)
entToDel = get_object_or_404(Finances, pk = entryId)
entToDel.delete()
return HttpResponseRedirect(reverse('finances'))
Finances.html
<tbody>
{% if entries %}
{% for entry in entries %}
{% if forloop.last %}
<tr>
<td>{{ entry.date }}</td>
<td>{{ entry.description }}</td>
{% if entry.value >= 0 %}
<td class="positive">{{ entry.value }}</td>
{% else %}
<td class="negative">{{ entry.value}}</td>
{% endif %}
<td>{{entry.total}}</td>
<td>
<form action="{% url "fdelete" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="entry" value="{{ entry.pk }}"/>
<input class="btn btn-primary" type="submit" value="Eliminar"/>
</td>
</tr>
{% else %}
<tr>
<td>{{ entry.date }}</td>
<td>{{ entry.description }}</td>
{% if entry.value >= 0 %}
<td class="positive">{{ entry.value }}</td>
{% else %}
<td class="negative">{{ entry.value}}</td>
{% endif %}
<td>{{entry.total}}</td>
<td></td>
</tr>
{% endif %}
{% endfor %}
{% endif %}
<tr>
<td></td>
<form class="input-group" action="{% url "finances" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<td><input class="form-control" type="text" placeholder="Concepte" name="description"/></td>
<td><input class="form-control" type="text" placeholder="Quantitat €" name="value" onkeydown="if (event.keyCode == 13) { this.form.submit(); return false; }"/></td>
</form>
<td></td>
<td></td>
</tbody>
Thanks for yout time

You have not closed your first form
<td>
<form action="{% url "fdelete" %}" method="post" enctype="multipart/form-data">
{% csrf_token %}
<input type="hidden" name="entry" value="{{ entry.pk }}"/>
<input class="btn btn-primary" type="submit" value="Eliminar"/>
</td>
Add closing </form> tag

Related

Django form post not saving

I am making a Django application (for the first time in my life). As part of the application, a timetable needs to be implemented. Loading data (from the databse) into the timetable works fine:
Timetable view
The thing is that the data should be editable. So users need to be able to change the time or the yes/no parameter. I've created a POST handler in views.py, but when I press save, the page quickly reloads and the old values are back. What am I doing wrong?
models.py
class timeTable(models.Model):
key = models.CharField(max_length=200, unique=True, null=True)
value = models.CharField(max_length=200, null=True)
def __str__(self):
return self.key
views.py
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
timetableform = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
form = timeTableFormset(request.POST)
if form.is_valid():
form.save()
return render(request, 'VulnManager/timetable.html', {'timetableform': timetableform})
timetable.html:
<form method="POST">
{% csrf_token %}
<table id="tablePreview" class="table table-borderless table-hover">
<!--Table head-->
<thead>
<tr>
<th></th>
<th>Monday</th>
<th>Tuesday</th>
<th>Wednesday</th>
<th>Thursday</th>
<th>Friday</th>
<th>Saturday</th>
<th>Sunday</th>
</tr>
</thead>
<!--Table head-->
<!--Table body-->
<tbody>
<tr>
<th scope="row">Scan?</th>
{{ timetableform.management_form }}
{% for timeTableValue in timetableform.forms %}
{% if forloop.counter <= 7 %}
<td><select class="form-control" id="{{ timeTableValue.key.value }}" disabled="true">
<option>{{ timeTableValue.value.value }}</option>
<option>
{% if timeTableValue.value.value == "true" %}
false
{% elif timeTableValue.value.value == "false" %}
true
{% endif %}
</option>
</select></td>
{% if forloop.counter == 7 %}
</tr>
<tr>
<th scope="row">Time begin</th>
{% endif %}
{% elif forloop.counter >= 8 and forloop.counter <= 14 %}
<td><input type="text" id="{{ timeTableValue.key.value }}" onchange="validateHhMm(this);" value="{{ timeTableValue.value.value }}" readonly /></td>
{% if forloop.counter == 14 %}
</tr>
<tr>
<th scope="row">Time end</th>
{% endif %}
{% elif forloop.counter >= 15 and forloop.counter <= 21 %}
<td><input type="text" id="{{ timeTableValue.key.value }}" onchange="validateHhMm(this);" value="{{ timeTableValue.value.value }}" readonly /></td>
{% endif %}
{% endfor %}
</tr>
</tbody>
<!--Table body-->
</table>
<input type="button" class="btn-primary" id="edit" value="Edit" />
<input type="submit" class="btn-primary" id="save" value="Save" />
</form>
Your "form" variable has the formset in it, but you have to loop through the forms in the formset individually:
if form.is_valid():
for form_line in form:
form_line.save()
Your view is always rendering the "get" form for lack of a better term.
I think if you keep your variable names the same, it'll make things a bit simpler and consistent. So to explain this;
views.py
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
timetableform = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
form = timeTableFormset(request.POST) # This form just gets left in this block
if form.is_valid():
form.save()
return render(
request,
'VulnManager/timetable.html',
{'timetableform': timetableform} # The context includes the fresh new form, with no post data
)
What you should do, is just call it formset, because it makes life easier;
from django.contrib import messages
#login_required(login_url='login')
def timetable(request):
timeTableFormset = modelformset_factory(timeTable, fields='__all__' ,extra=0)
formset = timeTableFormset(queryset=timeTable.objects.all())
if request.method == 'POST':
formset = timeTableFormset(data=request.POST, queryset=timeTable.objects.all())
if formset.is_valid():
formset.save()
# Do something here to reassure the user it saved. Redirect or add a message
messages.success(request, 'Form saved.')
return render(
request,
'VulnManager/timetable.html',
{'timetableform': formset}
)
There's an article here which may provide some worthy reading for you; https://medium.com/#MicroPyramid/understanding-djangos-model-fromsets-in-detail-and-their-advanced-usage-131dfe66853d

jinja2.exceptions.UndefinedError: object has no attribute

I am trying to create an Inventory Management System in which i can create/add stock through a form(WTForms) and have it displayed in a table on a separate page. Currently, i am stuck on the stated error. I have looked everywhere for an answer to no avail. I am supposed to add stock through 'createGPU.html' and be directed to 'retrieveGPU.html'
Clicking the submit button in createGPU results in jinja2.exceptions.UndefinedError: 'GPUs.GPUs object' has no attribute 'GPUName'
Main Program
from flask import Flask, render_template, request, redirect, url_for
from Forms import CreateGPUForm
import shelve, GPUs
#app.route("/createGPU", methods=['GET', 'POST'])
def createGPU():
createGPUForm = CreateGPUForm(request.form)
if request.method == 'POST' and createGPUForm.validate():
gpuDict = {}
db = shelve.open('storage.db', 'c')
try:
gpuDict = db['GPU']
except:
print('Error in retrieving GPUs from storage.db.')
gpu = GPUs.GPUs(createGPUForm.GPUName.data, createGPUForm.GPUUnitPrice.data, createGPUForm.GPUStock.data,createGPUForm.GPUSales.data)
gpuDict[gpu.get_GPUNo()] = gpu
db['GPU'] = gpuDict
db.close()
return redirect(url_for('retrieveGPU'))
return render_template('createGPU.html', form=createGPUForm)
if __name__ == '__main__':
app.run()
#app.route('/retrieveGPU')
def retrieveGPU():
gpuDict = {}
db = shelve.open('storage.db', 'r')
gpuDict = db['GPU']
db.close()
gpuList = []
for key in gpuDict:
gpu = gpuDict.get(key)
gpuList.append(gpu)
return render_template('retrieveGPU.html',gpuList=gpuList, count=len(gpuList))
createGPU
{% extends "base.html" %}
{% block title %}GPU-Assist - Add Graphics Card{% endblock %}
{% block content %}
{% from "includes/_formhelper.html" import render_field %}
<h1 class="display-4">Add Graphics Card</h1>
<form method="POST" action="">
<div class="form-group">
{{ render_field(form.GPUName, class="form-control") }}
</div>
<div class="form-group">
{{ render_field(form.GPUStock, class="form-control") }}
</div>
<div class="form-group">
{{ render_field(form.GPUUnitPrice, class="form-control") }}
</div>
<div class="form-group">
{{ render_field(form.GPUSales, class="form-control") }}
</div>
<input type="submit" value="Submit" class="btn btn-primary"/>
</form>
{% endblock %}
retrieveGPU
{% extends "base.html" %}
{% block title %}GPU-Assist - View GPU-Cart{% endblock %}
{% block content %}
<h1 class="display-4">View GPU</h1>
<div>
{% if count == 0 %}
<p>No GPU in recorded in inventory.</p>
{% elif count == 1 %}
<p>There is 1 GPU recorded in the inventory.</p>
{% else %}
<p>There are {{ count }} GPUs recorded in the inventory.</p>
{% endif %}
</div> <!--End of display number of users div-->
<div>
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Stock</th>
<th>Unit Price</th>
<th>Sales</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{% for gpu in gpuList %}
<tr>
<td>{{ gpu.GPUName() }}</td>
<td>{{ gpu.GPUStock() }}</td>
<td>{{ gpu.GPUUnitPrice() }}</td>
<td>{{ gpu.GPUSales() }}</td>
<td>Update</td>
<td>
<form action="" method="POST">
<input type="submit" value="Delete" class="btn btn-danger">
</form>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
GPUs.py
class GPUs:
countID = 0
def __init__(self,GPUName,GPUStock,GPUUnitPrice,GPUSales):
GPUs.countID += 1
self.__GPUName = GPUName
self.__GPUStock = GPUStock
self.__GPUUnitPrice = GPUUnitPrice
self.__GPUSales = GPUSales
self.__GPUNo=GPUs.countID
'''
One obvious limitation it has is that every time you restart the web application, the countID resets to 0.
Once the countID resets, the next newly created Users’s userID will start from 1 again and overwrite any User
that previously had __userID = 1. (Must figure out an alternative)
'''
#Getter or Accessor
def get_GPUNo(self):
return self.__GPUNo
def get_GPUName(self):
return self.__GPUName
def get_GPUStock(self):
return self.__GPUStock
def get_GPUUnitPrice(self):
return self.__GPUUnitPrice
def get_GPUSales(self):
return self.__GPUSales
#Settor or Mutator
def set_GPUNo(self, GPUNo):
self.__GPUNo = GPUNo
def set_GPUName(self, GPUName):
self.__GPUName = GPUName
def set_GPUStock(self, GPUStock):
self.__GPUStock = GPUStock
def set_GPUUnitPrice(self, GPUUnitPrice):
self.__GPUUnitPrice = GPUUnitPrice
def set_GPUSales(self, GPUSales):
self.__GPUSales = GPUSales
When Jinja2 processes
<td>{{ gpu.GPUName() }}</td>
it expects that gpu will have a callable member function named GPUName. The way you've coded things up, get_GPUName is what you want instead.
The Pythonic way were be to drop the getters and setters entirely, removed the double-underscore prefixes, and have the template go directly for the named instance variable.
<td>{{ gpu.GPUName }}</td>

How to select/unselect/delete multiple django items in a table with the same checkbox?

I have this table of items with their details, and I have implemented a method to 'select' a few items using a submit button, which submits all checked checkboxes on each item.
This is the code for the checkbox:
<input name='quiz-pids' id='checkbox-{{ quiz.id }}' type="checkbox" value="{{ quiz.id }}" required>
As you can see, I have passed the quiz.id in the checkbox value. This is my submit button I am using:
<input type="submit" class="btn btn-primary select-btn myitems-select-btn"
value='Finalize Items'
required>
Here, I have not mentioned what this button will do except than submit. This is the function which processes the data input by submit button.
class UploadedItems(ListView):
model = ItemBatch
ordering = ('uploaded',)
context_object_name = 'plan'
template_name = 'classroom/teachers/item_list.html'
def post (self, request, *args, **kwargs):
# get the selected quizs
quizs = request.POST.getlist('quiz-pids')
# retrieves thoses quizes from the database:
print("pids returned are ", quizs)
# items = ItemBatch.objects.filter(pid__in=quizs)
for i in quizs:
print("before", i)
i = get_object_or_404(ItemBatch, id=i)
i.rtd = 'True'
i.save()
print("after", i.truck_type) # print("items are",items)
return redirect('teachers:upload_batch')
As you can see, my function 'post' accepts only quiz-pids because of this line request.POST.getlist('quiz-pids'). Now my question is, I also want to delete and unselect my items. But, because my function can only accept quiz-pids, I cannot just create another button for that.
What I tried
I tried adding more functions:
def post (self, request, *args, **kwargs):
# get the selected quizs
quizs = request.POST.getlist('quiz-pids')
deleted_items = request.POST.getlist('delete-pids')
unselect_items = request.POST.getlist('unselect-pids')
# retrieves thoses quizes from the database:
print("pids returned are ", quizs)
# items = ItemBatch.objects.filter(pid__in=quizs)
for i in quizs:
print("before", i)
i = get_object_or_404(ItemBatch, id=i)
i.rtd = 'True'
i.save()
print("after", i.truck_type) # print("items are",items)
for j in unselect_items:
j = get_object_or_404(ItemBatch, id=i)
j.rtd = 'False'
j.save()
for k in deleted_items:
k = get_object_or_404(ItemBatch, id=i)
k.delete()
k.save()
But, because every checkbox I have in front of my items, has the name name='quiz-pids', I am not able to generate a deleted_items list or unselect_items list. I cannot possibly give three different checkboxes to every item. What should I do?
Here is my complete html and views function:
#method_decorator([login_required, teacher_required], name='dispatch')
class UploadedItems(ListView):
model = ItemBatch
ordering = ('uploaded',)
context_object_name = 'plan'
template_name = 'classroom/teachers/item_list.html'
def get_queryset (self):
return ItemBatch.objects.filter(uploaded_by=self.request.user)
def get_context_data (self, **kwargs):
context = super().get_context_data(**kwargs)
latest = ItemBatch.objects.filter(uploaded_by=self.request.user).order_by('-time').annotate(
truncated_time=Trunc('time', 'minute', output_field=DateTimeField()))
context['last'] = ItemBatch.objects.filter(uploaded_by=self.request.user).annotate(
truncated_time=Trunc('time', 'minute', output_field=DateTimeField())).filter(
truncated_time=Subquery(latest.values('truncated_time')[:1])).order_by('-rtd')
return context
def post (self, request, *args, **kwargs):
# get the selected quizs
quizs = request.POST.getlist('quiz-pids')
deleted_items = request.POST.getlist('delete-pids')
unselect_items = request.POST.getlist('unselect-pids')
# retrieves thoses quizes from the database:
print("pids returned are ", quizs)
# items = ItemBatch.objects.filter(pid__in=quizs)
for i in quizs:
print("before", i)
i = get_object_or_404(ItemBatch, id=i)
i.rtd = 'True'
i.save()
print("after", i.truck_type) # print("items are",items)
for j in unselect_items:
j = get_object_or_404(ItemBatch, id=i)
j.rtd = 'False'
j.save()
for k in deleted_items:
k = get_object_or_404(ItemBatch, id=i)
k.delete()
k.save()
print("pids converted are ", quizs)
return redirect('teachers:upload_batch')
HTML template:
{% extends 'base2.html' %}
{% load static %}
{% load tz humanize %}
{% timezone "Asia/Kolkata" %}
{% block content %}
<h2>Orders</h2>
{% include 'classroom/teachers/inventory_header.html' with active='myitems' %}
<h2 class="align-left"> Your Last Uploaded Items</h2>
{#Post New Bid#}
<div class="card last-items">
<form method="post" novalidate>
{% csrf_token %}
<table class="table table-striped mb-0" id="items">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>SKU ID</th>
<th>Quantity</th>
<th>Dimensions</th>
<th>Volume/Weight</th>
<th>Origin</th>
<th>Destination</th>
<th>Type</th>
<th>Uploaded</th>
<th>Dispatch Status</th>
</tr>
</thead>
<tbody>
<input type="checkbox" id="selectall" class="css-checkbox btn btn-primary" name="selectall"/>Select
All
{% for quiz in last %}
<input type="submit" class="btn btn-primary select-btn myitems-select-btn"
value='Finalize Items'
required>
<input type="submit" class="btn btn-primary select-btn myitems-select-btn"
value='Unselect Items'
required>
<input type="submit" class="btn btn-primary select-btn myitems-select-btn"
value='Delete Items'
required>
<a href="{% url 'teachers:pack_it' %}"
class="btn btn-primary mb-3 myitems-select-btn {% if quiz.rtd == 0 %} disabled {% endif %}"
role="button">Plan Vehicles</a>
<tr class="{% if quiz.rtd == True %} active{% endif %} {% if quiz.is_dispatched == True %} dispatched{% endif %}">
<td class="align-middle"><input name='quiz-pids' id='checkbox-{{ quiz.id }}'
type="checkbox" value="{{ quiz.id }}" required
{% if quiz.is_dispatched == 1 %} disabled{% endif %} ></td>
<td class="align-middle">{{ quiz.name }}</td>
<td class="align-middle">{{ quiz.pid }}</td>
<td class="align-middle">{{ quiz.quantity }}</td>
<td class="align-middle">{{ quiz.length }}x{{ quiz.width }}x{{ quiz.height }}</td>
<td class="align-middle">{{ quiz.volume|truncatechars:8 }}/{{ quiz.weight }}</td>
<td class="align-middle">{{ quiz.origin }}</td>
<td class="align-middle">{{ quiz.destination }}</td>
<td class="align-middle">{{ quiz.truck_type }}</td>
<td class="align-middle">{{ quiz.time|naturaltime }}</td>
<td class="align-middle">{{ quiz.is_dispatched|yesno:"Dispatched,Ready to Dispatch" }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</form>
</div>
<br>
<br>
<h2 class="align-left">All your Uploaded Items</h2>
<br>
<div class="card">
<table class="table table-striped mb-0" id="items">
<thead>
<tr>
<th>Select</th>
<th>Name</th>
<th>SKU ID</th>
<th>Quantity</th>
<th>Dimensions</th>
<th>Volume/Weight</th>
<th>Origin</th>
<th>Destination</th>
<th>Type</th>
<th>Uploaded</th>
<th>Dispatch Status</th>
</tr>
</thead>
<tbody>
<form method="post" novalidate>
{% csrf_token %}
{% for quiz in plan %}
<input type="submit" class="btn btn-primary select-btn myitems-select-btn"
value='Finalize Items'
required>
<a href="{% url 'teachers:pack_it' %}"
class="btn btn-primary mb-3 myitems-select-btn {% if quiz.rtd == 0 %} disabled {% endif %}"
role="button">Plan Vehicles</a>
<tr class="{% if quiz.rtd == True %} active{% endif %} {% if quiz.is_dispatched == True %} dispatched{% endif %}">
<td class="align-middle"><input name='quiz-pids' id='checkbox-{{ quiz.id }}'
type="checkbox" value="{{ quiz.id }}" required
{% if quiz.is_dispatched == 1 %} disabled{% endif %} ></td>
<td class="align-middle">{{ quiz.name }}</td>
<td class="align-middle">{{ quiz.pid }}</td>
<td class="align-middle">{{ quiz.quantity }}</td>
<td class="align-middle">{{ quiz.length }}x{{ quiz.width }}x{{ quiz.height }}</td>
<td class="align-middle">{{ quiz.volume }}/{{ quiz.weight }}</td>
<td class="align-middle">{{ quiz.origin }}</td>
<td class="align-middle">{{ quiz.destination }}</td>
<td class="align-middle">{{ quiz.truck_type }}</td>
<td class="align-middle">{{ quiz.time|naturaltime }}</td>
<td class="align-middle">{{ quiz.is_dispatched|yesno:"Dispatched,Ready to Dispatch" }}</td>
</tr>
<tr>
{% empty %}
<td class="bg-light text-center font-italic" colspan="9">You haven't uploaded any items yet.
</td>
</tr>
{% endfor %}
</form>
</tbody>
</table>
</div>
<link rel="stylesheet" href="http://cdn.datatables.net/1.10.13/css/jquery.dataTables.min.css">
{# <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>#}
<script src="https://cdn.datatables.net/1.10.13/js/jquery.dataTables.min.js"></script>
<script>
$(document).ready(function () {
$('#items').DataTable({
"pagingType": "full_numbers",
"bDestroy": true
});
});
</script>
<script>
$('#selectall').click(function () {
var checkedStatus = this.checked;
$('input:checkbox').each(function () {
$(this).prop('checked', checkedStatus);
});
});
</script>
{% endblock %}
{% endtimezone %}
Anybody has any doubts? or need more information?

Django ChoiceField

I'm trying to solve following issue:
I have a web page that can see only moderators.
Fields displayed on this page (after user have registered):
Username, First name+Last name, Email, Status, Relevance, etc.
I need to display table with information of all users stored in db with this fields, but two of fields have choices, so I want to make option that moderators can choose another option and after clicking on "Update" button this fields will be updated for selected user.
I can to display all choices of "status" and "relevance" fields, and after I choose new options from dropdown db is updated.
I want to display dropdowns and option stored in db should be selected.
I've tried a lot of options, I googled a lot of my time, and searched for answer or for right direction in StackOverFlow too, but didn't find anything.
Sorry for my bad english and thank you in advance for help!
Below is part of my code:
models.py:
class Profile(models.Model):
user = models.OneToOneField(User)
status = models.IntegerField(choices=((1, _("Not relevant")),
(2, _("Review")),
(3, _("Maybe relevant")),
(4, _("Relevant")),
(5, _("Leading candidate"))),
default=1)
relevance = models.IntegerField(choices=((1, _("Unread")),
(2, _("Read"))),
default=1)
forms.py:
class CViewerForm(forms.Form):
status = forms.ChoiceField(label="",
initial='',
widget=forms.Select(),
required=True)
relevance = forms.ChoiceField(widget=forms.Select(),
required=True)
views.py:
#group_required('Managers')
#render_to('reader/view.html')
def admins_view(request):
users_list = Profile.objects.select_related('user').all()
users_dict = dict()
if request.method and request.method == 'POST':
form = CViewerForm(request.POST)
if form.is_valid():
d = form.cleaned_data
# get all selected choices
status_list = request.POST.getlist('status')
relevance_list = request.POST.getlist('relevance')
# get all usernames viewed on page
users_list = request.POST.getlist('username')
# create dict from all those lists
users_dict = zip([user for user in users_list], [status for status in status_list], [rel for rel in relevance_list])
# run through dict and do bulk update
for user_dict in users_dict:
Profile.objects.filter(user__username=user_dict[0]).update(status=user_dict[1], relevance=user_dict[2])
return HttpResponseRedirect(reverse('reader:admins_view'))
else:
form = CViewerForm()
return {'users_list': users_list,
'user': request.user,
'form': form}
template:
<form class="form-horizontal" action="" method="post" name="update-form" class="well form-inline" id="view_form">
{% csrf_token %}
{{ form.non_field_errors }}
{% for hidden in form.hidden_fields %}
{{ hidden }}
{% endfor %}
{% if user.is_staff %}
<div>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>{% trans 'Username' %} </th>
<th>{% trans 'E-mail' %} </th>
<th>{% trans 'Status' %} </th>
<th>{% trans 'Relevance' %} </th>
</tr>
</thead>
<tbody>
{% for user in users_list %}
<tr>
<td><input type="text" READONLY name="username" value="{{ user.user.username }}"></td>
<td>{{ user.user.first_name }}</td>
<td>{{ user.user.last_name }}</td>
<td>{{ user.user.email }}</td>
<td>{{ user.get_status_display }}</td>
<td>{{ user.get_relevance_display }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<br>
{% endif %}
<div class="form-actions">
<input type="hidden" name="_cmd_personal">
<input type="submit" class="btn btn-info" value="{% trans 'Update' %}" name="update" class="default">
</div>
</form>
Below is a solution:
forms.py (as #Liarez wrote).
template:
<form class="form-horizontal" action="" method="post" name="update-form" class="well form-inline" id="view_form">
{% csrf_token %}
{% if user.is_staff %}
{% if users_list %}
<div>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>{% trans 'Username' %} </th>
<th>{% trans 'First name' %} </th>
<th>{% trans 'Last name' %} </th>
<th>{% trans 'E-mail' %} </th>
<th>{% trans 'CV Status' %} </th>
<th>{% trans 'CV Relevance' %} </th>
</tr>
</thead>
<tbody>
{% for user in users_list %}
<tr>
<td><input type="text" READONLY name="username" value="{{ user.user.username }}"></td>
<td>{{ user.user.first_name }}</td>
<td>{{ user.user.last_name }}</td>
<td>{{ user.user.email }}</td>
<td>
<select name="cv_status">
{% for key, status in status_choices %}
{% ifequal user.get_cv_status_display status %}
<option value="{{ user.cv_status }}" selected>{{ user.get_cv_status_display }}</option>
{% else %}
<option value="{{ key }}">{{ status }}</option>
{% endifequal %}
{% endfor %}
</select>
</td>
<td>
<select name="cv_signal">
{% for key, signal in signal_choices %}
{% ifequal user.get_cv_signal_display signal %}
<option value="{{ user.cv_signal }}" selected>{{ user.get_cv_signal_display }}</option>
{% else %}
<option value="{{ key }}">{{ signal }}</option>
{% endifequal %}
{% endfor %}
</select>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
<br>
{% endif %}
<div class="form-actions">
<input type="submit" class="btn btn-info" value="{% trans 'Update' %}" name="update" class="default">
</div>
First I recommend you as #ChrisHuang-Leaver suggested to define a new file with all the choices you need it there, like choices.py:
STATUS_CHOICES = (
(1, _("Not relevant")),
(2, _("Review")),
(3, _("Maybe relevant")),
(4, _("Relevant")),
(5, _("Leading candidate"))
)
RELEVANCE_CHOICES = (
(1, _("Unread")),
(2, _("Read"))
)
Now you need to import them on the models, so the code is easy to understand like this(models.py):
from myApp.choices import *
class Profile(models.Model):
user = models.OneToOneField(User)
status = models.IntegerField(choices=STATUS_CHOICES, default=1)
relevance = models.IntegerField(choices=RELEVANCE_CHOICES, default=1)
And you have to import the choices in the forms.py too:
forms.py:
from myApp.choices import *
class CViewerForm(forms.Form):
status = forms.ChoiceField(choices = STATUS_CHOICES, label="", initial='', widget=forms.Select(), required=True)
relevance = forms.ChoiceField(choices = RELEVANCE_CHOICES, required=True)
Anyway you have an issue with your template, because you're not using any {{form.field}}, you generate a table but there is no inputs only hidden_fields.
When the user is staff you should generate as many input fields as users you can manage. I think django form is not the best solution for your situation.
I think it will be better for you to use html form, so you can generate as many inputs using the boucle: {% for user in users_list %} and you generate input with an ID related to the user, and you can manage all of them in the view.
Better Way to Provide Choice inside a django Model :
from django.db import models
class Student(models.Model):
FRESHMAN = 'FR'
SOPHOMORE = 'SO'
JUNIOR = 'JR'
SENIOR = 'SR'
GRADUATE = 'GR'
YEAR_IN_SCHOOL_CHOICES = [
(FRESHMAN, 'Freshman'),
(SOPHOMORE, 'Sophomore'),
(JUNIOR, 'Junior'),
(SENIOR, 'Senior'),
(GRADUATE, 'Graduate'),
]
year_in_school = models.CharField(
max_length=2,
choices=YEAR_IN_SCHOOL_CHOICES,
default=FRESHMAN,
)
New method in Django 3
you can use Field.choices Enumeration Types new update in django3 like this :
from django.db import models
class Status(models.TextChoices):
UNPUBLISHED = 'UN', 'Unpublished'
PUBLISHED = 'PB', 'Published'
class Book(models.Model):
status = models.CharField(
max_length=2,
choices=Status.choices,
default=Status.UNPUBLISHED,
)
django docs
If your choices are not pre-decided or they are coming from some other source, you can generate them in your view and pass it to the form .
Example:
views.py:
def my_view(request, interview_pk):
interview = Interview.objects.get(pk=interview_pk)
all_rounds = interview.round_set.order_by('created_at')
all_round_names = [rnd.name for rnd in all_rounds]
form = forms.AddRatingForRound(all_round_names)
return render(request, 'add_rating.html', {'form': form, 'interview': interview, 'rounds': all_rounds})
forms.py
class AddRatingForRound(forms.ModelForm):
def __init__(self, round_list, *args, **kwargs):
super(AddRatingForRound, self).__init__(*args, **kwargs)
self.fields['name'] = forms.ChoiceField(choices=tuple([(name, name) for name in round_list]))
class Meta:
model = models.RatingSheet
fields = ('name', )
template:
<form method="post">
{% csrf_token %}
{% if interview %}
{{ interview }}
{% endif %}
{% if rounds %}
<hr>
{{ form.as_p }}
<input type="submit" value="Submit" />
{% else %}
<h3>No rounds found</h3>
{% endif %}
</form>

Multiple fields on the same row in Django

I'd like to display a row with a label, a textfield and a checkbox for each item in a database. I've managed to do this except for the checkbox that's on a new line. I wan't:
<tr>
<td>Label</td>
<td>Input</td>
<td>Checkbox</td>
<tr>
But all I get is:
<tr>
<td>Label</td>
<td>Input</td>
</tr>
<tr>
<td>Checkbox</td>
</tr>
Anyone knows how to do this?
EDIT:
To generate the form I do:
forms.py
class AttributeForm(forms.Form):
def __init__(self, *args, **kwargs):
extra = kwargs.pop('extra')
super(AttributeForm, self).__init__(*args, **kwargs)
for key in extra:
self.fields[key] = forms.CharField(label=key, initial=extra[key], required=False)
self.fields['delete_'+key] = forms.BooleanField(label='', required=False)
views.py
attribute_form = AttributeForm(extra=user)
return render_to_response('user.html', {'username': username, 'attribute_form': attribute_form})
template (user.html)
<form action="" method="post">
<table>{{ attribute_form.as_table }}</table>
<input type="submit" value="Save attributes">
</form>
EDIT 2:
My template ended up like this:
<form action="" method="post">
<table>
<tr>
{% for field in attribute_form %}
{% cycle '<th>' '' %}{% cycle field.label_tag '' %}{% cycle '</th>' '' %}
<td>{{ field }}{{ attribute_form.field.errors }}</td>
{% if not forloop.last %}{% cycle '' '</tr><tr>' %}{% endif %}
{% endfor %}
</tr>
</table>
<input type="submit" value="Save attributes">
</form>
.as_table renders each form field in seperate table row. You should render the form manually.

Categories

Resources