django "regroup by" controlled from view - django

How do I control by what my list gets regrouped from the view? I have a page with a drop down for attributes the list can be grouped by. Once an attribute selected it goes into the view and it will generate the list - I want the template to pick up the regroup attribute somehow.
{% regroup cities by country as country_list %}
this works, however when I pass the 'country' as a string from the view, it doesn't:
view:
return render_to_response('parts/action_items.html',
{
'action_item_list': action_items,
'view_filter': 'country'
}, template.RequestContext(request))
template:
{% regroup cities by view_filter as country_list %}
What do I pass into it to make it work?

It isn't possible to use a variable when using the template tag, because the regroup attribute is treated as a string.
You could regroup the list in the view instead. Importing the regroup tag in your view might work. If that doesn't, you can implement the functionality yourself. See this question for more info.

I used this django snippet for dynamic_regroup in my custom templatetags and was able to pass in the view_filter to regroup that way (replacing {% regroup ... %} with {% dynamic_regroup ... %}

Related

How do I properly compare two different models based on their field values and output the differences?

I am trying to figure out how to produce the output between two querysets that have similar fields. I have two different models where I keep identical fields, and at times I want to show the differences between these two models. I have researched and successfully used sets and lists in my python code, but I can't quite figure out how to leverage them or determine if I Can. Sets seems to strip out just the field values, and when I try to loop through my sets, it doesn't currently work because it's just the values without the keys.
Example:
class Team(models.Model):
player = models.Charfield
coach = models.Charfield
class TeamCommittee(models.Model):
player = models.Charfield
coach = models.Charfield
I want to be able to query both models at times and be able to exclude data from one model if it exists in the other. I have spent the afternoon trying to use sets, lists, and loops in my django templates but can't quite work this out. I have also tried various querysets using exclude....
I tried something like....
query1 = TeamCommittee.objects.filter(id=self.object.pk).values('coach','player')
query2 = Team.objects.filter(id=self.object.pk).exclude(id__in=query1)
When I use the approach above, I get TypeError: Cannot use multi-field values as a filter value.
I am wondering if I can do this via a query or if I need to dump my querysets and go down a path of manipulating a data dictionary? That seems extreme for what I am trying to do though. This does seem to be a bit more complicated because I am trying to cross reference two different models. If it was the same model this would be a lot easier but it's not an option for this particular use case.
Thanks in advance for any thoughts on the right way to approach this.
If you want to compare on the basis of the ID of both tables, probably you can use this:
teamID = list(Team.objects.all().values_list('id', flat=True))
query1 = TeamCommittee.objects.filter(id__in=teamID)
teamCommitteeID = list(TeamCommittee.objects.all().values_list('id', flat=True))
query2 = Team.objects.filter(id__in=teamCommitteeID)
I was super close...Instead I just did this...
query1 = TeamCommittee.objects.filter(id=self.object.pk).values('coach','player').distinct()
Then in my template I did a very simple....
{% for item in query1.all %}
item
{% endfor %}
Then when I wanted to get the values out of the other queryset I just did the same thing with the loop.
query2 = Team.objects.filter(id=self.object.pk).values('coach','player').distinct()
Then in my template I did a very simple....
{% for item in query2.all %}
item
{% endfor %}
Sometimes simplicity is hard.
The answer above after additional testing only partially worked. I ultimately abandoned that approach and instead incorporated the logic below into my template. I did not need to create separate queries, I just needed to loop through the fields that were already available to me as part of the DetailView I was using....
{% for author in author_detail.author_set.all %}
{% for book in book_detail.book_set.all %}
{% if author.author_name %}
{% if book.book_name in author.book_name %}
{% if author.book_name == book.book_name %}
{% elif author.book_name != book.book_name %}
{{ author.author_name }}
{% endif %}
{% endif %}
{% endif %}
{% endfor %}
{% endfor %}
Thank you to everyone who made suggestions to get me to this point.

django filter and order foreign-foreignkey in a query

I'm looking for a solution to filter and order foreign key of the foreign key of my model.
Let's say I have:
class Song(models.Model):
author = models.CharField(max_length=200,null=False)
class Songbook(models.Model):
songs = models.ManyToManyField(Song)
I'm already able thanks to annotation to sort my songbook query by song count:
context['popular_songbooks_list'] = Songbook.objects.annotate(
favoritesongbook_count=Count('favoritesongbook')).order_by('-favoritesongbook_count')[:10]
Now, I would like to display only the 3 main author contained in each songbook and I didn't find how to do it. Is there a solution using query or do I have to do a post-processing on the query list?
I didn't find an easy way to do it inside the view by annotating the query, but thanks to this post (django regroup and than dictsort by list length) I find a way to rich my goal.
Here is the solution :
From the popular_songbooks_list I showed in my first post, I use the regroup tag in template with custom filter and then slice to 3.
{% regroup songbook.songs.all by author as author_list %}
{% for author in author_list|groups_sort_reversed|slice:":3" %}
{{ author.grouper }}
{% endfor %}
The custom tag :
#register.filter()
def groups_sort_reversed(groups):
groups.sort(key=lambda group: len(group['list']), reverse=True)
return groups
I'm not sure this is the best solution, but it work !

How to get list of multiple choices

I have a problem rendering a template variable for example {{ profile.speciality }}
that resulted in [u'pediatrics'] on the web page, what I actually wanted is simply
pediatrics. The data is coming from MultipleChoiceField and a CheckboxSelectMultiple
widget, because user should be able to select multiple options.
Then i used request.POST.getlist('speciality') to populate data in to the model instance,
for example:
user_profile = UserProfile(speciality=request.POST.getlist('speciality'))
I also tried to iterate over {{ profile.speciality }} in the template but what I am getting is string iteration rather than a list iteration.
I am an absolute beginner, I have no programming experience, pardon me if I did anything stupid, need help desperately, tried everything I could.
thank you
You can use this to render a MultipleChoiceField
{% for speciality in profile.speciality.all %}
{{ speciality }}
{% endfor %}

Django boolean field views+templates

Here is my current setup:
http://dpaste.com/699684/
What I am looking to do is two things:
I want to include a new template if the boolean field value is true, for example
{% if clearance=true %} {% include example.html %} {% endif %}
I think that is easy(ish) but I cant work out how to get the value into a view then out into my template
I want to be able to define a new view called clearance that lists under "/clearance" that lists all products with the clearance boolean filed. I have one base polymorphic model and sevral other models that extend from there, Accessory is just one I have given as an example
This I think maybe slightly harder due to polymorphic, but I could be wrong.
You're pretty much there on including a template for clearance items, you're just not using the right syntax:
{% if object.clearance %}{% include 'example.html' %}{% endif %}
Where product is the current product within the forloop or whatever.
For the clearance view all you need is:
class ProductClearanceView(ListView):
model = Product
template_name = 'products/clearance.html'
def get_queryset(self):
qs = super(ProductClearanceView, self).get_queryset()
return qs.filter(clearance=True)

Django template can't access a form field if it is inside an array

Fairly new to Django here, so I don't know if I'm just not getting it or this is a bug. Let's say I have a form class:
class SurveyTwo(forms.Form):
food = [forms.BooleanField(required=False, initial=False, label="Seafood")]
Then, in the corresponding template, I am trying to access this by typing
{{ form.food.0 }}
When I do this, I get on my page:
<django.forms.fields.BooleanField object at 0x1c5b990>
Not the "Seafood" checkbox I was looking for. I can access the label just fine by doing {{ form.food.0.label }} but the checkbox just appears as that string. Should I be able to do this or not?
Essentially what I am trying to do is to pass an array of checkboxes to my form template, rather than having to define each form variable/field. I want to do this because I'm going to have a large number of checkboxes and want to be able to lay them out in a certain order (with a 2D array), rather than define them and lay them all out manually. If I can't do the above, does anyone know of a simpler solution? Thanks.
Mark
You can register simple template tag:
from django import template
register = template.Library()
#register.simple_tag
def bound_field(form, name):
""" returns bound field """
return form.__getitem__(name)
Then in template you just use:
{% bound_field form <field_name> %}
where is name of field.
If you have dynamicly generated fields that names you don't know you can access to them via fields.keys in this case generating all fields will look like
{% for name in form.fields.keys %}
{% bound_field form name %}
{% endfor %}