Приветствую, могущественное сообщество 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';
}