1

I'm asking how I can pick up a for loop in my django class based view to my HTML template.

User can check one or multiple checkboxe(s) and I would like to display informations for each checked checkboxes.

In my view I have :

checkbox_list = self.request.GET.getlist('PUBSDChoice') #Get object id checked by user
context_data['checkbox_list'] = checkbox_list

for checkbox in checkbox_list:
    pubsd = Publication.objects.get(id=checkbox)  
    get_request = Download.objects.filter(pub__publication__id=pubsd.id).count()

    context_data['pubsd'] = pubsd
    context_data['get_request'] = get_request

Now, in my template I have :

<table>
    <tbody>
    <tr>
        <th>{% trans 'Publication ID' %}</th>
        <th>{% trans 'Requests' %}</th>
    </tr>
    {% for item in checkbox_list %} # I'm not sure for this loop
    <tr>
        <td>{{ pubsd.pub_id }}</td> #Do I have to add item.??
        <td>{{ get_request }}</td>
    </tr>
    {% endfor %}
    </tbody>
</table>

Thank you very much

EDIT :

This is my real code with all querysets inside my view :

checkbox_list = self.request.GET.getlist('PUBSDChoice')
context_data['checkbox_list'] = checkbox_list

for checkbox in checkbox_list:
    pubsd = Publication.objects.get(id=checkbox)  # display publication id

    # Count number of requests in download table for checked publication
    get_request = Download.objects.filter(pub__publication__id=pubsd.id).count()
    #Get sum of publication usage (= downloads) for checked publication
    get_download = Download.objects.filter(pub__publication__id=pubsd.id).aggregate(get_sum_usage=Sum('usage'))

    # Get country which maximum download the checked publication
    get_country = Country.objects.filter(download__pub__publication__id=pubsd.id).annotate(
                ndown=Count('download')).order_by('-ndown').first()
    # Get customer which maximum download the checked publication
    get_customer = Download.objects.filter(pub__publication__id=pubsd.id).values('email').order_by(
                'email').annotate(count_email=Count('email')).first()
    # Get the best downloaded format for the checked publication
    get_format = Download.objects.filter(pub__publication__id=pubsd.id).values('pub__format').annotate(
                format_count=Count('pub__format')).order_by('-format_count').first()

    context_data['pubsd'] = pubsd
    context_data['get_request'] = get_request
    context_data['get_download'] = get_download
    context_data['get_country'] = get_country
    context_data['get_customer'] = get_customer['email']
    context_data['get_format'] = get_format['pub__format']

And this is exactly my model :

class Publication(models.Model):
    pub_id = models.CharField(max_length=10, verbose_name=_('publication ID'), default='')
    title = models.CharField(max_length=512, verbose_name=_('publication title'), null=False, unique=True)
    category = models.ForeignKey(Category, verbose_name=_('category'), null=False, related_name='publication')
    nb_document = models.IntegerField(verbose_name=_('number of documents'), default=0)
    nb_download = models.IntegerField(verbose_name=_('number of downloads'), default=0)
    new_publication = models.BooleanField(verbose_name=_('new publication'), default=True)

class Document(models.Model):
    language = models.CharField(max_length=2, verbose_name=_('language'), choices=LANGUAGE_CHOICES, null=False)
    format = models.CharField(max_length=10, verbose_name=_('format'), choices=FORMAT_CHOICES, null=False)
    title = models.CharField(max_length=512, verbose_name=_('document title'), null=False)
    publication = models.ForeignKey(Publication, verbose_name=_('publication title'), null=False,
                                    related_name='documents')
    nb_download = models.IntegerField(verbose_name=_('number of downloads'), default=0)

class Download(models.Model):
    email = models.CharField(max_length=150, verbose_name=_('e-mail'), null=False)
    country = models.ForeignKey(Country, verbose_name=_('country'), related_name='download')
    pub = models.ForeignKey(Document, verbose_name=_('Publication ID'), null=False)
    usage = models.IntegerField(verbose_name=_('usage'), default=0)

class Customer(models.Model):
    email = models.CharField(max_length=150, verbose_name=_('e-mail'), null=False)
    country = models.ForeignKey(Country, verbose_name=_('country'))
    institution = models.CharField(max_length=255, verbose_name=_('institution'), null=True)

As I said previously, for one checked publication it works fine, but when I want to check multiple publications, it does't work.

If someone could help me to convert this, it will be super ! Else I will try to use the good answer previously done to do that :)

2
  • Here you override the context keys in each iteration. But nevertheless, don't perform the queries in a for loop, use .annotate(..). Commented Oct 4, 2018 at 9:47
  • You're right, but if user selects multiple checkboxes, I have to display some queryes for the first checked object, then the second one etc .. I have other queries with .annotate but not all in the for loop Commented Oct 4, 2018 at 9:50

1 Answer 1

2

Here you each time overwrite the previous value of the key. As a result in the final context_data contains only values extracted in the last iteration.

checkbox_list = self.request.GET.getlist('PUBSDChoice')
context_data['checkbox_list'] = checkbox_list

context_data['pubsd'] = Publication.objects.filter(
    id__in=checkbox_list
).annotate(
    ndown=Count('publication__download')  # or something related
)

We thus filter the queryset such that it only contains Publications with the id in the list, and we annotate with the number of downloads (It is possible that the expression is a bit different, since you did not include the models.py).

The above will not be sorted according to the checkbox_list. If that is a requirement, you can post-sort it.

In the template, you can then render this with:

{% for item in pubsd %}
<tr>
    <td>{{ item.pub_id }}</td>
    <td>{{ item.ndown }}</td>
</tr>
{% endfor %}

We thus iterate over the pubsd queryset, and for each item (this is a Publication object), we render item.pub_id, and item.ndown.

Sign up to request clarification or add additional context in comments.

8 Comments

Nice explanation, now I have to see how I can handle your answer with my code. I could show you my entire querysets with models but it will be a bit hard because I have 7-8 different querysets.
@user10390326: do these querysets "interact". The fact that there are other qs, is usually not problematic.
Ok, I have to look how I can convert my qs with your code ! I will accept your answer when it will work ;)
I made something, maybe I should sent my new queries on Stackoverflow Code Review ? It seems to work, but honnestly I'm not sure that all is good. I valid your answer too ;)
What Django version do you use?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.