Extracting data outside of a DetailView function and using it in urls.py

I have not seen this question asked before and I want to start out by saying that I accept this might be an impossible task.

I’m rendering a pdf, and the name of the pdf in the URL should be the name from a database field called “ncr number” which is actually a string. I’m using a primary key to get the current context of everything. For example if the ncr number was “A109”, then when I open the pdf, the url should be http://localhost:8000/A109.pdf

I should mention that this RecordDetailPage is a html view revealing the information of the database record. There is a button on this page which opens the PDF. The fact that this page opens prior to the pdf led me to believe that this should be possible.

In my views.py file, I am trying to pull this NCR string out of the generic view function “get()”

Code:

class RecordDetailPage(LoginRequiredMixin, DetailView):
model = DashboardModel
template_name = “dashboard/record_detail.html”
context_object_name = ‘record’

def get(self, record, *args, **kwargs):  
    pk = self.kwargs.get('pk')
    record = DashboardModel.objects.get(pk=pk)
    self.object = self.get_object()

    print("test....", self.object)      # "self.object" is the string of text I need 
    print("test....", record.ncr_number)    # I can also get the string I need this way

    global var
    var = record.ncr_number    #I am trying to assign a global variable to extract the string from here

    return super().get(request, *args, **kwargs)

print(var) # This doesn’t work outside the function

urls.py (pseudocode to help you visualize it):

obj = RecordDetailPage()

urlpatterns = [

path('dashboard/record_details/<str:pk>/'+ str( obj.var ) +".pdf", Report.generate, name='run_pdfgen'),

]

If you could shine some light on the matter, that would be great.

This is the wrong approach for this.

Your URL would be something like:

path('dashboard/record_details/<str:pk>/<str:pdf_name>
or
path('dashboard/record_details/<str:pk>/<str:pdf_name>.pdf

It’s up to your view then to interpret or use the variable named pdf_name as needed.

(The whole concept of global variables has no meaning in Django, and, URLs are built internally as URL patterns long before any views are executed.)

1 Like

Thank you for your reply. I too felt that I was approaching this the wrong way.

I’ve promply taken your advice just now and I can see the url working - although what I’m doing on the html button/link is guess work. I may have my jinja2 syntax wrong.

my urls.py path is now:

path('dashboard/record_details/<str:pk>/<str:name>.pdf', ...)

href = "{% url 'run_pdfgen' record.pk record.ncr_number %}"

I also need the primary key on the button as I’m retrieving some database record data on the pdf. I will try and look into this further, thank you Ken.

Side note - when you’re posting single lines of code here, use the backtick - ` at the beginning and end of each line to keep the forum software from removing the < and > symbols (among others) from the post.

Very interesting, I never knew of a use for that keyboard character until now.

It is working.
edit: This is a mock NCR number, just for testing purposes.

I made a reply saying that I got things working, but an automated spam filter removed my post. An image I posted was showing the “NCR number”, but it was a mock number I made up myself. The spam filter must have assumed I was infringing on a companies rights.

I will post again exactly what I’ve done to make this work. Thanks Ken for guiding me in the right direction, I was digging myself into a hole with how I was initially trying to do this.

url path:

path('record_details/<str:pk>/<str:param>.pdf', Report.generate, name='run_pdfgen'),

Jinja2 on the button to pass the arguments (primary key and ncr number):

href="{% url 'run_pdfgen' record.pk record.ncr_number %}"

Now, on my function which returns the HttpResponse, I needed to pass the arguments for the primary key and ncr_number database field by using the names I defined in the url path:

  def generate(request, pk, param):
        meta = DashboardModel.objects.get(pk=pk)
        doc = Report(filename=meta.ncr_number, uuid=pk)
        response = HttpResponse()
        response.content = doc.getBuffer()
        response.headers['Content-Disposition'] = 'inline; filename=' + doc.filename + ".pdf"
        response.headers['Content-Type'] = 'application/pdf'
        response.headers['url-parameter'] = param

        return response

Final notes on this - Everything is now working perfectly.
Django is particular about needing the function argument names exactly as what I wrote in the url path. They can be named anything.
This http response header [‘url-parameter’] is something I defined myself, I could remove this and it would still work.