2013-08-29 5 views
6

Я получаю следующую ошибку при попытке перебрать переменную в своих шаблонах Django. Переменная в вопросе соответствующий объект модели, указанной в моем DetailView подкласса:TypeError object is not itable

TypeError в/EN/заявителей/50771459778/

объект 'Householdmember' не итерацию

Здесь мой 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> 

Та часть, которая закомментирована (т.е. часть между тегами <!-- -->), что заставляет меня думать, что я должен иметь возможность перебирать переменную householdmember. Но когда я пытаюсь сделать это, это не сработает - я просто получаю TypeError выше.

Я искал stackoverflow.com для ответа, но ближайший ответ, который я мог найти, это один: django how to loop through the context object passed back by a generic detailview?, но он не решает мою проблему, я думаю, потому что я использую представления на основе классов.

Был бы очень признателен за любую помощь. Благодаря!

ответ

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 ] 
+0

Привет, Лало, благодарю за ваш быстрый ответ. Один вопрос: что такое «Проект» в поле «для поля в Project._meta.fields» в вашем коде выше? –

+0

К сожалению, это должно быть членом семьи – lalo

0

мне удалось решить это; вот как. Я использовал информацию здесь: 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> 

И это дает желаемый выход.