简体   繁体   中英

In Django-rest-frame work 'NoneType' object has no attribute 'attname'

Here i have using abstract concept but when i try to call product it was throwing Error like 'NoneType' object has no attribute 'attname' .

In this models.py Product is the main model and other models like Category, Reviews, Specification and ItemNumber are sub models. In Product all Other sub models are mentioned as array field.

I don't know how to over come this so please tell me how to achieve this.

Models.py

class Categories(models.Model):
   name = models.CharField(max_length=255)

   class Meta:
       abstract = True
class CategoriesForm(forms.ModelForm):
   class Meta:
       model = Categories
       fields = ['name']
class Specifications(models.Model):
   cost_price = models.FloatField()
   quantity = models.IntegerField()
   sell_price = models.FloatField()
   size = models.CharField(max_length=255)

   class Meta:
       abstract = True


class SpecificationsForm(forms.ModelForm):
   class Meta:
       model = Specifications
       fields = ['cost_price', 'quantity', 'sell_price', 'size']


class Reviews(models.Model):
   author = models.CharField(max_length=255)
   date = models.CharField(max_length=255)
   rating = models.FloatField()
   comment = models.CharField(max_length=1000)
   class Meta:
       abstract = True
class ReviewsForm(forms.ModelForm):
   class Meta:
       model = Reviews
       fields = ['author', 'date', 'rating', 'comment']

class ItemNumber(models.Model):
  spec_id = models.CharField(max_length=20)

  class Meta:
    abstract = True

class ItemNumberForm(forms.ModelForm):
  class Meta:
    model = ItemNumber
    fields = ['spec_id']
class Product(models.Model):
   name = models.CharField(max_length=255)
   image = models.ImageField(upload_to='', blank=True)
   categories = models.ArrayModelField(
       model_container=Categories,
       model_form_class=CategoriesForm
   )
   specifications = models.ArrayModelField(
       model_container=Specifications,
       model_form_class=SpecificationsForm
   )
   description = models.TextField()
   reviews = models.ArrayModelField(
       model_container=Reviews,
       model_form_class=ReviewsForm
   )
   drizzly = models.BooleanField()
   complete = models.BooleanField()
   comment = models.TextField()
   item_number = models.ArrayModelField(
       model_container=ItemNumber,
       model_form_class=ItemNumberForm
   )
   def __str__(self):
       return self.name

Serializer.py

class Productserializer(serializers.ModelSerializer):
    class Meta:
        model = Product
        fields = '__all__'

Short answer : make the models non -abstract.

I think you do not really grasp the concept of an abstract model. An abstract model means that it does not really exists: you define columns, but there is no table for that model. You only do that such that can make another model that inherits from the abstract model(s), such that you automatically can define a huge amount of columns, as well as certain common behavior. Or as specified in the Django documentation :

Abstract base classes are useful when you want to put some common information into a number of other models . You write your base class and put abstract=True in the Meta class. This model will then not be used to create any database table . Instead, when it is used as a base class for other models, its fields will be added to those of the child class.

Here however you define forms, serializers, etc. on these abstract models. This is very strange, since how would that CategoriesForm manage to create a Categories object, if you - by design - should not be able to construct such Categories objects: you can only construct non -abstract model objects (that might, or might not inherit from one or more abstract models).

Your models, are defined as abstact:

class Categories(models.Model):
   name = models.CharField(max_length=255)

   class Meta:
       

So you should omit this (and this is probably applicable to most, if not all, models you defined).

You then will also have to construct the table in the database. You can do this by making migrations:

python3 manage.py makemigrations

and then migrate the database:

python3 manage.py migrate

The error als shows up if we make an abstract model, and create an object, like:

class Foo(models.Model):
    bar = models.IntegerField()

    class Meta:
        abstract = True

Then if we construct such object, we get the same error:

>>> Foo(bar=12)
Traceback (most recent call last):
File "/usr/lib/python3.6/code.py", line 91, in runcode
exec(code, self.locals)
File "<console>", line 1, in <module>
File "/tmp/foo/.local/lib/python3.6/site-packages/django/db/models/base.py", line 513, in __repr__
return '<%s: %s>' % (self.__class__.__name__, self)
File "/tmp/foo/.local/lib/python3.6/site-packages/django/db/models/base.py", line 516, in __str__
return '%s object (%s)' % (self.__class__.__name__, self.pk)
File "/tmp/foo/.local/lib/python3.6/site-packages/django/db/models/base.py", line 564, in _get_pk_val
return getattr(self, meta.pk.attname)
AttributeError: 'NoneType' object has no attribute 'attname'

Note : the nomenclature does not really follows the guidelines. Normally the name of a model is singular , so Category instead of Categories , and CategoryForm instead of CategoriesForm , or CategoryForms .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM