Search code examples
djangomodel

Django: Why does this query get the pk numbers instead of the names when downloading an excel?


Beginner at django here: I have the following code for downloading an excel document from my homepage:

class ExcelDownloadAllView(TemplateView):
    def get(self, request, *args, **kwargs):
        columns = ['Project Number', 'Assignee', 'Priority', 'Status', 'title','Summary', 'created_by']
        rows = BugTracker.objects.all().values_list('project_number','assignee','priority','status', 'title', 'summary', 'author', )
        filename ='All_Projects.xls'
        return create_sheet_response(filename, columns, rows)

def create_sheet_response(filename, columns, rows):
    response = HttpResponse(content_type='application/ms-excel')
    response['Content-Disposition'] = f'attachment; filename={filename}'

    wb = xlwt.Workbook(encoding='utf-8')
    ws = wb.add_sheet('All Projects Data') # this will make a sheet named Projects Data

# Sheet header, first row
row_num = 0

font_style = xlwt.XFStyle()
font_style.font.bold = True

for col_num in range(len(columns)):
    ws.write(row_num, col_num, columns[col_num], font_style) # at 0 row 0 column 

# Sheet body, remaining rows
font_style = xlwt.XFStyle()
for row in rows:
    row_num += 1
    for col_num in range(len(row)):
        ws.write(row_num, col_num, row[col_num], font_style)

wb.save(response)

return response

#models
class Developer(models.Model):
    firstname = models.CharField(max_length=30, default="To be")
    lastname = models.CharField(max_length=30, default="Assigned")
    email = models.EmailField(blank=True)

    def __str__(self):
        return self.firstname + " " + self.lastname

    def get_absolute_url(self):
        return reverse("developer_list")


class BugTracker(models.Model):
    project_number= models.IntegerField(primary_key=True)
    assignee=  models.ForeignKey(Developer, on_delete=models.CASCADE, null=True)
    priority = models.CharField(max_length=10, choices=priority_choices)
    title = models.CharField(max_length=70)
    summary=models.TextField()
    status= models.CharField(max_length=20, choices=progress, default="Open")
    author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, null=True)
    created_at=models.DateTimeField(default=timezone.now)
    updated_at=models.DateTimeField(auto_now=True)

    def __str__(self):
        return self.summary

    def get_absolute_url(self): 
        return reverse("bug_list")

It creates the excel file successfully, but it downloads the foreign keys from my models using the pk/id number instead of the name associated with that pk number. So in this example, the "assignee" and "author" fields show pk numbers related to models that I have. How can I fix this?

Also, is there way to download "DateTime Fields? Whenever I try adding "created_at/updated_at" field, it gives me an error "Cannot resolve keyword 'created at' into field. Choices are..." Thank you! Help with either question is appreciated.


Solution

  • Instead of author you can use author__FIELDNAME eg author__first_name or author__email

    For datetime fields i need more details, generally, doing such things is better using a proper serialization with marshmallow, pydantic or Drf serializers so that you will able to customize the desired output. Then you pass the queryset to the serializer and you get back the serialized data as list of dicts.