How to associate a comment with a parent comment in Django models - django

I have built an application with comments that are commented on a parent comment. I have the following comment model. How can I associate the comment with a parent comment ?
class Comment(models.Model):
uuid = models.UUIDField(max_length=255, default = uuid.uuid4)
description = models.CharField(max_length=5000, default="")
likes = models.PositiveIntegerField(default=0)
dislikes = models.PositiveIntegerField(default=0)
uploaded_at = models.DateTimeField(null=True, blank=True)
commentinguser = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.PROTECT)
video = models.ForeignKey(Video, on_delete=models.CASCADE)

You can have a recursive ForeignKey (a foreign key to the same model) by passing "self"
parent = models.ForeignKey('self', on_delete=models.CASCADE, null=True)

Related

How to use django-autocomplete-light and django-hacker to make a chained dropdown in django admin?

I have 3 models 1) university 2) courses and 3) enquiry.
My enquiry model has a foreign key to "course". And Course has a foreign key to the university. I only want to show the courses related to that university while adding an enquiry. I tried django-smart-select but failed to do so. I tried This answer but I dont understand the logic and failed to implement in my project.
this is my models.py file
class university(models.Model):
univ_name = models.CharField(max_length=100)
country = CountryField(blank=True, null=True)
univ_desc = models.CharField(max_length=1000)
univ_logo = models.ImageField(upload_to="media")
univ_phone = models.CharField(max_length=10, blank=True)
univ_email = models.EmailField(max_length=254, blank=True)
univ_website = models.URLField(blank=True)
assigned_users = models.ForeignKey(get_user_model(), on_delete=models.CASCADE, default="")
def __str__(self):
return self.univ_name
class Meta:
verbose_name_plural = "Universities"
class Course(models.Model):
university = models.ForeignKey(university, on_delete=models.CASCADE)
course_name = models.CharField(max_length=100)
course_levels = models.ForeignKey(course_levels, on_delete=models.CASCADE)
intake = models.ForeignKey(intake, on_delete=models.CASCADE)
documents_required = models.ForeignKey(documents_required, on_delete=models.CASCADE)
course_requirements = models.ForeignKey(course_requirements, on_delete=models.CASCADE)
Active = models.BooleanField()
def __str__(self):
return self.course_name
class enquiry(models.Model):
student_name = models.CharField(max_length=100)
student_phone = models.CharField(max_length=10)
student_email = models.EmailField()
student_address = models.TextField()
current_education = models.ForeignKey(current_education, on_delete=models.CASCADE)
country_interested = CountryField(blank=True, null=True)
university_interested = models.ForeignKey(university, on_delete=models.CASCADE)
course_interested = models.ForeignKey(Course, on_delete=models.CASCADE, limit_choices_to={'Active':True})
level_applying_for = models.ForeignKey(course_levels, on_delete=models.CASCADE)
intake_interested = models.ForeignKey(intake, on_delete=models.CASCADE)
assigned_users = models.ForeignKey(User, on_delete=models.CASCADE, default="", limit_choices_to={"is_active": True})
enquiry_status = models.ForeignKey(enquiry_status, on_delete=models.CASCADE, default="")
course_interested= ChainedForeignKey(Course,chained_field= 'university_interested',chained_model_field= 'university',show_all= False,auto_choose= True,sort=True,limit_choices_to = {"Active": True},)
I want to show the course_interested field related to that university. Need help.
I tried using django-smart-select but failed to implement it. I am not aware of jquery and ajax so that is out of the question to use in my project.
got the solution I used the django-select2 and was able to solve this issue.

Django rest framework get data from foreign key relation?

I have a models like this:
class Author(models.Model):
name = models.CharField(max_length=150, blank=False, null=False)
dob = models.DateField(null=True, blank=True)
description = models.TextField(max_length=2000, blank=False, default="This author doesn't have any description yet!")
image = models.ImageField()
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['created']
def __str__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=200, blank=False, null=False)
author = models.CharField(max_length=200)
genres = models.ManyToManyField(Genre, related_name='genre', blank=True)
author = models.ForeignKey(Author, related_name='author', blank=True, on_delete=models.CASCADE)
description = models.TextField(max_length=1200, blank=False, default="This book doesn't have description yet!")
image = models.ImageField(default="")
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
class Meta:
ordering = ['created']
def __str__(self):
return self.title
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
book = models.ForeignKey(Book, on_delete=models.CASCADE)
title = models.CharField(max_length=100, null=False, blank=False, help_text="Title overall of your review")
rating = models.IntegerField(validators=[MinValueValidator(0), MaxValueValidator(5)], help_text='Rating in range 0-5')
description = models.TextField(max_length=1000, null=False, blank=False)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
I want to get Book data response in json with my reviews of the book from my Review table but don't know how. I am not getting any useful solution from documentation and Google, please help.
You could set the related_name field in the book field of the Review model.
class Review(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
book = models.ForeignKey(Book, on_delete=models.CASCADE, related_name = 'reviews')
...
Then in the serializer, you can add the related field.
class ReviewSerializer(serializers.ModelSerializer):
class Meta:
model = Review
fields = '__all__'
class BookSerializer(serializers.ModelSerializer):
reviews = ReviewSerializer(many = True)
class Meta:
model = Book
fields = '__all__'
extra_fields = ('reviews', )

Django annotate with 'field' of 'related_name' of 'related_name'

I have three models : Domain Topic Post
Topic has a foreign key to Domain and Post has a foreign key to Topic.
Post has a field updated_on.
I want to annotate last_updated field in Domain queryset which would contain the latest post object from Post .
Edit 1: Added models definition:
class Board(models.Model):
name = models.CharField(max_length=30, unique=True)
description = models.CharField(max_length=50)
creation_time = models.DateTimeField(auto_now_add=True)
class Topic(models.Model):
subject = models.CharField(max_length=300, unique=True)
board = models.ForeignKey(Board, on_delete=models.SET_NULL, related_name='topics', null=True)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='topics', null=True)
created_on = models.DateTimeField(auto_now_add=True)
views = models.PositiveIntegerField(default=0)
class Post(models.Model):
message = models.CharField(max_length=5000)
created_by = models.ForeignKey(User, on_delete=models.SET_NULL, related_name='posts', null=True)
created_on = models.DateTimeField(auto_now_add=True)
topic = models.ForeignKey(Topic, on_delete=models.SET_NULL, related_name='posts', null=True)
updated_on = models.DateTimeField(default=timezone.now)

