{% extends "base.html" %} {% block title %}Review import{% endblock %} {% comment %} Shared review page for every CSV importer (see CSVContactImportMixin in views.py). Nothing has been written yet at this point: the parsed rows live in a one-time Redis token. Submitting this form applies them; cancelling discards the token. For contact imports (import_supports_duplicates), each possible-duplicate row gets a merge/create choice. Lot/award imports omit that section. {% endcomment %} {% block content %}

Review import{% if filename %} {{ filename }}{% endif %}

Nothing has been imported yet. Review the {{ total }} row{{ total|pluralize }} below, then confirm or cancel.

{% csrf_token %} {% if supports_duplicates and duplicate_rows %}
Possible duplicates — choose what to do with each
{% for row in duplicate_rows %} {% endfor %}
Imported row Matches existing Action
{{ row.fields.name|default:"(no name)" }} {% if row.fields.email %}
{{ row.fields.email }}{% endif %} {% if row.fields.bidder_number %}
Bidder #{{ row.fields.bidder_number }}{% endif %}
{{ row.target_display }}
{% endif %} {% if apply_rows %}
Rows to import
{% for header, key in columns %}{% endfor %} {% for row in apply_rows %} {% for cell in row.cells %}{% endfor %} {% endfor %}
{{ header }}
{% if row.action == "create" %}new {% elif row.action == "update" %}update{% endif %} {{ cell }}
{% endif %} {% if skipped_rows %}
Skipped rows ({{ skipped_rows|length }})
{% for row in skipped_rows %} {% endfor %}
ReasonRow
{{ row.reason }} {% for k, v in row.raw.items %}{{ k }}: {{ v }}{% if not forloop.last %} · {% endif %}{% endfor %}
{% endif %}
{% comment %} Cancel is its own POST (not a plain link) so it hits the _cancel branch and frees the Redis token immediately instead of waiting for it to expire. Both buttons live outside their forms and are wired up with the HTML5 form="" attribute so they can sit together while submitting different forms. {% endcomment %}
{% csrf_token %}
{% endblock %} {% block extra_js %} {% endblock %}