Home > Software engineering >  Django pdf template count severity per row
Django pdf template count severity per row

Time:12-17

I am using Django but I am stuck with the PDF report. There are three severity which are "Damage to Property", "Fatal" and "Non-Fatal". Download of PDF is working but but in my PDF report, I would want for every distinct address, it will count each severity (the number of Damage to Property, Fatal or Non-fatal). How can I achieve this?

This is what the table will look like:

Date | Time | Address | Damage to Property | Fatal | Non-Fatal

Model

class IncidentGeneral(SoftDeleteModel):
PENDING = 1
APPROVED = 2
REJECTED = 3
STATUS = (
    (PENDING, 'Pending'),
    (APPROVED, 'Approved'),
    (REJECTED, 'Rejected')
)

IF_DUPLICATE = (
    ('Duplicate', 'Duplicate'),
    ('Possible Duplicate', 'Possible Duplicate'),
    ('Not Duplicate', 'Not Duplicate')
)

WEATHER = (
    ('Clear Night', 'Clear Night'),
    ('Cloudy', 'Cloudy'),
    ('Day', 'Day'),
    ('Fog', 'Fog'),
    ('Hail', 'Hail'),
    ('Partially cloudy day', 'Partially cloudy day'),
    ('Partially cloudy night', 'Partially cloudy night'),
    ('Rain', 'Rain'),
    ('Rain', 'Rain'),
    ('Wind', 'Wind'),
)

LIGHT = (
    ('Dawn', 'Dawn'),
    ('Day', 'Day'),
    ('Dusk', 'Dusk'),
    ('Night', 'Night'),
)

SEVERITY = (
    ('Damage to Property', 'Damage to Property'),
    ('Fatal', 'Fatal'),
    ('Non-Fatal', 'Non-Fatal'),
)

user = models.ForeignKey(User, on_delete=models.CASCADE, editable=False, null=True, blank=True)
generalid = models.CharField(max_length=250, unique=True, null=True, blank=True)
upload_id = models.ForeignKey(UploadFile, on_delete=models.CASCADE, editable=False, null=True, blank=True)
description = models.TextField(max_length=250, blank=True)
address = models.CharField(max_length=250)
country = models.CharField(max_length=50, blank=True, null=True)
state = models.CharField(max_length=250, blank=True, null=True)
city = models.CharField(max_length=50, blank=True, null=True)
pin_code = models.CharField(max_length=6, blank=True, null=True)
latitude = models.FloatField(max_length=20, blank=True, null=True)
longitude = models.FloatField(max_length=20, blank=True, null=True)
geo_location = gismodels.PointField(blank=True, null=True, srid=4326) # New field
upload_photovideo = models.FileField(upload_to=incident_image_upload_path, blank=True, null=True)
date = models.DateField(auto_now_add=False, auto_now=False)
time = models.TimeField(auto_now_add=False, auto_now=False)
status = models.PositiveSmallIntegerField(choices=STATUS, blank=True, null=True)
duplicate =  models.CharField(choices=IF_DUPLICATE,max_length=250, blank=True, null=True)
duplicate_general =  models.ForeignKey('incidentreport.IncidentGeneral', on_delete=models.CASCADE, null=True, blank=True)
accident_factor = models.ForeignKey(AccidentCausation, on_delete=models.SET_NULL, blank=True, null=True)
collision_type = models.ForeignKey(CollisionType, on_delete=models.SET_NULL, blank=True, null=True)
crash_type = models.ForeignKey(CrashType, on_delete=models.SET_NULL, blank=True, null=True)
weather =  models.CharField(choices=WEATHER, max_length=250,blank=True, null=True)
light =  models.CharField(choices=LIGHT,max_length=250, blank=True, null=True)
severity = models.CharField(choices=SEVERITY, max_length=250, blank=True, null=True)
movement_code = models.CharField(max_length=250, blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)

VIEWS

