I have a page on my Django website, which is displaying a number of tables based on information stored in the database.
The view being used to create the page displaying the tables is defined with:
def current_budget(request, budget_id):
""" View the active provisional/deposit budget """
budget = Budget.objects.select_related('project', 'project__budget_overview').prefetch_related('project__projectroom_set', 'project__budget_versions', 'budget_items').get(id=budget_id)
project = budget.project
# project.projectroom_set.filter(budgetitem__isnull=True, cciitem__isnull=True).delete()
if project.budget_overview.deposit_budget_saved: return HttpResponseRedirect(reverse('costing:combined_budget', args=[project.id]))
#This is now done in the costing_home view
# if not budget:
# Budget.objects.create(project=project, current_marker=1)
if not budget.budget_items.exists() and not project.budget_overview.deposit_budget_saved: init_budget(budget) # Create initial BudgetItem objects as standard
budget_items = budget.budget_items.select_related('budget', 'budget__project', 'project_room', 'project_room__room', 'room')#.order_by('build_type', 'build_type_detail', 'project_room', 'order') # .exclude(build_type=None)
budget_items2 = None #budget.budget_items.filter(build_type=None).order_by('build_type_detail', 'project_room', 'room')
context = {
'project': project,
'budget': budget,
'offset1': -5,
'offset2': -4,
}
try: context['current_budget'] = project.budget_versions.get(current_marker=1) #For option name/date on top of pdfs
except ObjectDoesNotExist: pass
if request.GET.get('version') or project.budget_overview.deposit_budget_saved: #Make the fields all readonly
context['readonly'] = True
context['offset1'] = -7
if request.GET.get('report'): #Schedule of works report uses same data as current budget form
""" Client view of budget. IMPORTANT: Hidden items are not displayed here """
items_grouped = groupby(budget_items.filter(hidden_cost=False), lambda x: x.build_type)
grouped_items = [(x, list(y)) for x, y in items_grouped]
context['grouped_items'] = grouped_items
if request.GET.get('pdf'):
template = get_template('costing/report_schedule_of_works.html')
html = template.render(context)
file = open('test.pdf', "w+b")
pisaStatus = pisa.CreatePDF(html.encode('utf-8'), link_callback=fetch_resources, dest=file,
encoding='utf-8')
file.seek(0)
pdf = file.read()
file.close()
return HttpResponse(pdf, 'application/pdf')
else:
context['webview'] = 1
context['html'] = render_to_string('costing/report_schedule_of_works.html', context)
context['active_tab'] = '3'
return render(request, 'costing/reports_pre_deposit.html', context)
else:
if not context.get('readonly'):
context['skill_day_rate'] = skill_day_rate
context['labour_day_rate'] = labour_day_rate
# Dict with ProjectRoom ids and the total for the room
room_totals = {}
for project_room in project.projectroom_set.all():
room_totals[project_room.id] = sum(item.total_inc_profit for item in budget_items if item.project_room == project_room)
context['room_totals'] = room_totals
item_formset = BudgetItemFormset(queryset=budget_items, form_kwargs={'project': project})
item_form = item_formset.forms[0]
context['field_count'] = len(item_form.visible_fields())
context['ao_field_count'] = len(item_form.visible_fields())
room_choices = project.room_choices
context['formset'] = item_formset
context['widths'] = budget_item_column_widths #First column is add/delete options to allow for forloop count offset
context['options_width'] = options_width #First column is add/delete options to allow for forloop count offset
context['labour_rate'] = labour_day_rate
context['skill_rate'] = skill_day_rate
context['item_code_options'] = ItemCodeForm()
skill_total = int(budget_items.aggregate(Sum('skill_days'))['skill_days__sum'] or 0)
if budget_items2: labour_total = int(budget_items2.aggregate(Sum('labour_days'))['labour_days__sum'])
else: labour_total = 0
return render(request, 'costing/budget_current.html', context)
I now want to add a 'custom' column to these tables, to allow the user to enter their own notes in (i.e. one that will not be displaying data retrieved from the database, but which should add information to each row in the database when it is saved).
How would I do this? I would have thought that I will do it in the view (Python), rather than in the template (HTML), since the view is where the tables are being constructed?
Edit
So, I've added the extra field to the model in models.py
for the app:
class Deposit(models.Model):
""" Each Deposit is linked to a Payment, whose is_booking_deposit field = True """
project = models.OneToOneField('projects.Project', null=True, blank=True)
half_paid = models.DateField(null=True, blank=True)
date_received = models.DateField(null=True, blank=True)
amount_exc_vat = models.DecimalField(decimal_places=2, max_digits=12, null=True, blank=True)
invoice_raised = models.DateField(null=True, blank=True)
notes = models.TextField(null=True, blank=True)
# Create a column for 'custom notes' in the tables:
custom_notes = models.TextField(null=True, blank=True) #Add the column to table in tables.py
created = models.DateTimeField(auto_now_add=True)
modified = models.DateTimeField(auto_now=True)
payment = models.OneToOneField(Payment, null=True)
...
The field that I've added to the Deposit
model above is the custom_notes
one.
I also tried adding the same field to the BudgetItemTable()
in tables.py
:
class BudgetItemTable(tables.Table):
# Add a column for 'custom notes' to the tables for current budget
custom_notes = tables.Column(accessor='self.custom_notes')
class Meta:
model = BudgetItem
attrs = {"class": "paleblue"}
exclude = ('id')
I've run python manage.py makemigrations
& python manage.py migrate myApp
, but when I refresh my browser to view this page again, the new column for my table is not displayed- do I need to add it to the view somehow? How would I do this?
Edit
The HTML file for the view that displays the table I want to add a column to has the following structure:
...
{% block page_options_style %}allow-footer{% endblock page_options_style %}
{% block page_options %}
...
{% block report %}
<div id='budget_form' class="col-12" data-pr="{{project.id}}" style="margin-bottom:7em;">
<form class="autosave_form formset num_refresh text-sm" data-view-url="{% url 'costing:save_items' budget.id %}">{% csrf_token %}
{{formset.management_form}}
<div>
<table ...>
<thead class=... >
<tr class=...>
...
<!-- code to get table headings here -->
<th style="width:{{options_width}}">Custom Notes</th>
<!-- I added the 'Custom Notes' heading myself -->
</tr>
</thead>
...
<tbody>
...
<tr id="item_{{forloop.counter}}" class="{% cycle 'odd' 'even' %}">
...
<!-- code add columns and populate rows here -->
<td>
<a class="delete" ... ></a>
<!-- I can see this column with the 'delete' values is the last column in the table on the webpage, so I want to manually add another column after it in the table- I tried doing this by adding the following tags: -->
</td>
<td>
<a class="custom_notes" type="text" value=""></a>
</td>
...
</tr>
</tr>
</tbody>
</table>
...
</tbody>
</table>
</div>
</form>
I tried to add the 'Custom Notes' column to the table with the lines:
<td>
<a class="custom_notes" type="text" value=""></a>
</td>
When I view this page in the browser, I can see the Custom Notes
column heading that I've added, displayed above the table, but it is displayed just to the right of where the table ends (I expected the column that I added to the table to be displayed below it).
The table column for 'custom notes' that I have tried adding is not displayed in the table at all...
Why is this? How can I get the new column to be displayed in the table on the webpage? I've added the corresponding field to the model
in models.py
, so although there won't be any data in this field for any of the items in the database at the moment, when the user enters data in this field in the table, there is somewhere for those values to be stored in the model in the database...
Edit
I managed to add this additional field to the table by appending the following HTML to the table, just inside the last two </tr>
tags, inside </tbody></table>
:
<td>
<a class="custom_notes" type="text" value=""></a>
<input id="budget_notes" type="text" width="100" value="">
</td>
But for some reason, the text input field that I have added is very narrow- you can't see more than a few characters of text at a time when typing into it. I tried specifying the width of the field using width="100"
, as shown above, but this doesn't appear to have made any difference. How can I force the cells in this column to have a set width?