Как показать кнопку в панели администратора с определенным форматом ссылки
У меня есть поле заказа в моих моделях
class Order(models.Model):
STATUS = (
('Unpaid', 'Unpaid'),
('Paid', 'Paid'),
('Accepted', 'Accepted'),
('Completed', 'Completed'),
('Cancelled', 'Cancelled'),
)
user = models.ForeignKey(Customer, on_delete=models.SET_NULL, null=True)
payment = models.ForeignKey(Payment, on_delete=models.SET_NULL, blank=True, null=True)
payment_method = models.CharField(max_length=100,blank=True,null=True)
order_number = models.CharField(max_length=20,blank=True, null=True)
first_name = models.CharField(max_length=50,blank=True, null=True)
last_name = models.CharField(max_length=50,blank=True, null=True)
phone = models.CharField(max_length=15,blank=True, null=True)
email = models.EmailField(max_length=50,blank=True, null=True)
address_line_1 = models.CharField(max_length=50,blank=True, null=True)
address_line_2 = models.CharField(max_length=50, blank=True, null=True)
country = models.CharField(max_length=50,blank=True, null=True)
state = models.CharField(max_length=50,blank=True, null=True)
city = models.CharField(max_length=50,blank=True, null=True)
order_note = models.CharField(max_length=100, blank=True, null=True)
order_total = models.FloatField(blank=True, null=True)
tax = models.FloatField(blank=True, null=True)
status = models.CharField(max_length=10, choices=STATUS, default='New')
ip = models.CharField(blank=True, null=True, max_length=20)
is_ordered = models.BooleanField(default=False)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
pin_code = models.CharField(max_length=7,blank=True,null=True)
bill_url = models.CharField(max_length=100,blank=True,null=True,)
def full_name(self):
return f'{self.first_name} {self.last_name}'
def full_address(self):
return f'{self.address_line_1} {self.address_line_2}'
def __str__(self):
return self.order_number
на основе id url у меня есть конечная точка /order/download-bill/{order.id}
Так что я хочу, чтобы в моей админ панели у админа была кнопка, на которую он нажмет и url триггер, который будет автоматически загружать счет
Вам нужно настроить URL обратного вызова ссылки для этой конкретной цели, просто настройте шаблон для ссылки на кнопку.
Шаг 1: Необходимо настроить download_pdf_button.html для добавления кнопки в админке
{% extends 'admin/change_form.html' %}
{% block submit_buttons_bottom %}
{{ block.super }}
<div class="submit-row">
<input type="submit" value="Download PDF" name="_download_pdf">
</div>
{% endblock %}
Шаг 2. Настройте форму изменения Отклика объекта модели Внутри файла admin.py Связанные импорты :
xhtml2pdf - внешний Pypi пакет для установки ,
pip install xhtml2pdf
Также, настройте link_callback в том же каталоге, где находится файл admin.py. создайте файл link_callback.py и добавьте в него этот код.
import os
from django.conf import settings
from django.contrib.staticfiles import finders
def link_callback(uri, rel):
"""
Convert HTML URIs to absolute system paths so xhtml2pdf can access those
resources
"""
result = finders.find(uri)
if result:
if not isinstance(result, (list, tuple)):
result = [result]
result = list(os.path.realpath(path) for path in result)
path = result[0]
else:
sUrl = settings.STATIC_URL # Typically /static/
sRoot = settings.STATIC_ROOT # Typically /home/userX/project_static/
mUrl = settings.MEDIA_URL # Typically /media/
mRoot = settings.MEDIA_ROOT # Typically /home/userX/project_static/media/
if uri.startswith(mUrl):
path = os.path.join(mRoot, uri.replace(mUrl, ""))
elif uri.startswith(sUrl):
path = os.path.join(sRoot, uri.replace(sUrl, ""))
else:
return uri
# make sure that file exists
if not os.path.isfile(path):
raise Exception(
'media URI must start with %s or %s' % (sUrl, mUrl)
)
return path
Импортировать их.
from django.template.loader import get_template
from django.http import HttpResponse
from xhtml2pdf import pisa # import python module
from .link_callback import link_callback
Необходимо настроить Model Admin
class OrderAdmin(admin.ModelAdmin):
# ...
change_form_template = "download_pdf_button.html" # That will be the button that can be seen in the end of change form.
def response_change(self, request, obj):
template_path = 'order_pdf.html' # template to be rendered in pdf
context = {
'order_number ': obj.order_number,
# add more things for the template if needed
}
# Create a Django response object, and specify content_type as pdf
response = HttpResponse(content_type='application/pdf')
response['Content-Disposition'] = 'attachment; filename="OrderPDF.pdf"'
# find the template and render it.
template = get_template(template_path)
html = template.render(context) # close output file
# create a pdf
pisa_status = pisa.CreatePDF(
html, dest=response, link_callback=link_callback)
# if error then show some response
if pisa_status.err:
return HttpResponse('We had some errors <pre>' + html + '</pre>')
return response
Шаг: 3 Настройка шаблона загрузки для заказа
В этом примере я использовал его как order_pdf.html
<!DOCTYPE html>
<html>
<head>
<title>Order PDF</title>
</head>
<body>
<h1>{{ order_number }}</h1>
</body>
</html>
Теперь у вас будет кнопка в конце формы изменений, которая будет выдавать файл pdf при нажатии
Используя аналогичный способ, вы можете настроить его в любом месте в django. Если вам не нужна кнопка, а нужно просто вставить ее в представление, то вы можете легко воспроизвести это, используя данный подход.