pythondjangodjango-models

seeing error register for model in model_or_iterable: TypeError: 'type' object is not iterable


I have following models in

from django.db import models

# Create your models here.

class Post(models.Model):
    text = models.TextField()

    def __str__(self):
        return self.text[:50]


POWER_CHOICES= (('O', 'ON'),
                ('F','OFF')
        )

STATE_CHOICES =(('AV','Available'),
               ('U','In Use '),
               ('NU','Do Not Use')                
       )

class Device(models.Model):

   name = models.CharField(unique=True,max_length=50 )

   ipaddress=models.ForeignKey('Ipaddress', on_delete=models.CASCADE,)

   devicetype= models.ForeignKey('DeviceType', on_delete=models.CASCADE)
   model= models.ForeignKey('DeviceModel', on_delete=models.CASCADE)
   description= models.TextField(max_length=400)
   location= models.ForeignKey('Location', on_delete=models.CASCADE)
   group= models.ForeignKey('DeviceGroup', on_delete=models.CASCADE)
   managment= models.CharField(max_length=100)
   power= models.CharField(max_length=6, choices=POWER_CHOICES)
   offtime= models.CharField(max_length=30)
   state= models.CharField(max_length=10, choices=STATE_CHOICES)
   user= models.CharField(max_length=100)
#   department= models.ForeignKey('Department',on_delete=models.CASCADE)
   comments= models.CharField(max_length=200)

   def __unicode__(self):
        return self.name[:50]

class DeviceType(models.Model):
    name= models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.name[:50]

class DeviceModel(models.Model):
    name= models.CharField(max_length=100, unique=True)

    def __unicode__(self):
        return self.name[:50]

class Ipaddress(models.Model):
    address=models.CharField(max_length=20, unique=True)
    owner=models.CharField(max_length=200)
    loation=models.CharField(max_length=200)
    note =models.TextField()
    def __unicode__(self):
        return self.address[:50]

class Department:
    name= models.CharField(max_length=100, unique=True)
    def __unicode__(self):
        return self.name[:50] 


class DeviceGroup:
    name= models.CharField(max_length=100, unique=True)
    def __unicode__(self):
        return self.name[:50] 

class Location:
    description= models.CharField(max_length=100, unique=True)
    def __unicode__(self):
        return self.description[:50] 

My admin page looks like as below:

from django.contrib import admin
from pages.models import Post, Device, DeviceType, DeviceModel, Ipaddress, DeviceGroup, Location

admin.site.register(Post)
admin.site.register(Device)
admin.site.register(DeviceType)
admin.site.register(DeviceModel)
admin.site.register(Ipaddress)
#admin.site.register(Department)
admin.site.register(DeviceGroup)
admin.site.register(Location)

I am seeing following error and not sure what causing this error. Can someone please give me some idea. please

...
...
File "C:\Users\mohiuddin_rana\labmcproject\pages\admin.py", line 10, in <module>
    admin.site.register(DeviceGroup)
  File "C:\Users\mohiuddin_rana\AppData\Local\Programs\Python\Python37-32\lib\site-packages\django\contrib\admin\sites.py", line 102, in register
    for model in model_or_iterable:
TypeError: 'type' object is not iterable

Solution

  • For some of your models, you forgot to subclass it from models.Model:

    class Department(models.Model):
        name= models.CharField(max_length=100, unique=True)
        def __unicode__(self):
            return self.name[:50] 
    
    
    class DeviceGroup(models.Model):
        name= models.CharField(max_length=100, unique=True)
        def __unicode__(self):
            return self.name[:50] 
    
    class Location(models.Model):
        description= models.CharField(max_length=100, unique=True)
        def __unicode__(self):
            return self.description[:50]

    This change will also result in some migrations, since up till now, Django (probably) did not understand that these classes were actually models, and therefore did not construct database equivalents.

    Django expects a model when you register it to the admin.site variable, but the check fails. As a "fallback" mechanism, it checks if you perhaps have provided an iterable of models, but this again fails, since it is just a "vanilla" class.

    This behavior can be confirmed when we check the source code of the register(..) function [GitHub]:

    def register(self, model_or_iterable, admin_class=None, **options):
    
        # ...
    
        admin_class = admin_class or ModelAdmin
        if isinstance(model_or_iterable, ModelBase):
            model_or_iterable = [model_or_iterable]
        for model in model_or_iterable:
            # ...
            pass

    (I removed some parts to make the semantics more clear).

    As you can see, it checks if the model_or_iterable you pass is a model. If that is the case, it wraps it in a list, otherwise it assumes it is an iterable, and aims to iterate over it.

    Note: it looks like you use __unicode__, but use Python-3.x at the same time. __unicode__ has, to the best of my knowledge, no meaning anymore in the Python-3.x data model. You should use __str__ instead.