Как создать PDF с помощью нажимаемой кнопки на каждом объекте в Django Admin? - PullRequest
0 голосов
/ 28 ноября 2018

Приветствую, могущественное сообщество stackoverflow!

Я не понимаю, как создать столбец в представлении администратора с кликабельными ссылками на каждый объект (он же столбец со ссылками 'create pdf') способом, описанным ниже (def show_phone_url), для этой модели счета на каждый объект для создания PDF с использованием метода рендеринга.

Благодаря соответствующим вопросам здесь мне удалось выяснить, как получить каждый объект модели с Invoice.objects.all() подачей в html-шаблон pdf.html, а затем преобразовать в PDF через xhtml2pdf и io.

Я могу вводить данные одного объекта вручную, помещая Invoice.objects.get (pk = 1) и удаляя jinja {% for invoice in invoices %} {% endfor %}.

Ранее мне удалось создать столбец с интерактивной ссылкой для каждого объекта в админке (для другой модели), который получает значение из атрибута объекта.Вот как это было достигнуто:

from django.utils.html import format_html

    class SipAccountAdmin(admin.ModelAdmin):
        list_display = ('sip_no', 'show_phone_url')

    def show_phone_url(self, obj):
        return format_html("<a href='{url}'>{url}</a>", url=obj.sip_account_ip)
    show_phone_url.short_description = u'Web interface'

Идея состоит в том, чтобы каким-то образом передать pk объекта в параметры класса Pdf, нажав кнопку «Создать PDF» и получить нужный шаблон с данными.

Может случиться так, что подход в корне неверен, и задача может быть выполнена более элегантно.Я заранее извиняюсь, потому что я новичок в django и кодировании, так как это первый пост здесь ...

Некоторые вещи, которые я рассмотрел после бесконечного поиска в сети, дажехотя я и не знаю, как их достичь:

  • Создание настраиваемого действия администратора: объект выбран -> «Создать PDF», выбранный из выпадающего списка действий -> действие приводит кпросмотр с использованием PDF-файла, заполненного данными из выбранного объекта
  • PDF создается, как только создается объект Invoice и сгенерированный файл «заполняет» FileField этого объекта .

Заранее благодарен всем, кто мог бы помочь в этом вопросе.

MODELS.PY

class Invoice(models.Model):
class Meta:
    verbose_name = 'Invoice'
    verbose_name_plural = 'Invoices'

invoice_number = models.BigIntegerField('Invoice number')
invoice_value = models.FloatField('Invoice value')
invoice_date = models.DateField('Date issued')

def __str__(self):
    return str(self.invoice_number)

@staticmethod
def render(path: str, params: dict):
    template = get_template(path)
    html = template.render(params)
    response = BytesIO()
    pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), response, encoding='utf-8')
    if not pdf.err:
        return HttpResponse(response.getvalue(), content_type='application/pdf')

    else:
        return HttpResponse("Error rendering", status=400)

ПРОСМОТРОВ.PY

from invoicesystem.models import *


class Pdf(View):

    def get(self, request):
        invoices = Invoice.objects.all()

        params = {
            'invoices': invoices,
            'request': request
        }

        return Invoice.render('invoicesystem/render/pdf.html', params)

URLS.PY

path('render/pdf/', Pdf.as_view())

Часть шаблона HTML, в которую вставляются данные:

 <table class="table">
        <thead>
        <tr>
            <th>Number</th>
            <th>Date</th>
            <th>Value</th>
        </tr>
        </thead>
        <tbody>
        {% for invoice in invoices %}
            <tr>
                <td>{{ invoice.invoice_number }}</td>
                <td>{{ invoice.invoice_date }}</td>
                <td>{{ invoice.invoice_value }}</td>
            </tr>
        {% endfor %}
        </tbody>
    </table>

Информация для всех, кто борется с кодировкой сгенерированного PDF (кириллица, арабский и т. Д.):

Я нашел довольно много вопросов о «черных квадратах» вместо символов.

Эти параметры правильно отображают символы:

pdf = pisa.pisaDocument(BytesIO(html.encode("UTF-8")), response, encoding='utf-8')

Не забудьте вставить метатег в шаблон:

<meta http-equiv=Content-Type content="text/html;charset=utf-8">

Включить font-face и font-family ввнутренний стиль шаблона с путем;убедитесь, что он доступен, возможно, даже укажите полный путь к выбранному вами шрифту ttf, который поддерживает необходимые символы.Я поместил мой в статическую папку проекта и использовал относительный путь:

@font-face {
  font-family: "Ubuntu"; 
  src: url("project/static/font/Ubuntu/Ubuntu-R.ttf");}
 html,body {
   font-family: 'Ubuntu';
    }
...