Can't figure out where my mistake is. Not able to map through to display the list of blog comments. I'm using Django and react. From the code below, I tried to assess each blog post with comments using foreign key. But I'm not able to get the comment property from the blog. If I do something like {blog.title} I get the title of the blog back on the browser. Since comments are associated with each post I try to get different properties of comment from the blog object (just as I specified in the code below) but the value I'm getting is undefined. And have the following blog post and blog comment models:
class BlogComment(models.Model):
post = models.ForeignKey(BlogPost, on_delete=models.SET_NULL, related_name="post_comment", null=True)
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, related_name="user_comment", null=True)
name = models.CharField(max_length=200, null=True, blank=True)
comment = models.TextField(null=True, blank=True)
dateCreated = models.DateTimeField(auto_now_add=True)
def __str__(self):
return str(self.user.username)
class BlogPost(models.Model):
...
author = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.CASCADE)
body = models.TextField()
dateCreated = models.DateTimeField(auto_now_add=True)
And the serializers for both models are:
class CommentSerializer(serializers.ModelSerializer):
class Meta:
model = BlogComment
fields = '__all__'
class BlogPostSerializer(serializers.ModelSerializer):
comments = serializers.SerializerMethodField(read_only=True)
class Meta:
model = BlogPost
fields = "__all__"
def get_comments(self, obj):
comments = obj.comment_set.all()
serializer = CommentSerializer(comments, many=True)
return serializer.data
The endpint of comment is path('posts/<str:pk>/comment/', CreateCommentView, name="create-comment"),.
The endpoint is working. I'm able to add comment to posts both from the front end. The error comes when I try to map through the
comments for each post. Get the error: AttributeError: 'BlogPost' object has no attribute 'comment_set'.
Here is the code I'm using to map through to display all the blogs of a particular post in the blog details page in react. I'm assess each blog there:
<h2>{blog.title}</h2>
<img src={blog.image} />
<div variant='flush'>
{blog.comments.map((comment) => (
<div key={comment.id}>
<strong>{comment.name}</strong>
<p>{comment.dateCreated}</p>
<p>{comment.comment}</p>
</div>
))}
</div>
Here is the code I'm using to map through to display all the blogs of a particular post in the blog details page in react. If I do not map the error does not come up and I'm able to add comment. However, in order to display the comments under each blog post I map through. How do I fix this?
You need to use post_comment:
comments = obj.post_comment.all()
You declared it here:
post = models.ForeignKey(BlogPost, on_delete=models.SET_NULL, related_name="post_comment", null=True)
related_name is used as a name for Django relation. See more here.
But changing post_comment with something else would be a better solution for me.
Related
I am trying to make a button on the post that when a user cliks on it, is requesting to be added to the post as an attendance and then, the author of the post has to approve that request.
Models.py
class Attending(models.Model):
is_approved = models.BooleanField(default=False)
attending = models.ManyToManyField(User, related_name='user_event_attending')
class Post(models.Model):
title = models.CharField(max_length=100)
content = models.TextField(blank=True)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
attending = models.ForeignKey(Attending, on_delete=models.CASCADE, verbose_name='atending', null=True)
My problem here is that every time I writte a query for the button is giving me erros and I couldn`t figure it out how to get the reverse of the foreign key.
This is my code on my views.py
def request_event(request, pk):
previous = request.META.get('HTTP_REFERER')
try:
query = Attending.objects.get(pk=pk)
request_attending = query.post_set.add(request.user)
messages.success(request, f'Request sent!')
return redirect(previous)
except query.DoesNotExist:
return redirect('/')
Thank you very much for your help in advance!
This: query.post_set is just relationship. You cannot call method add just like that. You can add to ManyToMany relation and I believe you want to add user to Attending.attending field, not directly to Post object. Change that to:
...
query = Attending.objects.get(pk=pk)
query.attending.add(request.user)
messages.success(request, f'Request sent!')
....
| Update |
I think you should consider rearraning your relationships. If I understand your plan, you should go this way:
class Attending(models.Model):
...
attendant = models.ForeignKey(User, related_name='events_attending', on_delete=models.CASCADE)
post = models.ForeignKey('Post', on_delete=models.CASCADE)
class Post(models.Model):
...
author = models.ForeignKey(User, on_delete=models.CASCADE)
For one Post object there can be many Attending objects, then you can use relations like that:
att = Attending.objects.first()
att.post # get related Post object from ForeignKey | there is only one
post = Post.objects.first()
post.attending_set.all() # get all related Attending objects
Post.objects.get(attending=att) # get Post object that the Attending object have in ForeignKey field
user = User.objects.first()
user.post_set.all() # get all Post objects that User is author in
user.events_attending.all() # get all related Attending objects
For more check Django Docs.
I been struggling with this for a while and can't seem to find an answer on any of the other threads.
I am trying to programmatically add some entries to a model in Django, the model I am trying to add to has a foreign key, and this is what I am getting hung up on.
My two models are:
class Post(models.Model):
direct_url = models.URLField(unique=True)
post_url = models.URLField()
post_title = models.CharField(max_length=300)
time_posted = models.DateTimeField(default=timezone.now)
class Comment(models.Model):
post = models.ForeignKey(Post, related_name='comments', on_delete=models.CASCADE)
content = models.CharField(max_length=500)
author = models.CharField(max_length=60)
date_created = models.DateTimeField(default=timezone.now)
I am trying to run some code to add some data I am pulling from another location in the DetailView (Class based view)
The code that I have for that is here:
class PostDetailView(DetailView):
model = Post
for i in hot:
if i.url.endswith(Endings):
post_to = model.objects.get(direct_url=i.url)
submission = reddit.submission(url=f'https://www.reddit.com/r/{i.permalink}')
submission.comments.replace_more(limit=None)
for comment in submission.comments.list():
Comment.objects.create(post=f'{post_to}', content=f'{comment.body}', author=f'{comment.author}', date_created=f'{datetime.datetime.fromtimestamp(comment.created)}')
I am trying to pull the reddit comments, and store them in a database. The problem I am running into is the following:
ValueError: Cannot assign "'Post object (22)'": "Comment.post" must be a "Post" instance.
What am I doing wrong?
As per this meta directive, I have turned the following comment by #Sajad into a community wiki, signalling that this question is solved.
In the last line, you're formatting post_to to string and assigning it to post which must be a Post instance and not str. Just write post=post_to.
The following code should work:
class PostDetailView(DetailView):
model = Post
for i in hot:
if i.url.endswith(Endings):
post_to = model.objects.get(direct_url=i.url)
submission = reddit.submission(url=f'https://www.reddit.com/r/{i.permalink}')
submission.comments.replace_more(limit=None)
for comment in submission.comments.list():
Comment.objects.create(post=post_to, content=f'{comment.body}', author=f'{comment.author}', date_created=f'{datetime.datetime.fromtimestamp(comment.created)}')
I have a blog project and users can create posts with similar titles, How can I prevent a user or even the admin from proceeding without getting an error that the title already exists so that I can avoid future errors in the website such as get() returned more than one Post-it returned 2!
I have tried to use class meta for unique together but still, post was saved with the same title
Here is the post model
class Post(models.Model):
designer = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
slug = models.SlugField(blank=True, null=True, max_length=120)
def __str__(self):
return self.title
class Meta:
unique_together = ('title', 'slug')
You can add unique=True
title = models.CharField(max_length=100, unique=True)
See the docs here.
I have an app within my project called posts, where inside their in the models.py, I have two models: Post and Like.
I want to add a many-to-many-field on the post that references the Like model.
I have executed makemigrations and migrate, however I am getting this error:
NameError: name 'Like' is not defined
models.py:
class Post(models.Model):
file = models.ImageField(upload_to='images/')
summary = models.TextField(max_length=600)
pub_date = models.DateTimeField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.ManyToManyField(Like)
def __str__(self):
return self.user.username
def summary_pretty(self):
return self.summary[:50]
def pub_date_pretty(self):
return self.pub_date.strftime('%b %e %Y')
class Like(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
user = models.ForeignKey(User, on_delete=models.CASCADE)
status = models.BooleanField(default=False)
it says
NameError: name 'Like' is not defined
because you must move Like model above Post model it hasn't been defined yet in your code in that line (python code is interpreted)
and it's not a good thing to design database models like that based on:
Why should I avoid loops when designing relationships for a database?
so delete the Post foreign key in Like model and you can retrieve a like's post with reverse lookup
you can find more about it in django official docs:
Lookups that span relationships
and also
Many-to-many relationships
You're referencing the class Like before initiating it in your Python file. Hence "Like" is not defined.
likes = models.ManyToManyField(Like)
You need to delete "likes" from your Post class. That will fix the error.
As for your code, I think you're misunderstanding why we use Intermediary Tables. You don't need to reference Like in your Post class. You've already established that relationship in the Like Class:
post = models.ForeignKey(Post, on_delete=models.CASCADE)
Retrieving the users who have liked a post is as simple as writing a filter on the Likes table.
#views.py
from models import Post, Like
post_id = 1
likes = Like.objects.filter(post=post_id)
I'm trying to find the most efficient way (as less db queries as possible) for the following model structure.
In my template I then want to pass all the data from all 3 models because I would have to show the post data as well as looping through the comments to create a comments list and display all the attachments for the different comments.
class Post(BaseModel):
user = models.ForeignKey('User', blank=True, null=True,
title = models.CharField(max_length=128)
content = models.TextField()
class Comment(BaseModel):
post = models.ForeignKey('Post', on_delete=models.CASCADE)
user = models.ForeignKey('User', on_delete=models.SET_NULL)
text = models.TextField()
class CommentAttachment(BaseModel):
comment = models.ForeignKey('Comment', on_delete=models.CASCADE)
name = models.CharField(max_length=128)
Should I fetch all data from CommentAttachment direction (meaning fetching all CommentAttachments where comment__post__id is the post id and then get all other data with select_related) or is there another way to start from the Post Model?
You can use prefetch_related or select_related in your query:
posts = Post.objects.filter(user=some_user).prefetch_related(
'comment_set', 'comment_set__commentattachment_set'
)
For example, after making a query as mentioned, the following command may retrieve all the comments for the first post in the queryset without making a SQL query:
posts.first().comment_set.all()