Reputation: 5132
I have multiple objects saved in my database but I would only like to show items in my queryset that are unique and if they actually have an item saved.
class Everything(models.Model):
profile = models.ForeignKey(User)
playlist = models.CharField('Playlist', max_length = 2000, null=True, blank=True)
platform = models.CharField('Platform', max_length = 2000, null=True, blank=True)
video = models.CharField('VideoID', max_length = 2000, null=True, blank=True)
def __unicode__(self):
return u'%s %s %s %s' % (self.profile, self.playlist, self.platform, self.video)
playlist2 = Everything.objects.filter(profile=request.user)
<select name ="playlist2">
{% for item in playlist2 %}
<option value="{{item.playlist}}">{{item.playlist}}</option>
{% endfor %}
</select>
There doesn't have to be a playlist because null=True and blank=True. Some of the items in playlist might also be duplicated. How do I show only the distinct items that have values in them?
Upvotes: 0
Views: 1869
Reputation: 36691
You could just filter out all the null and blank objects.
playlist2 = Everything.objects.filter(playlist__isnull=False).exclude(playlist__exact='').distinct()
I edited the above to include handling of blanks, as noted by miki725. There's probably no need for the Q()
functions though. Not that there's anything wrong with Q()
functions, I just try to avoid them where readability could be increased. By DeMorgan's theorem, NOT (playlist is null OR playlist is blank)
is equivalent to (NOT playlist is null) AND (NOT playlist is blank)
. I prefer filter
to exclude
, but exclude
is necessary for the blanks, since there's no unequal field lookup. You could just as well exclude
the null playlists, but what you can't do is combine the excludes into one call, unless you use Q functions, otherwise you get NOT (playlist is null AND playlist is blank)
, which is not equivalent.
Upvotes: 0
Reputation: 27869
You can use exclude
and distinct
queryset functions (docs).
However in your case it is not that simple since your CharField
definitions allow both NULL
(null=True
) and empty string (blank=True
) values. So that means you have to test for two conditions and for that you have to use Q
(docs) objects:
everything = Everything.objects.exclude(Q(playlist=None) | Q(playlist='')).distinct()
That is exactly why Django docs do not recommend to use null=True
for string model fields (docs). Here is excerpt:
Avoid using null on string-based fields such as CharField and TextField unless you have an excellent reason. If a string-based field has null=True, that means it has two possible values for “no data”: NULL, and the empty string. In most cases, it’s redundant to have two possible values for “no data;” Django convention is to use the empty string, not NULL.
If you follow this conversion, then your filter lookup becomes much simpler:
everything = Everything.objects.exclude(playlist=None).distinct()
Upvotes: 1