【问题标题】:TypeError object is not iterableTypeError 对象不可迭代
【发布时间】:2013-09-01 23:28:32
【问题描述】:

尝试在我的 Django 模板中循环一个变量时出现以下错误。有问题的变量是我的 DetailView 子类中指定的模型的相关对象:

/en/applicants/50771459778/ 处的类型错误

“家庭成员”对象不可迭代

这是我的models.py 文件:

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)

这是我的urls.py 文件:

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'),

这是我模板的相关部分,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>

被注释掉的部分(即&lt;!-- --&gt; 标签之间的部分)有效,这让我认为我应该能够迭代householdmember 变量。但是当我尝试这样做时,它不起作用 - 我只是得到上面的 TypeError。

我已经在 stackoverflow.com 上搜索了一个答案,但我能找到的最接近的答案是这个:django how to loop through the context object passed back by a generic detailview?,但它并没有解决我的问题,我想是因为我使用的是基于类的视图。

非常感谢任何帮助。谢谢!

【问题讨论】:

    标签: django python-2.7 django-templates detailview


    【解决方案1】:

    如果您的 views.py 文件与我的类似:

        from django.shortcuts import render
        from django.http import HttpResponse
        from django.contrib.auth.forms import UserCreationForm
        from .models import Home 
        from django.template import RequestContext
        from django.shortcuts import render_to_response
        from django.db.models import Count
        # Create your views here.
    
        def homepage(request):
          context = RequestContext(request)
    
          titles_string = Home.objects.get(id=2)
          print (titles_string)
    
          context_dict = {'titles' : (titles_string)}
          print(context_dict)
    
    
          return render_to_response('main/home.html', context_dict, context)
    

    您可以通过在模板文件中打印来打印所需的值:{{titles}}

        % extends "main/header.html" %}
        {% block title %} 
            {{titles}}
        {% endblock %}
        {% block content %} 
            {{titles}}
        {% endblock %}
    

    【讨论】:

      【解决方案2】:

      我设法解决了这个问题;这里是如何。我使用了这里的信息:Iterate over model instance field names and values in template

      这是我添加到 models.py 文件中的内容:

      def get_all_fields(self):
          fields = []
          for f in self._meta.fields:
              fname = f.name        
              # resolve picklists/choices, with get_xyz_display() function
              get_choice = 'get_'+fname+'_display'
              if hasattr( self, get_choice):
                  value = getattr( self, get_choice)()
              else:
                  try :
                      value = getattr(self, fname)
                  except User.DoesNotExist:
                      value = None
      
              # only display fields with values and skip some fields entirely
              if f.editable and f.name not in ('id', 'created_at', 'updated_at', 'applicant'):
      
                  fields.append(
                      {
                      'label':f.verbose_name, 
                      'name':f.name, 
                      'value':value,
                      }
                  )
          return fields
      

      这就是我的detail.html 文件最终的样子:

      <table class="package_detail">
          <tr>
              {% include "applicants/householdmember_heading_snippet.html" %}
          </tr>
          {% for householdmember in applicant.householdmember_set.all %}
          <tr>    
          {% for field in householdmember.get_all_fields %}
              <td>{{ field.value }}</td>
          {% endfor %}
          </tr>
          {% endfor %}
      </table>
      

      这给出了所需的输出。

      【讨论】:

        【解决方案3】:

        您不能迭代模型实例。 我建议您使用您的注释代码。

        如果你还想使用forloop,也许你可以添加这段代码:

        class Householdmember(models.Model):
            # all yuur fields...
        
            def __iter__(self):
                return return [field.value_to_string(self) for field in Householdmember._meta.fields]
        

        但是,没有人推荐

        这样更好:

        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 ] 
        

        【讨论】:

        • 您好拉洛,感谢您的快速回复。一个问题:上面代码中for field in Project._meta.fields中的Project是什么?
        • 对不起,那必须是家庭成员
        猜你喜欢
        • 2017-08-27
        • 2018-10-10
        • 2021-12-13
        • 2019-02-20
        • 2020-03-27
        • 2018-12-12
        • 2018-07-16
        • 2011-09-12
        • 2018-04-14
        相关资源
        最近更新 更多