Noble-Surfer
Noble-Surfer

Reputation: 3172

Django- how to copy elements from one view to another?

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 thereport-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

Answers (1)

bignose
bignose

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

Related Questions