How to pass iterable list of filtered users in Django template using form?

Hi there,

I have a custom user model that has additional filter than the default Django User, viz. is_candidate and is_voter. I want to pass the list of all those users who have is_candidate as True. I tried to make a form of such users and passed that form in template, but I ma getting following error:

TypeError at /votes/
cannot unpack non-iterable User object
Request Method:	GET
Request URL:	http://localhost:8000/votes/
Django Version:	4.0.3
Exception Type:	TypeError
Exception Value:	
cannot unpack non-iterable User object
Exception Location:	C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\widgets.py, line 737, in _choice_has_empty_value
Python Executable:	C:\Users\Admin\AppData\Local\Programs\Python\Python310\python.exe
Python Version:	3.10.4
Python Path:	
['D:\\VU\\CS619\\BC170403979\\punjabbarcouncil',
 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Python\\Python310\\python310.zip',
 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Python\\Python310\\DLLs',
 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Python\\Python310\\lib',
 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Python\\Python310',
 'C:\\Users\\Admin\\AppData\\Local\\Programs\\Python\\Python310\\lib\\site-packages']
Server time:	Sun, 12 Jun 2022 10:19:32 +0000

Complete details of error is:

Traceback Switch to copy-and-paste view
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\exception.py, line 55, in inner
                response = get_response(request) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\core\handlers\base.py, line 197, in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs) …
