how to delete item in listfield for django nonrel - python

I use mongodb as the django nonrel database to build a blog site. The basic models for the blog site are:
class Post:
comments = ListField(EmbeddedModelField('Comment'))
....(omitted here)
class Comment:
created = models.DateTimeField(auto_now_add=True)
author = models.CharField(max_length=35)
email = models.EmailField(max_length=64)
text = models.TextField()
ip_addr = models.IPAddressField()
I found that when I created a comment and append it to the listfield of a post, the comment will not have an objectid because it's embedded. Thus, when I want to delete a comment, I have trouble to let the database know which comment I want to delete. Is it possible that I pass the comment from the template to views without the url function in urls.py?

You can rewrite the model as
class Post:
comments = ListField(models.ForeignKey('Comment'))
....(omitted here)
class Comment:
created = models.DateTimeField(auto_now_add=True)
author = models.CharField(max_length=35)
email = models.EmailField(max_length=64)
text = models.TextField()
ip_addr = models.IPAddressField()

Related

"Object has no property _set" in Django

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.

How to auto increment a model field in django admin form by having add another on the side?

I have this model:
class BlogPost(models.Model):
author = models.CharField(max_length=64, default='Admin')
image = models.ImageField(blank=True, null=True)
title = models.CharField(max_length=255)
caption = models.CharField(max_length=500)
content = RichTextUploadingField()
# todo support for tags
tags = models.CharField(max_length=255, default='travel') #todo
date_created = models.DateField()
Now in tags field, I want to give multiple strings like #tips, #travel, etc on the same field. What I want is there should be like an add or increment tag, which when I click will show another tag field appears on the admin form and the user can adder another tag.
My backend is not on the regular HTML page. I have customized the default Django admin page for the backend using the material package. That is I cant use button tag and all.
How can I achieve this?? I have an image attached which explains better.
Image here
You can create another model called Tag and connect it to your BlogPost like this:
class Tag(models.Model):
text = models.CharField(max_length=244, default='travel')
blog_post = models.ForeignKey(BlogPost, on_delete=models.CASCADE, related_name='tags')
Then if you want to acces tags of a certain post in a view you would use:
blog_post = BlogPost.objects.get(pk=pk) # query the blog post you want the tags to
tags = blog_post.tags.all() # get the tags
Then simply add a form to each blog post where you would add a tag and save it to the related post. I'm not sure how you would do it an an admin interface though.

Add entries to model with ForeignKey

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)}')

Django efficient Queryset with Foreign Key Models

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()

Select Children of an Object With ForeignKey in Django?

I'm brand new to Django, so the answer to this is probably very simple. However, I can't figure it out.
Say I have two bare-bones Models.
class Blog(models.Model):
title = models.CharField(max_length=160)
text = models.TextField()
class Comment(models.Model):
blog = models.ForeignKey(Blog)
text = models.TextField()
In the Python/Django shell, if I have a Blog object in a variable (say blog = Blog.objects.get(id=3)), how do I select all its child comments?
This doesn't seem to work: blog.objects.all()
to follow foreign keys 'backwards' you use
blog.comment_set.all()

Categories