【问题标题】:Django throws column cannot be null error when POSTing to REST Framework发布到 REST 框架时,Django 抛出列不能为空错误
【发布时间】:2016-07-24 08:04:17
【问题描述】:

即使我在 POST 数据时发送值,Django REST 框架仍报告值为空的错误。

Django 报告的错误是:

django.db.utils.IntegrityError: (1048, "Column 'owner_id' cannot be null")
[04/Apr/2016 18:40:58] "POST /api/items/ HTTP/1.1" 500 226814

POST 到 Django REST Framework API 的 Angular 2 代码是:

    let body = JSON.stringify({ url: 'fred', item_type: 'P', owner_id: 2 });

    let headers = new Headers();
    headers.append('Content-Type', 'application/json');

    this.http.post('http://127.0.0.1:8000/api/items/',
        body, {
        headers: headers
      })
      .subscribe(
        data => {
          alert(JSON.stringify(data));
        },
        err => alert('POST ERROR: '+err.json().message),
        () => alert('POST Complete')
      );

我的 Django API 视图如下所示:

class ItemViewSet(viewsets.ModelViewSet):
    queryset = Item.objects.all().order_by('-date_added')
    serializer_class = ItemSerializer

    """
        Use the API call query params to determing what to return

        API params can be:

        ?user=<users_id>&num=<num_of_items_to_return>&from=<user_id_of_items_to_show>
    """

    def get_queryset(self):
        this_user = self.request.query_params.get('user', None)
        restrict_to_items_from_user_id = self.request.query_params.get('from', None)
        quantity = self.request.query_params.get('num', 20)

        if restrict_to_items_from_user_id is not None:
            queryset = Item.objects.filter(owner=restrict_to_items_from_user_id, active=True).order_by('-date_added')[0:int(quantity)]
        elif this_user is not None:
            queryset = Item.objects.filter(active=True, credits_left__gt=0).exclude(pk__in=Seen.objects.filter(user_id=this_user).values_list('item_id', flat=True))[0:int(quantity)]
        else:
            queryset = Item.objects.filter(active=True, credits_left__gt=0)[0:int(quantity)]

        print("User id param is %s  and quantity is %s" % (user_id,quantity))

        return queryset

关联的模型是:

class Item(models.Model):

    ITEM_TYPES = (
        ('V', 'Vine'),
        ('Y', 'YouTube'),
        ('P', 'Photo'),         # Photo is stored by us on a CDN somewhere
        ('F', 'Flickr'),
        ('I', 'Instagram'),
        ('D', 'DeviantArt'),
        ('5', '500px'),
    )
    owner           = models.ForeignKey(User, on_delete=models.CASCADE)     # Id of user who owns the item
    title           = models.CharField(max_length=60, default='')           # URL of where item resides (e.g. Vine or YouTube url)
    url             = models.CharField(max_length=250, default='')          # URL of where item resides (e.g. Vine or YouTube url)
    item_type       = models.CharField(max_length=1, choices=ITEM_TYPES)    # Type of item (e.g. Vine|YoutTube|Instagram|etc.)
    keywords        = models.ManyToManyField(Keyword, related_name='keywords')
                                                                            # E.g. Art, Travel, Food, etc.
    credits_applied = models.IntegerField(default=10, help_text='Total number of credits applied to this item including any given by VeeU admin')
                                                                            # Records the total number of credits applied to the Item
    credits_left    = models.IntegerField(default=10, help_text='The number of credits still remaining to show the item')
                                                                            # Number of credits left (goes down each time item is viewed
    credits_gifted  = models.IntegerField(default=0, help_text='The number of credits this item has been gifted by other users')
                                                                            # Number of credits users have gifted to this item
    date_added      = models.DateTimeField(auto_now_add=True)               # When item was added
    liked           = models.IntegerField(default=0)                        # Number of times this item has been liked
    disliked        = models.IntegerField(default=0)                        # Number of times this item has been disliked
    active          = models.BooleanField(default=True, help_text='If you mark this item inactive please say why in the comment field. E.g. "Inapproriate content"')
                                                                            # True if item is available for showing
    comment         = models.CharField(max_length=100, blank=True)          # Comment to be applied if item is inactive to say why

    # Add defs here for model related functions

    # This to allow url to be a clickable link
    def item_url(self):
        return u'<a href="%s">%s</a>' % (self.url, self.url)
    item_url.allow_tags = True

    def __str__(self):
        return '%s: Title: %s, URL: %s' % (self.owner, self.title, self.url)

