Counting users by the type in their profile I'm creating a django web application and I would like to know how to shorten this code.

I have a model where every user has a typeOfPerson (Student, Teacher, Guest ...) and I want to count these types.

@register.simple_tag()
def get_stats_type(choice):
    items = []
    for vote in choice.vote_set.all():
        if vote.user not in items:
            items.append(vote.user)

    types = {}
    for user in items:
        if user.userprofile.typeOfPerson not in types:
            types[user.userprofile.typeOfPerson] = Vote.objects.filter(Choice=choice).count()

    percent = 0
    for type, value in types.items():
        percent += value
    if percent == 0:
        percent = 1

    values = {}
    for type, value in types.items():
        if type not in values:
            values[type] = value / percent * 100

    return values
I'm creating a django


You probably mean that you're creating a web application on top of Django.

Given this code:

items = []
for vote in choice.vote_set.all():
    if vote.user not in items:
        items.append(vote.user)


you should instead be able to do

items = set(v.user for v in choice.vote_set.all())


This achieves the same goal - creating a collection of unique entries. The only catch is that order will not be preserved. If that's important, you'll have to do something more clever.

This:

types = {}
for user in items:
    if user.userprofile.typeOfPerson not in types:
        types[user.userprofile.typeOfPerson] = Vote.objects.filter(Choice=choice).count()


apparently makes an effort to avoid overwriting entries in a dictionary, but I'm not clear on whether that's necessary. If order doesn't matter, and if items all have equal priorities, then you can make this much more simple:

n_votes = Vote.objects.filter(Choice=choice).count()
types = {u.userprofile.typeOfPerson: n_votes for u in items}


This also assumes that Vote.objects.filter(Choice=choice).count() doesn't vary at all over the course of the loop.

This:

percent = 0
for type, value in types.items():
    percent += value
if percent == 0:
    percent = 1


can be:

percent = max(1, sum(types.values()))


This:

values = {}
for type, value in types.items():
    if type not in values:
        values[type] = value / percent * 100


can probably just be

values = {t: v/percent * 100 for t, v in types.items()}


Again, it's not clear why all three of your loops are attempting to be careful in avoiding rewriting values, or what the priority system should be.