Reputation: 3172
I have a Django project, and on one of the pages, I am displaying a report about some of the information in a database.
The element in which I am displaying the report has a number of tabs- each one displaying a 'PDF-style' report about different elements in the database.
I want to add the information that's being displayed on one of the tabs to another tab, but I'm not too sure how I'd do this.
The view for the tab that has the information I want to copy to the other tab is defined with:
def report_ccis(request, project_id):
""" CCI items styled for pdf """
project = Project.objects.get(id=project_id)
budget = get_current_budget(project_id)
cci_total_exc = budget.cci_total_exc_vat_final
cci_grouped_items = budget.cci_items.all().order_by('project_room', 'name')
context = {
'project': project,
'cci_total_exc': cci_total_exc,
'cci_grouped_items': cci_grouped_items,
'webview': 1,
}
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('stage') == 'pd':
""" Render post deposit homepage """
context['html'] = render_to_string('costing/report2_ccis.html', context)
context['active_tab'] = '4'
return render(request, 'costing/reports_post_deposit.html', context)
else:
""" Render pre deposit homepage """
context['html'] = render_to_string('costing/report_ccis.html', context)
context['active_tab'] = '5'
return render(request, 'costing/reports_pre_deposit.html', context)
and the view for the tab on which I want to display this information is defined with:
def report_overview(request, project_id):
""" Budget overview styled for pdf """
project = Project.objects.get(id=project_id)
budget = get_current_budget(project_id)
if not budget and not project.budget_versions.filter(current_marker=1):
Budget.objects.create(project=project, current_marker=1)
cci_total_exc = budget.cci_total_exc_vat
item_total_exc = budget.item_total_exc_vat()
total_exc = cci_total_exc + item_total_exc
total_exc_2 = budget.grand_total_exc_vat
total_inc = budget.grand_total_inc_vat
#----- Add CCIs to the 'Overview tab' -----
cci_total_exc_final = budget.cci_total_exc_vat_final # ERF(29/11/2016 @ 1615) Changed from cci_total_exc to cci_total_exc_final
cci_grouped_items = budget.cci_items.all().order_by('project_room', 'name')
#-----(29/11/2016 @ 1615) -----
context = {
'project': project,
'budget': budget,
'cci_total_exc': cci_total_exc,
'item_total_exc': item_total_exc,
'total_exc': total_exc,
'total_exc_2': total_exc_2,
'total_inc': total_inc,
#-----(29/11/2016 @ 1615) Add CCIs to the 'Overview tab'-----
'cci_grouped_items': cci_grouped_items,
'webview': 1,
#-----(29/11/2016 @ 1615) -----
}
print '****************************************************'
try:
context['current_budget'] = project.budget_versions.get(current_marker=1) #For option name/date on top of pdfs/pages
print 'OPTION NAME', project.budget_versions.get(current_marker=1)
except ObjectDoesNotExist:
print 'No option found with current marker'
pass
if request.GET.get('pdf'):
template = get_template('costing/report_overview.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_overview.html', context)
context['active_tab'] = '1'
return render(request, 'costing/reports_pre_deposit.html', context)
I have tried to add the information displayed in the first view
to the second veiw
by appending the code from the first view
to it, i.e. adding:
if request.GET.get('pdf'):
""" Render post deposit homepage """
context['html'] = render_to_string('costing/report2_ccis.html', context)
context['active_tab'] = '1'
return render(request, 'costing/reports_post_deposit.html', context)
else:
""" Render pre deposit homepage """
context['html'] = render_to_string('costing/report_ccis.html', context)
context['active_tab'] = '1'
return render(request, 'costing/reports_pre_deposit.html', context)
to the end of the report_overview
view, however, when I display the page in the browser, and select the 'overview' tab on the report, I still just see what was displayed before- none of the information that I have copied from the report_ccis
view is displayed.
Why is this? How can I copy the information displayed by the one view
to the other?
Edit
Since both the report_ccis(...)
& the report_overview(...)
view return the same template, the HTML for that file is:
{% extends "costing/reports_tabbed.html" %}
{% load staticfiles utilities %}
{% block title2 %}
| Pre-deposit reports
{% endblock title2 %}
{% block page_title %}
<a id="topbar-shortcuts" data-view-url="{% url 'hub:open_sidebar' %}?app={{app.name}}&p={{project.id}}&po=1">
<span class="m-l-md">Reports</span> <img class="icon open text-sm m-l-md" src="{% static 'img/down-lt.png' %}" >
</a>
<div id="topbar-results" class="{{app.color}}" style="display:none;"></div>
{% endblock page_title %}
{% block tabs %}
{% with 'Overview, Construction budget, Schedule of works, Client choice items'|listify as tabs %}
{% for tab_name in tabs %}
{% with forloop.counter as tab %}
{% if not tab == active_tab|add:0 %}<a class="tab" href="{% url 'costing:report_tabbed' project.id %}?tab={{tab}}">{% else %}<a class="active tab">{% endif %}{{tab_name}}</a>
{% endwith %}
{% endfor %}
{% endwith %}
{% endblock tabs %}
This HTML is displaying a 'tabbed- view' page element, and what I want to do is copy the contents from the tab displayed by the report-ccis(...)
view to the tab displayed by the report-overview(...) view, also keeping all of the information currently displayed by the
report-overview(...)` view there.
Edit
Ah, actually, I've just spotted that although both views
return the same template, there is a report_ccis.html
file in my project structure, which has the following code:
{% extends "pdf_base.html" %}
{% load money_handling %}
{% block content_overview %}
{% endblock content_overview %}
{% block content_construction %}
{% endblock content_construction %}
{% block content_schedule_of_works %}
{% endblock content_schedule_of_works %}
{% block content_report_by_class %}
{% endblock content_report_by_class %}
{% block content_ccis %}
{{block.super}}
{% endblock content_ccis %}
and the else
statement of the if
in the report_overview(...)
view has the line:
context['html'] = render_to_string('costing/report_ccis.html', context)
which I guess is where/ how this 'tabbed' view part of the HTML file is being changed when that tab is selected...?
How would I add this content to the report-overview
tab of the tabs
block in the HTML?:
{% block tabs %}
{% with 'Overview, Construction budget, Schedule of works, Client choice items'|listify as tabs %}
{% for tab_name in tabs %}
{% with forloop.counter as tab %}
{% if not tab == active_tab|add:0 %}<a class="tab" href="{% url 'costing:report_tabbed' project.id %}?tab={{tab}}">{% else %}<a class="active tab">{% endif %}{{tab_name}}</a>
{% endwith %}
{% endfor %}
{% endwith %}
{% endblock tabs %}
Edit
I've just spotted that there's a view for the 'tabbed' report area on the HTML page, it's defined with:
def report_tabbed(request, project_id):
project = Project.objects.get(id=project_id)
tab = request.GET.get('tab', '1')
tab_map = {
'1': reverse('costing:report_overview', args=[project.id]),
'2': reverse('costing:report_construction', args=[project.id]),
'3': reverse('costing:budget', args=[project.budget_overview.version.pk])+"?report=1",
# '4': reverse('costing:report_by_class', args=[project.id]),
'4': reverse('costing:report_ccis', args=[project.pk]),
}
return HttpResponseRedirect(tab_map[tab])
It seems that this view
is what's used to switch between what reports are displayed in the 'tabbed' area of the the page. Is there a way to merge the '4':reverse('costing:report_ccis', args=[project.pk]),
into the '1':reverse('costing:report_overview', args=[project.id]),
?
Upvotes: 0
Views: 226
Reputation: 32347
The problem you describe – duplicated code – is one of many common problems addressed by refactoring. The refactoring action to apply here is called Extract Method.
For shared code, extract the common code to a separate function and call that function from all the different places that need it.
For shared template content, extract the common content to a separate template file and {% include … %}
that template from all the different places that need it.
Upvotes: 1