我看不出我的 POST 调用或 Django 代码有什么问题。

编辑:添加序列化代码 这是关联的序列化程序

class ItemSerializer(serializers.HyperlinkedModelSerializer):
    username = serializers.SerializerMethodField()

    def get_username(self, obj):
        value = str(obj.owner)
        return value

    def get_keywords(self, obj):
        value = str(obj.keywords)
        return value

    class Meta:
        model = Item
        fields = ('url', 'item_type', 'title', 'credits_applied', 'credits_left', 'credits_gifted', 'username', 'liked', 'disliked')

【问题讨论】:

    标签: angularjs django django-rest-framework


    【解决方案1】:

    您需要为作为外键的字段传递资源 URI, 这里的所有者是 FK,所以

    ownerIns = User.objects.get(id=2)
    let body = JSON.stringify({ url: 'fred', item_type: 'P', owner: ownerIns, owner_id: ownerIns.id });
    

    【讨论】:

      【解决方案2】:

      您的 ItemSerializer 代码是否正确?其余的在我看来都不错。

      我认为你的序列化器字段中应该有“owner_id”。

      看看这个答案,按这种方式添加相关字段。

      https://stackoverflow.com/a/20636415/5762482

      【讨论】:

      • 我已将关联的序列化程序添加到我的帖子中。
      • 我认为你的序列化器字段中应该有 'owner_id'。
      • 如果我将 'owner_id' 添加到序列化程序中,我会在运行时收到以下错误“字段名称 owner_id 对模型 Item 无效。”在我的模型中,该字段称为所有者,但在数据库中它是 owner_id。
      【解决方案3】:

      您的序列化程序没有所有者字段,您的视图也没有提供。由于它在您的模型中不为空,因此数据库会抱怨这一点。

      您应该覆盖视图的perform_update 并添加the owner as extra argument to the serializer

      【讨论】:

      • 我对此感到不解。 perform_update 需要什么样的外观才能将所有者作为参数添加到序列化程序?
      • 在链接的文档中有解释——你需要滚动一下,你会有一个例子。
      【解决方案4】:

      我在使用 Angular 和 Flask 时遇到了类似的问题。这可能是因为您的 Django 应用程序的 CORS 标头设置不正确,这使得您的 Angular 应用程序不允许发布到后端。在 Flask 中,我使用以下代码修复了它:

      @app.after_request
      def after_request(response):
          response.headers.add('Access-Control-Allow-Origin', '*')
          response.headers.add('Access-Control-Allow-Headers', 'Content-Type,Authorization')
          response.headers.add('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE')
          return response
      

      我不确定如何在 Django 中执行此操作,但这对您来说可能是一个很好的第一站,因为这可能是您的问题。

      【讨论】:

      • 谢谢杰伦。我目前只是在同一来源上运行(用于测试),但我的 CORS 设置与您的示例相同。
      • 该死的人,至少你可以把它从列表中标记出来。我不确定会出现什么问题。如果我看到任何东西,我会再看一遍并告诉你。
      • 也许这与所有者是外键有关?
      猜你喜欢
      • 2017-12-25
      • 1970-01-01
      • 2021-06-18
      • 2015-09-19
      • 1970-01-01
      • 1970-01-01
      • 2023-03-26
      • 2021-12-09
      • 2015-06-18
      相关资源
      最近更新 更多