Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TypeError object is not iterable

I am getting the following error when trying to loop over a variable in my Django templates. The variable in question is the related object of the model specified in my DetailView subclass:

TypeError at /en/applicants/50771459778/

'Householdmember' object is not iterable

Here is my models.py file:

class Applicant(models.Model):
    user              = models.ForeignKey(User, editable=False)
    bank_card_number  = models.CharField(_('Bank card number'),max_length=50, unique=True)
    site_of_interview = models.IntegerField(_('Site of interview'), choices = SITE_CHOICES, default=TIRANA, blank=False)
    housenumber       = models.CharField(_('House Number'),max_length=8)
    address_line1     = models.CharField(_('Address line 1'),max_length=50)
    address_line2     = models.CharField(_('Apt #'),max_length=50,blank=True) 
    municipality      = models.CharField(_('Municipality/commune'),max_length=25)
    district          = models.CharField(_('District'),max_length=25,blank=True)
    urban             = models.IntegerField(_('Area (urban/rural)'), choices = AREA_CHOICES, blank=False)
    postal            = models.CharField(_('Postal code'),max_length=25,blank=True) 

class Householdmember(models.Model):
    applicant         = models.ForeignKey(Applicant)
    first_name        = models.CharField(_('First name'),max_length=50,blank=False)
    middle_name       = models.CharField(_('Middle name'),max_length=50,blank=True) 
    last_name         = models.CharField(_('Last name'),max_length=50,blank=False)
    national_id       = models.CharField(_('National ID'),max_length=50,blank=False, unique=True)
    male              = models.IntegerField(_('Gender'), choices = GENDER_CHOICES, blank=False)
    date_of_birth     = models.DateField()
    rel_to_head       = models.IntegerField(_('Gender'), choices = RELTOHEAD_CHOICES, blank=False)
    disability        = models.IntegerField(_('Is disabled?'), choices = YESNO_CHOICES, blank=False)
    created_at        = models.DateTimeField(auto_now_add = True)
    updated_at        = models.DateTimeField(auto_now = True)

Here is my urls.py file:

class ListViewApplicants(ListView):
    paginate_by = 100
    def get_queryset(self):
        return Applicant.objects.all()

class DetailViewUnmask(DetailView):
    def get_object(self):
        return self.get_queryset().get(pk=mask_toggle(self.kwargs.get("pk_masked")))

urlpatterns = patterns('',
    url(r'^$',
        login_required(ListViewApplicants.as_view( 
                            template_name='applicants/index.html',
                            #context_object_name='form',
                            )),
        name='index'),
    url(r'^(?P<pk_masked>\d+)/$',
        login_required(DetailViewUnmask.as_view( model=Applicant,
                            template_name='applicants/detail.html'
                            )), 
        name='detail'),

Here is the relevant part of my template, detail.html:

<h2>Household members</h2>
<table class="package_detail">
    <tr>
        {% include "applicants/householdmember_heading_snippet.html" %}
    </tr>
    
    {% for householdmember in applicant.householdmember_set.all %}
    <tr>
        
        {% for field in householdmember %}
            <td>{{ field }}</td>
        {% endfor %}
        <!--
        <td>{{ householdmember.first_name }}</td>
        <td>{{ householdmember.middle_name  }}</td>
        <td>{{ householdmember.last_name  }}</td>
        <td>{{ householdmember.national_id  }}</td>
        <td>{{ householdmember.get_male_display }}</td>
        <td>{{ householdmember.date_of_birth }}</td>
        <td>{{ householdmember.get_rel_to_head_display }}</td>
        <td>{{ householdmember.get_disability_display }}</td>
        -->
    </tr>
    {% endfor %}
</table>

The part that is commented out (i.e. the part in between the <!-- --> tags) works, which leads me to think that I should be able to iterate over the householdmember variable. But when I try to do so, it doesn't work - I just get the TypeError above.

I have searched stackoverflow.com exentsively for an answer, but the closest answer I could find is this one: django how to loop through the context object passed back by a generic detailview?, but it does not solve my problem, I think because I'm using class based views.

Would greatly appreciate any help. Thanks!

like image 325
Shafique Jamal Avatar asked Aug 29 '13 13:08

Shafique Jamal


People also ask

How do I fix TypeError float object is not iterable?

Conclusion # The Python "TypeError: 'float' object is not iterable" occurs when we try to iterate over a float or pass a float to a built-in function like, list() or tuple() . To solve the error, use the range() built-in function to iterate over a range, e.g. for i in range(int(3.0)): .

Is not iterable TypeError?

The JavaScript exception "is not iterable" occurs when the value which is given as the right-hand side of for...of , as argument of a function such as Promise. all or TypedArray. from , or as the right-hand side of an array destructuring assignment, is not an iterable object.

How do I fix this TypeError NoneType object is not iterable?

The TypeError: 'NoneType' object is not iterable error is raised when you try to iterate over an object whose value is equal to None. To solve this error, make sure that any values that you try to iterate over have been assigned an iterable object, like a string or a list.

How do you make an object iterable in Python?

To create an object/class as an iterator you have to implement the methods __iter__() and __next__() to your object. As you have learned in the Python Classes/Objects chapter, all classes have a function called __init__() , which allows you to do some initializing when the object is being created.


1 Answers

You can't iter over a model instance. I recommend you use your commented code.

If you still want to use a forloop, maybe you can add this code:

class Householdmember(models.Model):
    # all yuur fields...

    def __iter__(self):
        return return [field.value_to_string(self) for field in Householdmember._meta.fields]

But, no one recommend that

That's better:

class Householdmember(models.Model):
    # all yuur fields...

    def __iter__(self):
        return [ self.first_name, 
                 self.middle_name, 
                 self.last_name, 
                 self.national_id, 
                 self.get_male_display, 
                 self.date_of_birth, 
                 self.get_rel_to_head_display, 
                 self.get_disability_display ] 
like image 195
Leandro Avatar answered Oct 06 '22 08:10

Leandro