在Django-rest-frame工作中,“ NoneType”对象没有属性“ attname”

时间:2018-09-26 09:31:06

标签: python django django-models django-rest-framework

我在这里使用抽象概念,但是当我尝试调用产品时,它会抛出诸如'NoneType' object has no attribute 'attname'之类的错误。

在此models.py中,产品是主要模型,而其他模型(例如,类别,评论,规格和ItemNumber)是子模型。在产品中,所有其他子模型都称为数组字段。

我不知道该如何克服这个问题,所以请告诉我如何实现这一目标。

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__'

1 个答案:

答案 0 :(得分:2)

简短答案:使模型抽象。

我认为您不太了解抽象模型的概念。抽象模型意味着它实际上并不存在:您定义列,但是该模型没有表。您这样做的唯一目的是可以创建另一个继承自抽象模型的模型,从而可以自动定义大量列以及某些常见行为。或如Django documentation中指定:

  

当您要添加一些常见内容时,抽象基类非常有用   信息导入其他许多模型。你写你的基类   并将abstract=True放在Meta类中。然后,该模型将不被   用于创建任何数据库表。而是当它用作基础时   其他模型的类,其字段将添加到孩子的字段中   课。

但是,您在这里定义了这些抽象模型的形式,序列化器等。这很奇怪,因为如果设计使您无法构造CategoriesFormCategories将如何设法创建Categories对象对象:您只能构造 non 非抽象模型对象(可能会也可能不会从一个或多个抽象模型继承)。

您的模型定义为摘要:

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

   class Meta:
       abstract = True

因此您应该忽略这一点(这可能适用于您定义的大多数(如果不是全部)模型)。

然后,您还必须在数据库中构造表。您可以通过进行迁移来做到这一点:

python3 manage.py makemigrations

然后迁移数据库:

python3 manage.py migrate

如果我们创建一个抽象模型并创建一个对象,则会显示错误消息,例如:

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

    class Meta:
        abstract = True

然后,如果我们构造这样的对象,则会得到相同的错误:

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

注意术语并未真正遵循指南。通常,模型的名称为单数,因此Category代替 Categories ,而CategoryForm代替 {{ 1}} CategoriesForm