How To Solve Django ValueError: :Comment.post" должен быть экземпляром "Software"
Я получаю ошибку снова и снова, когда отображаю комментарии к программе. Пожалуйста, подскажите, в чем проблема? Я сделал много попыток, используя get , filter , но ошибка остается той же. Другие ошибки могут появляться при изменении вида комментариев. Пожалуйста, помогите.
def download(request,slug):
app = get_object_or_404 (Software,slug = slug)
comments= app.comments.filter(active=True).order_by("-created")
try :
app = Software.objects.filter(slug = slug)
except :
raise Http404
new_comment = None
if request.method == "POST":
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.post= app <<<--------------------------->>> here my error
new_comment.save()
else:
comment_form = CommentForm()
context ={
'app' :app,
'comments': comments,
'new_comment': new_comment,
'comment_form': comment_form,
}
return render( request,'download.html',context)
это мои модели:
class Software (models.Model):
class Meta :
verbose_name_plural = 'software'
ordering = ['created_at']
category = models.ForeignKey(Categorie,on_delete=models.CASCADE,null=True, related_name="mac")
category = models.CharField(max_length=150 , null=True,blank=True)
slug = models.SlugField(blank=True,allow_unicode=True,editable=True)
title = models.CharField(max_length=50 , null=True)
requirements = models.CharField(max_length=100 , null=True)
version = models.CharField(max_length=100 , null=True)
picture = models.ImageField(upload_to='img_pro' , null=True)
size = models.CharField(max_length=20 , null=True)
created_at = models.DateField(auto_now_add=True)
auther = models.CharField(max_length=100 , null=True)
download = models.URLField(null=True)
def __str__(self):
return self.slug
def get_absolute_url(self):
return reverse('download', args=(self.slug,))
class Comment(models.Model):
post = models.ForeignKey(Software , on_delete=models.CASCADE ,null=True, related_name='comments')
name = models.CharField(max_length=80 , null=True)
email = models.EmailField(max_length=200, blank=True , null=True)
body = models.TextField( null=True)
created = models.DateTimeField(auto_now_add=True , null=True)
active = models.BooleanField(default=False , null=True)
parent = models.ForeignKey('self', null=True, blank=True, related_name='replies',on_delete=models.CASCADE)
class Meta:
ordering = ('created',)
def __str__(self):
return 'Comment by {}'.format(self.post)
Ok, obj.objects.filter()
всегда возвращает кверисет. Значит, в вашем случае переменная app
является кверисетом, а не экземпляром модели Software
.
Чтобы убедиться, что переменная app
содержит только один единственный экземпляр Software
, необходимо использовать obj.objects.get()
, что приведет либо к ошибке DoesNotExist
, либо к ошибке MultipleObjectsReturned
, либо к единственному попаданию в искомый экземпляр модели Software
.
Здесь вы переходите к поиску с помощью ...objects.get()
.
Чтобы полностью заменить блок try-except на удобную функцию get_object_or_404()
сделайте так:
def download(request,slug):
app = get_object_or_404(Software, slug=slug)
if request.method == "POST":
comment_form = CommentForm(data=request.POST)
if comment_form.is_valid():
new_comment = comment_form.save(commit=False)
new_comment.comments = app <<<--------------------------->>> here my error
new_comment.save()
else:
comment_form = CommentForm()
context ={
'app' :app,
'comments': app.comments,
'new_comment': new_comment,
'comment_form': comment_form,
}
return render( request,'download.html',context)
Другой проблемой может быть то, что вы ссылаетесь на свои сообщения с помощью comment.post =
, но в своей модели Comment
вы сказали через related_name
, что хотите ссылаться на свои сообщения через comments
.
Вам нужно использовать .get() вместо .filter() Запрос для получения объекта, подобного этому...
app = Software.objects.get(slug = slug) <--- this need to be correct
new_comment = comment_form.save(commit=False)
new_comment.comments = app
new_comment.save()