django:无法分配“ 1”:“ TitleVideoModel.video_id”必须是“ VideosModel”实例

时间:2018-08-19 14:24:01

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

我正在尝试创建一个API,用于在数据库表中添加项目。我当前的代码是https://github.com/scaltro/youtubeapp/blob/master/myupload/views.py

问题是,当我尝试在api http://142.93.130.167:1080/api/titles中发布数据时,出现此错误:

  

无法分配“ 1”:“ TitleVideoModel.video_id”必须是“ VideosModel”实例

怎么了?我该如何解决该错误?

4 个答案:

答案 0 :(得分:1)

问题是您试图将一个整数(可以是VideosModel的ID,也可以只是一个随机整数)分配到外键字段中。

查看您的代码,我会修复许多非Django的问题:

  • 模型名称应为单数(除非它们引用一组事物,在这种情况下无论如何我都只用Group表示),即VideosModel应该为VideoModel
  • 模型名称中不应包含单词Model;显然他们是模特。 (考虑Django的内置User。它不是UserModel)。因此,要添加到上面:将VideosModel仅设为Video
  • ForeignKey字段不应以_id结尾。它们不是ID字段 sich ,即使它们在幕后由ID字段(恰好称为FIELDNAME_id)支持-也就是说,您的模型将具有物理数据库名为video_id_id的字段。 因此,TitleVideoModel.video_id应该只是video
    实际上,重命名该字段将使您的API正常工作,但这只是偶然的。您可以在Django中为支持外键的字段分配ID值,很高兴知道何时只有ID并且不想拔出实际对象只是为了分配它。

然后有非DRFism。您实际上应该将rest_framework.viewsets.ModelViewSet / TitlesList / TitleDetail用作TitlesView,然后将获得为验证而手动编写的所有代码这些序列化程序,并为值等设置默认值。

我建议阅读视图集上的DRF tutorial

答案 1 :(得分:0)

fuentes fuente2 = new fuentes { referencia = "CE18M", modelo = "MEANWELL", voltaje = 12, potencia = 18, ip = 67, factorpotencia = 0.5, precio = 14 }; fuentes fuente7 = new fuentes { referencia = "CE36M", modelo = "MEANWELL", voltaje = 12, potencia = 36, ip = 67, factorpotencia = 0.5, precio = 26 }; fuentes fuente9 = new fuentes { referencia = "CE60M", modelo = "MEANWELL", voltaje = 12, potencia = 60, ip = 67, factorpotencia = 0.5, precio = 29.5 }; fuentes fuente14 = new fuentes { referencia = "CE120M", modelo = "MEANWELL", voltaje = 12, potencia = 120, ip = 67, factorpotencia = 0.5, precio = 76.62 }; List<double> units = new List<double>(); List<double> fuentesexterior = new List<double>() { fuente14.potencia, fuente12.potencia, fuente9.potencia, fuente7.potencia, fuente2.potencia}; calculofuentesexterior(units, fuentesexterior, 0, 0, totalwatios); } static void calculofuentesexterior(List<double> units, List<double> fuentesexterior, double highest, double sum, double goal) { if (sum <= (goal + (goal * 25 / 100)) && sum >= (goal + (goal * 15 / 100))) { pintafuentesexterior(units, fuentesexterior); return; } if (sum > (goal + (goal * 25 / 100))) { return; } foreach (double value in fuentesexterior) { if (value >= highest) { List<double> copy = new List<double>(units); copy.Add(value); calculofuentesinterior(copy, fuentesexterior, value, sum + value, goal); } } } static void pintafuentesexterior(List<double> units, List<double> amounts) { foreach (double fuentesexterior in amounts) { double count = units.Count(value => value == fuentesexterior); Console.WriteLine("{0}: {1}", fuentesexterior, count); } Console.WriteLine(); Console.ReadKey(); } 必须是video_id的实例,因此请替换:

VideosModel

作者:

video_id = video_id

答案 2 :(得分:0)

您必须传递VideosModel的对象,以便Django可以通过关系对其进行映射。因此,在TitlesView中,您可以执行以下操作:

try:
   video = VideosModel.objects.get(id=video_id)

    t = TitleVideoModel(
        title=title,
        video=video,
        publicato=publicato,
        youtube_url=youtube_url,
        author=author,
        created_at=created_at,
        updated=updated_at,
    )
except VideosModel.DoesNotExist:
    # Handle the case when video by id is not found.

答案 3 :(得分:0)

Django ForeignKey名称

问题实际上更多地位于models.py中,而不是views.py中。 Django开发人员经常犯的一个错误是写类似这样的东西:

class TitleVideoModel(models.Model):
    # ...
    video_id = models.ForeignKey(VideosModel, on_delete=models.PROTECT)

在这里,您定义了一个ForeignKey实例,该实例引用了一个VideosModel实例。现在,这当然会在数据库中存储为一列,该列引用VideosModel表的主键值),但是在Django级别上,这实际上是对{{1}的(惰性)引用}对象。因此,名称应为VideosModel,而不是video

videos

为什么那么重要?因为对于class TitleVideoModel(models.Model): # ... video = models.ForeignKey(VideosModel, on_delete=models.PROTECT),Django具有两个属性:ForeignKeyvideo(在旧版本中为video_id,但是那是一个丑陋的名称)。 video_id_id懒惰地引用了video实例,它的双胞胎VideosModel存储了主键。实际上,video_id属性有点“虚拟”,因为在数据库中仅存在video

因此,您可以通过简单地编写以下内容来设置主键,而无需首先对该对象进行提取:

video_id

,然后您可以直接更新参考。由于Django添加了外键约束,因此如果some_titlevideomodel.video_id = 123 some_titlevideomodel.save() 不是有效的主键值,这也会出错。过滤,更新,创建等操作也会发生同样的情况。编写123时,它将接受一个主键值(默认情况下,主键是一个整数),并因此使用该值。

我建议您重命名该关系并构建迁移,因为这更多的是Django风格。

替代:使用video_id

如果您不想重命名video_id_id,可以将其重写为:

ForeignKey

但这最终只会导致更多的混乱。尽管现在需要一些工作来解决这种情况,但我认为最后,您的努力很值得。

  

注意:Django风格还指定模型应具有单数名称,并且通常 not t = TitleVideoModel( title=title, video_id_id=video_id, publicato=publicato, youtube_url=youtube_url, author=author, created_at=created_at, updated=updated_at )结尾,因此Model代替TitleVideo,而TitleVideoModel代替Video