Local vars
D:\VU\CS619\BC170403979\punjabbarcouncil\register\views.py, line 142, in votes
    return render(request, 'register/votes.html', context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\shortcuts.py, line 24, in render
    content = loader.render_to_string(template_name, context, request, using=using) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\loader.py, line 62, in render_to_string
    return template.render(context, request) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\backends\django.py, line 62, in render
            return self.template.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 175, in render
                    return self._render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 167, in _render
        return self.nodelist.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1000, in render
        return SafeString("".join([node.render_annotated(context) for node in self])) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1000, in <listcomp>
        return SafeString("".join([node.render_annotated(context) for node in self])) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 958, in render_annotated
            return self.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1059, in render
            output = self.filter_expression.resolve(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 712, in resolve
                obj = self.var.resolve(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 842, in resolve
            value = self._resolve_lookup(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 909, in _resolve_lookup
                            current = current() …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\utils.py, line 66, in as_p
        return self.render(self.template_name_p) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\utils.py, line 53, in render
            (renderer or self.renderer).render( …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\renderers.py, line 23, in render
        return template.render(context, request=request).strip() …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\backends\django.py, line 62, in render
            return self.template.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 175, in render
                    return self._render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 167, in _render
        return self.nodelist.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1000, in render
        return SafeString("".join([node.render_annotated(context) for node in self])) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1000, in <listcomp>
        return SafeString("".join([node.render_annotated(context) for node in self])) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 958, in render_annotated
            return self.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\defaulttags.py, line 238, in render
                    nodelist.append(node.render_annotated(context)) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 958, in render_annotated
            return self.render(context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1065, in render
        return render_value_in_context(output, context) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\template\base.py, line 1042, in render_value_in_context
            value = str(value) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\utils\html.py, line 382, in <lambda>
    klass.__str__ = lambda self: mark_safe(klass_str(self)) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\boundfield.py, line 34, in __str__
        return self.as_widget() …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\boundfield.py, line 94, in as_widget
        attrs = self.build_widget_attrs(attrs, widget) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\boundfield.py, line 248, in build_widget_attrs
            widget.use_required_attribute(self.initial) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\widgets.py, line 754, in use_required_attribute
            and self._choice_has_empty_value(first_choice) …
Local vars
C:\Users\Admin\AppData\Local\Programs\Python\Python310\lib\site-packages\django\forms\widgets.py, line 737, in _choice_has_empty_value
        value, _ = choice …
Local vars

My custom User Model is below:

class User(AbstractBaseUser, PermissionsMixin):
    username = models.CharField(max_length=254, null=True, blank=True)
    email = models.EmailField(max_length=254, unique=True)
    first_name = models.CharField(max_length=254, null=True, blank=True)
    last_name = models.CharField(max_length=254, null=True, blank=True)
    pbc_id = models.CharField(max_length=254, null=True, blank=True)
    is_staff = models.BooleanField(default=False)
    is_superuser = models.BooleanField(default=False)
    is_active = models.BooleanField(default=True)
    is_candidate = models.BooleanField(default=False)
    is_voter = models.BooleanField(default=False)
    votes = models.IntegerField(default=0)
    last_login = models.DateTimeField(null=True, blank=True)
    date_joined = models.DateTimeField(auto_now_add=True)
    
    USERNAME_FIELD = 'email'
    EMAIL_FIELD = 'email'
    REQUIRED_FIELDS = []

    objects = UserManager()

    def get_absolute_url(self):
        return "/users/%i/" % (self.pk)

My Manager UserManager class is:

class UserManager(BaseUserManager):
    def _create_user(self, email, password, is_staff, is_superuser, is_candidate, is_voter, **extra_fields):
        if not email:
            raise ValueError('Users must have an email address')

        now = timezone.now()
        email = self.normalize_email(email)

        user = self.model(
            username=email,
            email=email,
            is_staff=is_staff, 
            is_active=True,
            is_superuser=is_superuser, 
            is_candidate=is_candidate,
            is_voter=is_voter,
            last_login=now,
            date_joined=now, 
            **extra_fields
        )
        user.set_password(password)
        user.save(using=self._db)
        user.pbc_id = "PBC-" + str(user.pk)
        user.save(using=self._db)
        return user

    def create_user(self, email, password, **extra_fields):
        user = self._create_user(email, password, False, False, False, False, **extra_fields)
        user.save(using=self._db)
        user.pbc_id = "PBC-" + str(user.pk)
        user.save(using=self._db)
        
        return user

My admin.py is:

class UserAdmin(BaseUserAdmin):
    fieldsets = (
        (None, {'fields': ('username', 'email', 'password', 'first_name', 'last_name', 'last_login')}),
        ('Permissions', {'fields': (
            'is_active', 
            'is_staff', 
            'is_superuser',
            'is_candidate',
            'is_voter',
            'groups', 
            'user_permissions',
        )}),
    )
    add_fieldsets = (
        (
            None,
            {
                'classes': ('wide',),
                'fields': ('email', 'password1', 'password2')
            }
        ),
    )

    list_display = ('username', 'email', 'first_name', 'last_name', 'pbc_id', 'is_staff', 'is_candidate', 'is_voter', 'last_login')
    list_filter = ('is_staff', 'is_candidate', 'is_voter', 'is_superuser', 'is_active', 'groups')
    search_fields = ('email',)
    ordering = ('email',)
    filter_horizontal = ('groups', 'user_permissions',)

    def save_model(self, request, obj, form, change):
        super().save_model(request, obj, form, change)
        if obj.is_candidate:
            obj.pbc_id = "PBC-C" + str(obj.pk)
        elif obj.is_voter:
            obj.pbc_id = "PBC-V" + str(obj.pk)
        else:
            obj.pbc_id = "CPBC-" + str(obj.pk)
        obj.save()

My forms.py is:

class CandidateForm(forms.Form):
    candidate = forms.ChoiceField(choices=User.objects.all().filter(is_candidate=True))

My views.py is:

def votes(request):
    candidatesfm = CandidateForm(request.POST)

    context = {
            'candidatesfm': candidatesfm
        }

    if candidatesfm.is_valid():
            candidate = candidatesfm.cleaned_data.get("candidate")
            
            if candidate is not None:
                print(candidate.votes)
                return redirect("/pbcdashboard")
            else:
                print("Error")

    return render(request, 'register/votes.html', context)

My template votes.html is:

<form action="" method="post">
        {% csrf_token %}
        <div style="background-color: #34495E; padding: 50px; color: white;">
            <div style="background-color: #34495E;">
                {{ candidatesfm.as_p }}
            </div>
        </div>
        <div align="center" style="padding: 50px;">
            <input style="padding-top: 10px; padding-bottom: 10px; padding-left: 20px; padding-right: 20px; font-size: large;" type="submit" value="Check">
        </div>
    </form>

Any help would be appreciated.

@KenWhitesell can you see what wrong am I doing?

See the docs at Form fields | Django documentation | Django for how to use a queryset here.

Or, for a ChoiceField only, you can pass a callable that returns the 2-tuples built from the values from a queryset.

That’s what I did in the forms.py as below:

class CandidateForm(forms.Form):
    candidate = forms.ChoiceField(choices=User.objects.all().filter(is_candidate=True))

You did not pass a callable, you passed a queryset. (A callable could be the name of a function, but not an expression that calls that function.) Nor did you pass something that returned a 2-tuple.

See the related threads at Populate choice field from model with conditional query Django and How can I implement a Model field with dynamic choices? for some ideas.