QuerySet Django, need to get multiple result on one - django

I got this model :
class BfMatchingNafRome(models.Model):
code_naf = models.CharField(null=False,max_length=255)
libelle_naf = models.CharField(null=True,max_length=255)
code_rome = models.CharField(null=True,max_length=255)
I want to put some data in a table.
{% for match in matching %}
<tr>
<th scope="row">{{match.code_naf}}</th>
<td>{{match.libelle_naf}}</td>
<td>
{% for i in match.code_rome %}
{{i}}
{% endfor %}
</td>
{% endfor %}
I use :
matching = BfMatchingNafRome.objects.filter(code_naf__lte=activity.code_activity).order_by('code_naf')
I've tried absolutely all I can find on stack overflow, google, youtube, but I cant link my datas.
I just get, on my view, one line with code_naf - code_rome.
I want one line per code_naf with all code_rome for this code_naf.
I create multiple entries (for an other view I need one data by entry).
But, for this view, I need to receive datas linked.
Thanks for help

code_naf is a CharField so they are compared not by value but lexicographically. For exapmle '9' > '89', since the first characters are '8' and '9', and '8' is first in the alphabet. Be sure that you compare it properly

Related

Table population in html with complex for loop

Why doesn't this work:
{% for a,b,c,d,e in test1,test2,test3,test4,test5 %}
<tr>
<td>{{a}}</td>
<td>{{b}}</td>
<td>{{c}}</td>
<td>{{d}}</td>
<td>{{e}}</td>
</tr>
{% endfor %}
Am I doing this wrong or is this not how this sort of task should be done?
I receive the error:
Could not parse the remainder: ',test2,test3,test4,test5' from 'test1,test2,test3,test4,test5'
My view is like this:
def jobs(request):
test1 = range(10)
test2 = range(10)
test3 = range(10)
test4 = range(10)
test5 = range(10)
context ={
"test1":test1,
"test2":test2,
"test3":test3,
"test4":test4,
"test5":test5,
}
return render(request,"jobs.html",context)
I want a table that shows job number, client, etc.. and I'm just performing tests at the moment with simple ranges to see if this works in concept. But I'm not getting it to work.
So, in production, it test1 might be equal to a list like test1 = ['Job 1','Job 2','Job 3']
In production, I'd hope you have an object model that actually represents the data you are trying to display, then it would just be a very simple task to iterate over a list or queryset of said model.
In your current situation, you could use a mixture of custom template tags (getrange used below is this)
def index(value, arg):
return value[arg]
{% with len=test1|length %}
{% for i in len|getrange %}
<tr>
<td>{{test1|index:i}}</td>
<td>{{test2|index:i}}</td>
<td>{{test3|index:i}}</td>
<td>{{test4|index:i}}</td>
<td>{{test5|index:i}}</td>
</tr>
{% endfor %}
{% endwith %}
Now I hope you can see that the above is incredibly ugly and should be fired into the sun at the first available opportunity.
Instead, make an actual model that represents the data.

Loop over a sorted dictionary a specific number of times in a django template

I have a sorted dictionary that contains sort options:
sort_options = SortedDict([
("importance" , ("Importance" , "warning-sign")),
("effort" , ("Effort" , "wrench" , "effort")),
("time_estimate" , ("Time Estimate" , "time")),
("date_last_completed" , ("Date Last Completed" , "calendar")),
])
I'm displaying these options in my template:
{% for key, icon in sort_options.items %}<!-- Sort Options -->
<a class="btn btn-info" href={{ request.path }}?key={{ key }}&orientation=desc><i class="icon-{{ icon.1 }} icon-large"></i></a>
{% endfor %}
I need to define the 4 sort options, but I only want to display the first 3 (the remaining options are used elsewhere). I also anticipate adding other sort options that I won't need to be displayed. I could write an if statement with a forloop counter to prevent the last option from displaying, but this seems wasteful.
I found this filter but I'm not sure how to combine it with the forloop that needs both the key and the icon data.
How can I write a django template for loop that runs on a dictionary and only loops X number of times?
Similar to Joe's answer, but there's actually a built-in filter slice that'll do this for you:
{% for key, icon in sort_options.items|slice:":3" %}
I think you could do this with a template filter. For example, in:
./mymodules/templatetags/mytags.py
#register.filter
def get_recent(object, token):
"""
Must pass a Option Dictionary
"""
return object.items()[:token]
And then in your template:
{% load mytags %}
{% for option in sort_options|get_recent:3 %}
key: {{ option.0 }}
value: {{ option.1 }}
{% endfor %}
I haven't had a chance to test the above code, but think the logic is sound. Let me know what you think.