django - deleting User raises integrity error

I am doing a "Reddit Clone" using django and these are my models:
models.py
class Profile(models.Model):
owner = models.OneToOneField(User, on_delete=models.CASCADE)
dob = models.DateField()
karma = models.IntegerField(default=0)
class Subreddit(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING, null=True, blank=True, related_name='subreddits')
name = models.CharField(max_length=100)
title = models.CharField(max_length=100)
description = models.CharField(max_length=500)
subscribers = models.ManyToManyField(Profile, blank=True, related_name='subscriptions')
moderators = models.ManyToManyField(Profile, blank=True, related_name='moderates')
class Post(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING)
title = models.CharField(max_length=300)
content = models.CharField(max_length=1000)
votes = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
subreddit = models.ForeignKey(Subreddit, on_delete=models.CASCADE)
class Comment(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING)
content = models.CharField(max_length=500)
votes = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
parent_post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent_comment = models.ForeignKey("Comment", null=True, blank=True, on_delete=models.CASCADE)
Now, I tried to delete a user who just made 1 comment. When I tried to delete the user from django admin, I got the following error.
IntegrityError at /admin/auth/user/2/delete/ (1451, 'Cannot delete or
update a parent row: a foreign key constraint fails
(redditdb.redditapp_comment, CONSTRAINT
redditapp_comment_owner_id_fdc65fee_fk_redditapp_profile_id FOREIGN
KEY (owner_id) REFERENCES redditapp_profile (id))')
I did user on_delete=models.CASCADE so I don't know why I am getting this error. Do I need to restructure the foreign keys in my models?
Actually reddit follows a structure where when a parent comment is deleted, its child comments won't get deleted. The deleted parent comment will be dashed or striked out and its child comments are still shown. Knowing this, how do I move forward with my code, should I delete profiles at all?
You Comment is not directly related to User. It is related through Profile. SO when you delete User, its Profile is deleted. which affects the comment, as it becomes dangling.
You can either have
owner = models.ForeignKey(Profile, on_delete=models.CASCADE)
or
owner = models.ForeignKey(Profile, on_delete=models.DO_NOTHING ,null=True)
The error mention that the owner_id of the app's redditapp Comment model references
the id of the app's redditapp Profile model, and the Comment model owner ForeignKey on_delete attribute
is set to models.DO_NOTHIN
DO_NOTHING:
Take no action. If your database backend enforces
referential integrity, this will cause an IntegrityError unless you
manually add an SQL ON DELETE constraint to the database field.
Your best choice is on_delete=models.CASCADE because comments are associated with a specific Profile, if the Profile is deleted its Comments become anonymous with no identifying Profile.
Edit:
Here if the parent comment is deleted the child will not, and the reference to the parent comment will be set to null
class Comment(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.CASCADE)
content = models.CharField(max_length=500)
votes = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
parent_post = models.ForeignKey(Post, on_delete=models.CASCADE)
parent_comment = models.ForeignKey("Comment", null=True, blank=True, on_delete=models.SET_NULL)
The same goes for Post model:
class Post(models.Model):
owner = models.ForeignKey(Profile, on_delete=models.CASCADE)
title = models.CharField(max_length=300)
content = models.CharField(max_length=1000)
votes = models.IntegerField()
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
subreddit = models.ForeignKey(Subreddit, on_delete=models.CASCADE)
Or you can prevent the deletion of the profile all along using models.PROTECT
You have two options:
parent_post = models.ForeignKey(Post, on_delete=models.CASCADE)
or
parent_post = models.ForeignKey(Post, on_delete=models.DO_NOTHING )

How to query articles a user has commented on?

I want to get all articles in which a user has commented but the article itself is created by others.
Here are the models:
class Article(models.Model):
title = models.CharField(max_length=300, blank=False)
body = models.TextField(max_length=10000, blank=False)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, blank=True, null=True)
updated = models.DateTimeField(auto_now=True)
class Comment(models.Model):
title = models.CharField(null=True, blank=True)
created = models.DateTimeField(auto_now_add=True)
creator = models.ForeignKey(User, null=True)
updated = models.DateTimeField(auto_now=True)
article = models.ForeignKey(Article)
body = models.TextField(max_length=10000)
published = models.BooleanField(default=True)
The query that I use is:
mycomments = Article.objects.filter(Q(comment__creator=request.user) and ~Q(creator=request.user)).order_by("-created")[:30]
But for some reason it returns many articles in which the user has not commented. So I'm wondering what should be the correct queryset?
Article.objects.filter(comment__creator=request.user) \
.exclude(creator=request.user).distinct()