def GenerateInvoiceLocation(request):
try:
    if request.method == 'POST':
        fromdate = request.POST.get('fromdate')
        todate = request.POST.get('todate')
        report = GenerateReport(user=request.user, fromdate=fromdate, todate=todate, report="Location PDF")
        report.save()
        
    print(fromdate, todate)

    # incident_general_accident = IncidentGeneral.objects.filter(user_report__status = 2).values('accident_factor__category').annotate(Count('severity'), filter=Q(severity='Damage to Property'))
    incident_general_accident = IncidentGeneral.objects.filter(status = 2, date__range=[fromdate, todate ]).distinct('address', 'latitude', 'longitude')
    incident_general_accident1 = IncidentGeneral.objects.filter(status = 2,severity='Fatal', date__range=[fromdate, todate ] ).annotate(Count('severity'))
    incident_general_accident2 = IncidentGeneral.objects.filter(status = 2,severity='Damage to Property', date__range=[fromdate, todate ] ).annotate(Count('severity'))
    incident_general_accident3 = IncidentGeneral.objects.filter(status = 2,severity='Non-Fatal', date__range=[fromdate, todate ] ).annotate(Count('severity'))
    incident_general_classification = IncidentGeneral.objects.filter(status = 2, severity="Damage to Property", date__range=[fromdate, todate ]).distinct('address', 'latitude', 'longitude')
    incident_general_collision = IncidentGeneral.objects.filter(status = 2, severity="Damage to Property", date__range=[fromdate, todate ]).distinct('address', 'latitude', 'longitude') #you can filter using order_id as well
    
    
    report1 = GenerateReport.objects.all().order_by('-created_at')[:1]
except:
    return HttpResponse("505 Not Found")
data = {
    'incident_general_accident': incident_general_accident,
    'incident_general_classification': incident_general_classification,
    'incident_general_collision': incident_general_collision,
    'incident_general_accident1': incident_general_accident1,
    'incident_general_accident2': incident_general_accident2,
    'incident_general_accident3': incident_general_accident3,
    'report1':report1
        # 'amount': order_db.total_amount,
}
pdf = render_to_pdf('pages/generate_report_pdf_location.html', data)
    #return HttpResponse(pdf, content_type='application/pdf')

    # force download
if pdf:
    response = HttpResponse(pdf, content_type='application/pdf')
    filename = "Location.pdf" #%(data['incident_general.id'])
    content = "inline; filename='%s'" %(filename)
        #download = request.GET.get("download")
        #if download:
    content = "filename=%s" %(filename)
    response['Content-Disposition'] = content
    return response
    # return HttpResponse("Not found")
return render(request, 'pages/generate_report_sa.html')

HTML

<table  style="width:100%">
  <h3>{{report1.fromdate}} {{report1.todate}}</h3>
      <thead>
          <tr>
            <th scope="col">DATE</th>
            <th scope="col">TIME</th>
            <th scope="col">ADDRESS</th>
              
              {% comment %} <th scope="col">ACCIDENT CAUSATION SUB-CATEGORY</th> {% endcomment %}
              <th scope="col">DAMAGE TO PROPERTY</th>
              <th scope="col">FATAL</th>
              <th scope="col">NON-FATAL</th>
          </tr>
      </thead>
      <tbody>
          {% for i in incident_general_accident %}
        
          <tr>
            <td scope="row">{{i.date}}</td>
            <td scope="row">{{i.time}}</td>
            <td scope="row">{{i.address}}</td>
              {% comment %} <td scope="row">{{i.accident_subcategory.sub_category}}</td> {% endcomment %}
              {% if severity == "Damage to Property"%}
              <td>{{i.severity | length}}</td>
              {% endif %}
              {% if severity == "Fatal"%}
              <td>{{i.severity | length}}</td>
              {% endif %}
              {% if severity == "Non-Fatal"%}
              <td>{{i.severity | length}}</td>
              {% endif %}
             
       
          </tr>
          {% endfor %}

          <tr>
              <td scope="row"></td>
              <td>TOTAL: </td>
              <td>{{incident_general_accident | length}}</td>
              
          </tr>
      </tbody>
  </table> 

CodePudding user response:

you can of course do it by using Django annotate and Q Djagno aggregation

But, first of all, it is a good behaviour to use related_name in your ForeignKey field :

user = models.ForeignKey(User,related_name='incident_generals' on_delete=models.CASCADE, editable=False, null=True, blank=True)

By this way you can retrieve all related IncidentGeneral for a user by doing : user.incident_generals.all(). It is possible without that but it is more suitable.

Next: If you want to retrieve all IncidentGeneral for a user with the count off severity status then you do :

from django.db.models import Count, Q
count_damage_to_property = Count('IncidentGeneral', filter=Q(severity='Damage to Property'))
count_fatal = Count('IncidentGeneral', filter=Q(severity='Fatal'))
count_non_fatal = Count('IncidentGeneral', filter=Q(severity='Non-Fatal'))
user_incident_generals = user.incident_generals.annotate(damage_to_property=count_damage_to_property).annotate(fatal=count_fatal).annotate(non_fatal=count_non_fatal)

You can now acces each user IncidentGeneral count by severity level like this

for user_incident in user_incident_generals:
    nb_fatal = user_incident.fatal
    nb_non_fatal = user_incident.non_fatal

You can now do what you whant. Hope it will help you

  • Related