Django how to pass two different query in same view for export csv file from two different html page?

Viewed 125

I am using this query patient = Patient.objects.all() for exporting all objects in csv file and this query Patient.objects.filter(slug=slug) for exporting single objects in csv. The main problem it's downloading single objects and all objects together in a csv file. I want single object query only run when I will be on details page and all objects query will be run when I will be on list page. here is my code:

here is my code:

models.py

class Patient(models.Model):
      patient_name = models.CharField(max_length=150)
      patient_id = models.CharField(max_length=100,blank=True,null=True)
      date_of_birth = models.DateField()
      age = models.CharField(max_length=100,blank=True,null=True)
      phone =  models.CharField(max_length=100)
      email = models.EmailField(blank=True,null=True)
      slug = models.SlugField(max_length=255,unique=True,blank=True,null=True)

views.py

    def exportcsv(request): #I am exporting csv file from this view
        response = HttpResponse(content_type='text/csv') 
        response ['Content-Disposition'] = 'attachment; filename=PatientData'+str(datetime.datetime.now())+'.csv'
    
        writer = csv.writer(response)
        writer.writerow(['patient_name'])
        
        all_patient_objects = Patient.objects.all() #exporting all objects
        single_patients_objects = Patient.objects.filter(slug=slug) #exporting single objects 

        for i in single_patients_objects: #want to run this loop only in details page
            print(i.patient_name)
            writer.writerow([i.patient_name])

        for i in all_patient_objects: #want to run this loop only in list page
            print(i.patient_name)
            writer.writerow([i.patient_name])

        return response

#urls.py

path('all-patient/',views.AllPatient,name='all-patient'), #list page
path('<slug:slug>/patient-details/',PatientDetails.as_view(),name='patient-details'),  #details page
path('<slug:slug>/export-csv-patient-data/',views.exportcsv,name='export-csv-patient-data'),

Now it's downloading all objects and single objects together in a single csv file. I want it will download only single objects from details page and all objects from list page.

I want to run this loop only in details page for exporting single object:

for i in single_patients_objects: #want to run this loop only in details page
            print(i.patient_name)
            writer.writerow([i.patient_name])

I want to run this loop only in list page for download all objects:

 for i in all_patient_objects: #want to run this loop only in list page
            print(i.patient_name)
            writer.writerow([i.patient_name])

Basically I have two for loop and want to run only one for loop at a time depend on page .

3 Answers

You need to identify from which page you are coming from when calling this view. One approach could be to parse query_params when calling this view. E.g.:

The export link in your details page:

/patient_name/export-csv-patient-data/?details=True

and in your exportcsv view:

def exportcsv(request):
    details = request.query_params.get('details')

    ...

    if details:
        # Do the stuff for the details export
    else:
        # Do the stuff for the all patients export

The code snippet above works for requests. in th django.restframework. For WSGIRequests:

def exportcsv(request):
    details = request.GET.get('details')
    
    ...
    
    if details:
        # Do the stuff for the details export
    else:
            # Do the stuff for the all patients export

You can add another path for downloading all patient data like this:

urls.py

path('export-csv-patient-data/',views.exportcsv,name='export-csv-patient-data'),
path('export-csv-patient-data/<slug:patient_slug>/',views.exportcsv,name='export-csv-patient-data')
# I have moved slug parameter to end instead of start as that is the convention and have also gave it a meaningful name

views.py

def exportcsv(request, patient_slug=None):
   # rest of the code
   params = {'slug': patient_slug} if patient_slug else {}
   patient_names = Patient.objects.filter(**params).values('patient_name')

   for patient_name in patient_names:
       writer.writerow([patient_name['patient_name']])

   return Response
       

At last I find one of the simplest solution. I just add another non slug url parameter in my urls.py. here is my code:

patient = Patient.objects.filter(slug=slug) #this query for slug url 
all_patient = Patient.objects.all() #this query for non slug url 
    
for i in patient: #this for loop will run for slug url
                   writer.writerow([i.patient_id,i.patient_name,i.date_of_birth,i.age,i.phone,i.email,i.gender,i.country,i.state,i.city,i.zip_code,i.address])

if slug == None: #this for loop only running for non slug url
            for i in all_patient:
                writer.writerow([i.patient_id,i.patient_name,i.date_of_birth,i.age,i.phone,i.email,i.gender,i.country,i.state,i.city,i.zip_code,i.address])

uls.py now just added another non slug url.

 path('export-csv-patient-data/<slug:slug>/',views.exportcsv,name='export-csv-patient-data'),
 path('export-csv-all-data/',views.exportcsv,name='export-csv-all-data'),
Related