Django: How do I get the number of elements returned in a database call?

This seems to me like a very simple question, but I can't seem to find the answer.
All I need to do is determine the number of objects returned by a database query.
The specific circumstance is this: I have a model named Student. This model has a ManyToManyField member named courses_current, which relates to a table of Course models. When I pass my Student instance to a template, I want to be able to do something like the following (the syntax may not be exact, but you'll get the basic idea):
<div id="classes">
{% if student.classes_current.all.size == 0 %}
<h1> HEY! YOU AREN'T TAKING ANY CLASSES! REGISTER NOW!
{% else %}
Here are your courses:
<!-- ... -->
{% endif %}
</div>
Now, I'm fairly certain that X_set.all.size is not a real thing. In the manage.py shell I can just use len(student.classes_current.all()), but I don't know of any way to use built-in functions, and "dictionary-like objects" don't have .size() functions, so I'm at a loss. I'm sure there's a very simple solution (or at least I hope there is), but I can't seem to find it.
{{ student.classes_current.all.count }} but be warned that it doesn't fetch the objects so you will need to do a separate query if you want to loop over them.
If you need loop over the classes for tag has way to get what you need.
{% for cl in student.current_classes.all %}
{{ cl }}
{% empty %}
<h1>Hey! ...</h1>
{% endfor %}
Documentation https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs#for-empty

Django template: Ordering dictionary items for display

I am making a website that displays a user's chosen youtube videos. A user can enter a comment for each video.
I want to display (in this order):
User comment
video title
I have already made the view and have created the following list of dictionary items. Each one represents one video. I send this to my html page:
[
{"my_own_object": vid_obj1, "youtube_obj": obj1}
{"my_own_object": vid_obj2, "youtube_obj": obj2}
]
"youtube_obj" is the object supplied by youtube, which contains the url, title, rating, etc. "my_own_object" contains the user's comments as well as other information.
I iterate over the list and get one dictionary/video. That's fine. Then I need to display the video's information:
{% for key,value in list.items %}
{% if key = "my_own_object" %}
<div>
<p>{{value.user_comment}}</p>
</div>
{% endif %}
{% if key = "youtube_obj" %}
<div>
<p> {{value.media.title.text}}</p>
</div>
{% endif %}
{% endfor %}
This works, except that, because I cannot determine the dictionary order, I might end up with:
Video title
User comment
I thought I could get around this by assigning variables (and then printing the values in the proper order), and am still reeling from the fact that I cannot assign variables!
So, how can I get around this? Can I pluck the key/value that I need instead of iterating over the dictionary items - I tried looking for ways to do this, but no luck. Any other ideas? (I need to pass both video objects as I may need more information than comment and title, later.)
You can use dictionary keys directly:
{% for item in list %} {# PS: don't use list as a variable name #}
<p>{{item.my_own_object.user_comment}}</p>
<p>{{item.youtube_obj.media.title.text}}</p>
{% endfor %}
Just iterate twice. Once for the videos, and once again for the comments. Or, split them into their own dictionaries that are passed through to the template. That's probably a better option, as you avoid iterating twice over the dict. For very small dicts this will be no problem. For larger ones, it can be a problem.

Django: Add number of results

I'm displaying the number of search results, however, i do more than one search.
So to display the number of results i'd have to add them up.
So i've tried this:
<p>Found {{ products|length + categories|length + companies|length }} results.</p>
But i get an error.
How do i do this?
Django templates do not support arithmetic operators. However you can use the add filter. I think you need something like this:
<p>Found {{ products|length|add:categories|length|add:companies|length }} results.</p>
Alternatively you should calculate the total in the view and pass it pre-calculated to the template.
EDIT: Further to the comments, this version should work:
{% with categories|length as catlen %}
{% with companies|length as complen %}
<p>Found {{ products|length|add:catlen|add:complen }} results.</p>
{% endwith %}
{% endwith %}
However, this feels very hacky and it would be preferable to calculate the figure in the view.
I would do this in your view when you are creating your context dictionary:
'result_count': len(products) + len(categories) + len(companies)
Then, in your template, just use:
<p>Found {{ result_count }} results.</p>
I'd like to point that Van Gale's answer is not optimal.
From the QuerySet API documentation, you should use query.count() rather than len(query)
A count() call performs a SELECT COUNT(*) behind the scenes, so you
should always use count() rather than loading all of the record into
Python objects and calling len() on the result (unless you need to
load the objects into memory anyway, in which case len() will be
faster).
So the answer should be:
In the view:
'result_count': products.count() + categories.count() + companies.count()
The template remains unchanged