Как показать кнопку в панели администратора с определенным форматом ссылки

У меня есть поле заказа в моих моделях

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. Если вам не нужна кнопка, а нужно просто вставить ее в представление, то вы можете легко воспроизвести это, используя данный подход.

Вернуться на верх