I am creating simple forum site using Django framework, and I've created comment model, at this moment my comment model has OneToOne relation with Post, it means that every moment belong to specific post, but there is also another feature that I want to provide. Every comment model should has possibility to be related to Post object OR to Answer model. Answer model it is just as in Stack Overflow, you add a Post and another user can add an answer to it. I want to mention that answer is too related with Post with OneToOne relation I think it will be sufficient and dosen't need edition.
Summarizing: How to allow adding comments to Post object or Answer object?
Also I want to say that I was considering creating two comments models, namely PostComment, and AnswerComment but I've got a conclusion that is really bad solution.
class Post(models.Model):
subject = models.CharField(max_length=100)
description = models.TextField(null=True)
section = models.ForeignKey(Section, on_delete=models.CASCADE, null=True)
author = models.ForeignKey(User, null=True, blank=True)
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
slug = models.SlugField(max_length=100, null=True)
active = models.BooleanField(default=True)
def __str__(self):
return self.subject
def publish(self):
self.published_date = timezone.now()
self.save()
def close(self):
self.active = False
self.save()
class Comment(models.Model):
content = models.CharField(max_length=600)
post = models.OneToOneField(Post, on_delete=models.CASCADE)
author = models.ForeignKey(User, null=True, blank=True)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return "Comment to post: {0} added by {1} at {2}.".format(self.post.subject, self.author, self.published_date)
class Answer(models.Model):
content = models.TextField()
post = models.OneToOneField(Post, on_delete=models.CASCADE)
author = models.ForeignKey(User, null=True, blank=True)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def __str__(self):
return "Answer to post: {0} added by {1} at {2}.".format(self.post.subject, self.author, self.published_date)
Answer can be associated to only one post, so one to one
comment can only be associated with one post, so one to one
comment can only be associated with one answer, so one to one
Remember that the order of classes matters in Python. Place the comment class at the end, so that you can create one to one relationships between both Post and Answer. In the current position you can only do it with Post.
class Post(models.Model):
##
class Answer(models.Model):
##
class Comment(models.Model):
post = models.OneToOneField(Post, on_delete=models.CASCADE, null=True, blank=True)
answer = models.OneToOneField(Answer, on_delete=models.CASCADE, null=True, blank=True)
If one Post object can have several comments, I think you need ForeignKey in your comment field. About Answer, maybe you can add another field to your comment pointing to the object Answer which is related, with a ForeignKey if several comments are permited for an answer.
Related
I`m creating a simple blog now, and the main problem is to create a relation between Users. I use a default django User which should subscribe another user who is an author of post.
I have only one Post model in my app
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
title = models.CharField(max_length=128)
content = models.TextField(blank=True)
created_on = models.DateTimeField(auto_now_add=True)
seen = models.ManyToManyField(User, related_name='blog_posts', blank=True)
The relationship you're referring to isn't about the Post model as I understand it. So I think it might be better if you create a separate model. I share a model below as an idea, you can edit field names or add/delete fields according to your needs.
class AuthorSubscription(models.Model):
author = models.OneToOneField(User, on_delete=models.CASCADE, 'author_subscription')
subscribers = models.ManyToManyField(User, related_name='subscriptions', blank=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
I work on the voting system (vote up and vote down) and the functionality - follow.
I want it to be done well, because I don't have anyone to advise, I put the post and code here.
Follow function - it should show how many followers there are and who they are. I used here a m2m relation with the intermediate model Follower.
My question - is this the correct approach to the topic - using m2m with an intermediate model here?
Functionality vote up and vote down - it is supposed to show how many votes up and how many down and who voted down and who voted up.
My question is whether there is also OK here with the relation between m2m and the intermediate model Voter?
Code for follow feature:
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='posts')
title = models.CharField(max_length=255, unique=True)
description = models.TextField(max_length=1024)
followers = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Follower', blank=True)
is_visible = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('posts:post_detail', kwargs={'pk': self.pk})
def number_of_followers(self):
return self.followers.count()
class Follower(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user
Code for vote up and vote down feature:
class Question(models.Model):
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
title = models.CharField(max_length=200)
vote_up = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Voter', blank=True)
vote_down = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Voter', blank=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('qa:qa_detail', kwargs={'pk': self.id})
class Voter(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.user
Now is working only follow feature but I want to make sure my approch is ok. Please and thanks for your help.
Currently there is nothing that differentiates the up_vote from the down_vote on the Question model so this will return the same query.
As a side note if you plan to add similar voting/following functionality to other models it may be worth considering whether this is a good use case for a Generic Relationship. This will create a polymorphic relationship and is DRY.
Here are the docs
generic relations
I tried to solve the problem and got stuck. The problem is that I have a post that I can follow. My problem is that I don't know how to add a tracking button. Should this be done by url, with a view? Or should it be rather as a method in the model?
My problem is also whether it is properly written in terms of models - using the intermediate model Follower?
Here is Post model and I would like to add followers here. I mean, everybody who is interested, can follow this post.
class Post(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='posts')
title = models.CharField(max_length=255, unique=True)
description = models.TextField(max_length=1024)
followers = models.ManyToManyField(settings.AUTH_USER_MODEL, through='Follower', blank=True)
is_visible = models.BooleanField(default=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('posts:post_detail', kwargs={'pk': self.pk})
def number_of_followers(self):
return self.followers.count()
Here is my manager for follower model:
class FollowerManager(models.Manager):
use_for_related_fields = True
def follow(self, user, pk):
post_object = get_object_or_404(Post, pk=pk)
if user.is_authenticated():
if user in post_object.followers.all():
Follower.objects.filter(post=post_object, user=user).delete()
else:
Follower.objects.create(post=post_object, user=user)
Here is Follower model:
class Follower(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
post = models.ForeignKey(Post, on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
objects = FollowerManager()
Interactions between a user's browser and the database can only be done via a URL and a view. That view might call a model method, but there is no possible way for the browser to call that method directly.
(Also I don't understand what you're doing in the manager. Why are you deleting followers if the user is authenticated? Note that will always be true, so the followers will always be deleted.)
I got an error,ValueError at /app/recomment/1/
Cannot assign "": "ReComment.target" must be a "POST" instance.The error is happened when I put Recomment button.I wanna make a page which is shown comment&recomment.I wrote codes
in models.py
class POST(models.Model):
title = models.CharField(max_length=100)
created_at = models.DateTimeField(auto_now_add=True)
class Comment(models.Model):
name = models.CharField(max_length=100, blank=True)
target = models.ForeignKey(POST, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, null=True)
class ReComment(models.Model):
name = models.CharField(max_length=100, blank=True)
target = models.ForeignKey(POST, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True, null=True)
I cannot understand the error message's meaning that is I should put POST into obj.target = comment in place of comment in views.py.The variable of comment is send via POST,so I think this is POST instance.I cannot understand the difference of POST instance and normal instance.What is wrong in my code?How should I fix this?
Do something like this and check that to not forget anything.
class DetailView(generic.DetailView):
model = POST <<<<-------- error give true model here
template_name = 'detail.html'
From the last seven days I am trying to build a blog using django and I figured out the model for my blog as follows
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=200)
body = models.TextField()
created_at = models.DateTimeField('created date', auto_now_add=True, auto_now=False)
updated_at = models.DateTimeField('updated date', auto_now_add=False, auto_now=True)
def __str__(self):
return self.title
class Author(models.Model):
name = models.CharField(max_length=150)
email = models.EmailField(blank=True)
bio = models.TextField()
#This line define many author can have a post
#but I want manypost can only have single author.
#in my view to accomplish this i need to define author in Post class
#on defining author=ForeignKey(Author) in post, It throws an error Author is not defined
post = models.ForeignKey(Post)
def __str__(self):
return self.author
class Category(models.Model):
cat_name = models.CharField(max_length=200)
post = models.ManyToManyField(Post)
def __str__(self):
return self.cat_name
The thing that I am so much confused is the relation between the Post, Categories, Author and Tag.
Relation What I wanted to set is
author can have many posts, A post can have only single author
categories can have many posts, A post can have many categories
a tag can have many posts a post can have many tags
But the models that I am created above is not working as I expected(I am so confused).
when I put the author field in Post Class, so that i would be a relation like, an author can have many posts, but I got the error Author is not defined.(as I know the interpreter run code from top to bottom). How do I accomplish
You have two options:
Change Author and Post position, thus Page can see Post definition.
Use Lazy call as: author= models.ForeignKey("Author")
In this way, Django will wait until all models load then resolve the dependencies.
Try model structure syntax:
class Author(models.Model):
name = models.CharField(max_length=150)
email = models.EmailField(blank=True)
bio = models.TextField()
def __str__(self):
return self.author
class Post(models.Model):
author = models.ForeignKey(Author)
title = models.CharField(max_length=200)
body = models.TextField()
created_at = models.DateTimeField('created date', auto_now_add=True, auto_now=False)
updated_at = models.DateTimeField('updated date', auto_now_add=False, auto_now=True)
def __str__(self):
return self.title
class Category(models.Model):
cat_name = models.CharField(max_length=200)
post = models.ManyToManyField(Post)
def __str__(self):
return self.cat_name
class Tag(models.Model):
tag_name = models.CharField(max_length=200)
post = models.ManyToManyField(Post)
def __str__(self):
return self.tag_name
This will solve your three requirements:
1.) Author can have many posts because I set the Post Model into one-to-many field
2.) Categories can have many posts vice versa (This is already set according to your code)
3.) Tag can have many posts vice versa (Very similar to your already made Category Model where I made the field many-to-many between the two)
The reason why you got an error is because you made your author to post relation to many-to-one (many authors in one post) according to your model structure
Now to test it simply migrate all these changes and quickly test it in your admin page
author can have many posts, A post can have only single author
Post model should have a ForeignKey pointing to Author.
class Post(...):
author = models.ForeignKey('Author')
categories can have many posts, A post can have many categories
Post model should have a ManyToManyField pointing to Category.
class Post(...):
category = models.ManyToManyField('Category')
a tag can have many posts a post can have many tags
Same as number 2.