Не получается вывести аватар пользователя в коментариях Django с использованием Ninja shema
Файл с моделями для постов и коментариев
from django.db import models
from django.urls import reverse
from django.utils import timezone
from taggit.managers import TaggableManager
from blog.manager import PublishedManeger
class Post(models.Model):
class Status(models.TextChoices):
DRAFT = "DRAFT", "Draft"
PUBLISHED = "PUB", "Published"
title = models.CharField(max_length=250)
slug = models.SlugField(max_length=100, unique_for_date="published")
body = models.TextField()
status = models.CharField(max_length=20, choices=Status.choices, default=Status.DRAFT)
author = models.ForeignKey(User, on_delete=models.CASCADE, related_name="posts")
published = models.DateTimeField(default=timezone.now)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
tags = TaggableManager()
objects = models.Manager()
approved = PublishedManeger()
class Meta:
ordering = ["-published"]
indexes = [models.Index(fields=["-published"])]
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse(
"blog:post_detail",
args=[
self.published.year,
self.published.month,
self.published.day,
self.slug,
],
)
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name="comments")
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name="comments")
body = models.TextField(max_length=250)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ["-created"]
indexes = [models.Index(fields=["-created"])]
def __str__(self):
return f"Comment by {self.user} on {self.post}"
Файл с моделью профиля пользователя
from django.conf import settings
# from django.contrib.auth.models import User
from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
avatar = models.ImageField(upload_to="users/%Y", default="users/default.jpg")
def __str__(self):
return f"{self.user.username}'s profile"
@receiver(post_save, sender=user)
def create_user_profile(sender, instance, created, **kwargs):
if created:
Profile.objects.create(user=instance)
@receiver(post_save, sender=user)
def save_user_profile(sender, instance, **kwargs):
instance.profile.save()
Файл API.
from datetime import datetime
from django.utils.text import slugify
from ninja import Router, Schema, ModelSchema
from account.models import Profile
from django.contrib.auth.models import User
from blog.models import Comment, Post
router = Router()
class PostIn(Schema):
title: str
body: str
class PostOut(Schema):
title: str
slug: str
body: str
created: datetime
class CommentIn(Schema):
post_id: int
body: str
class ProfileSchema(ModelSchema):
class Meta:
model = Profile
fields = ["avatar"]
# class ProfileSchema(Schema):
# avatar: str
class UserOut(Schema):
id: int
username: str
avatar: ProfileSchema
class CommentOut(Schema):
post_id: int
body: str
created: datetime
user: UserOut
@router.get("/comments/{post_id}", response=list[CommentOut])
def comment_list(request, post_id: int):
post = Post.objects.get(id=post_id)
comments = post.comments.select_related("user")
return comments
@router.post("/comments/", response=CommentOut)
def comment_create(request, payload: CommentIn):
values = payload.dict()
values["user_id"] = int(request.user.id)
comment = Comment.objects.create(**values)
comment.save()
return comment
@router.get("/", response=list[PostOut])
def post_list(request):
return Post.approved.all()
@router.get("/{post_id}", response=PostOut)
def post_detail(request, post_id: int):
return Post.objects.get(id=post_id)
@router.post("/")
def post_create(request, payload: PostIn):
values = payload.dict()
values["author_id"] = int(request.user.id)
values["slug"] = slugify(values["title"])
post = Post.objects.create(**values)
post.save()
return {"id": post.id}
Файл HTML
{% extends 'base.html' %}
{% block title %}
: Читать
{% endblock %} {% block main %}
<h2 class="main__heading text-4xl">{{ post.title }}</h2>
<article class="post">
<p class="post__body text-xl">{{ post.body }}</p>
<footer class="post__meta mt-4">Published {{ post.published }} by {{ post.author }}
<a class="btn btn-sm btn-outline btn-secobdary ml-2" href="{% url "blog:post_share" post.id %}">Share</a>
</footer>
</article>
{% comment %} {% with comments.count as total_comments %}
<h2>{{ total_comments }} comment{{ total_comments|pluralize }}</h2>
{% endwith %}
{% for comment in comments %}
<div class="comment">
<p class="info">Comment {{ forloop.counter }} by {{ comment.user_id }}
{{ comment.created }}</p>
{{ comment.body|linebreaks }}
</div>
{% empty %}
<p>There are no comments.</p>
{% endfor %} {% endcomment %}
<section class="comments">
<h2 class="comments__counter mb-10"></h2>
<div class="comments__content"></div>
</section>
{% include "blog/post/comment_form.html" %}
{% endblock %}
{% block js %}
<script>
function createCommentElement({ body, created, user}) {
const commentElement = document.createElement("div")
commentElement.innerHTML = `<div class="comment mb-10">
<p class="info"><div class="avatar">
<div class="w-20 rounded-full mr-5">
<img src= ${user.avatar} />
{% comment %} <img src="https://daisyui.com/images/stock/photo-1534528741775-53994a69daeb.jpg" /> {% endcomment %}
</div>
<p> Comment by ${user.username} ${new Date(created).toLocaleString("ru")} </p>
${body}
</div>`
return commentElement
}
function loadComments() {
fetch("/api/blog/comments/{{ post.id }}").then(responce => {
if (!responce.ok) {
throw new Error("API Error")
}
return responce.json()
}).then(data => {
if (data.length === 0) {
commentsCounter.textContent = "There are no comments yet..."
} else {
commentsCounter.textContent = `There are ${data.length} comments`
}
commentsContent.innerHTML = '<div class="comments__content"></div>'
commentsContent.append(...data.map(createCommentElement))
})
.catch(error => {
console.error(error)
})
}
function handleSubmit(event) {
event.preventDefault()
const formData = newForm.elements
const post_id = +formData["post_id"].value
const body = formData["body"].value
fetch("/api/blog/comments/", {
method: "post",
body: JSON.stringify({ post_id, body }),
headers: {
"Content-Type": "application/json"
}
}).then((responce) => {
if (!responce.ok) {
throw new Error("API error")
}
loadComments()
formData["body"].value = ""
})
.catch(error => console.log(error))
}
const newForm = document.querySelector(".collapse form[method=post]")
const commentsCounter = document.querySelector(".comments__counter")
const commentsContent = document.querySelector(".comments__content")
newForm.addEventListener("submit", handleSubmit)
document.addEventListener("DOMContentLoaded", loadComments)
</script>
{% endblock%}
Выдает такую ошибку: Field required [type=missing, input_value=<DjangoGetter: <User: testuser2>>, input_type=DjangoGetter] For further information visit https://errors.pydantic.dev/2.6/v/missing