Count Object in Models Django - python

I have a problem with creating a modelfield which Count number of people who like an article.
I have class Like:
class Reaction(models.Model):
user = models.ForeignKey(User)
article = models.IntegerField(null=True, blank=True)
date = models.DateTimeField(auto_now_add=True, null=True)
and class Article:
from api.reactions.models import Reaction
class Article(models.Model):
user = models.ForeignKey(User)
post = models.TextField()
likes = models.IntegerField(default=0)
def __str__(self):
return self.post
def calculate_likes(self):
likes = Reaction.objects.count(article=self.pk)
self.likes = likes
self.save()
return self.likes
But likes wont be counted.
What's wrong with this? Please help me. Thanks!

def get_likes(self):
return self.likes.all().count()
this should basically be it, you don't need to point a model to an instance of itself, creating a reaction class is overkill.
But if you are still going for it instead of:
likes = Reaction.objects.count(article=self.pk)
Try:
likes = Reaction.objects.filter(article=self.pk).count()

Related

How to create a function that counts total string objects in my ArrayField column for my model?

Trying to create a column in my model called, stock_count, that finds the sum of the total string objects in my ArrayField(), aka stock_list. Here is my function.
def total_stocks_calc(self):
self.stock_count = Bucket.objects.aggregate(Sum('stock_list', distinct=True))
self.save()
However it doesn't seem to be doing anything, no calculating, leaving the field blank in my model, admin page, and DRF interface...
EDIT: updated post with new implementation.
Here is my model.
class Bucket(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='buckets')
users = models.ManyToManyField(settings.AUTH_USER_MODEL)
category = models.CharField(max_length=30, choices=category_options)
name = models.CharField(max_length=35)
created = models.DateTimeField(default=timezone.now)
slug = models.SlugField(unique=True, blank=True)
stock_count = models.IntegerField(blank=True, null=True)
stock_list = ArrayField(models.CharField(max_length=6,null=True),size=30,null=True)
about = models.CharField(max_length=75)
objects = models.Manager()
bucketobjects = BucketObjects()
class Meta:
ordering = ('-created',)
def total_stocks_calc(self):
self.stock_count = Bucket.objects.annotate(stock_count=F('stock_list__len'))
self.save()
def __unicode__(self):
return self.stock_list
Would like to know the proper way to count total items in ArrayField(), thank you in advance.
The ArrayField provides the len lookup field, through that you can get the count
like
from django.db.models import F
Bucket.objects.annotate(stock_count=F('stock_list__len'))

How to show foreignkey attributes django admin fields?

This question is similar with others but it is a different one actually ! So, I have 3 models such as (I have deleted some unnecessary things for shorter code):
class Category(models.Model):
category_title = models.CharField(max_length=200)
category_content = models.TextField()
category_slug = models.CharField(max_length=200)
def __str__(self):
return self.category_title
class Classes(models.Model):
classes_title = models.CharField(max_length=200)
classes_content = models.TextField()
classes_category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT)
def __str__(self):
return self.classes_title
class Subjects(models.Model):
subject_title = models.CharField(max_length=200)
subject_content = models.TextField()
subject_class = models.ForeignKey(Classes, on_delete=models.SET_DEFAULT)
def __str__(self):
return self.subject_title
So let me give an example. I can have 2 categories and in those categories I can have "same named" classes. Lets think about maths is a class for both categories. When I want to add a new subject to maths I see 2 same named maths in admin page. So I want to know which one belongs to which category in admin page. So I can add my subject to right class.
class SubjectAdmin(admin.ModelAdmin):
fields = ('subject_title', 'subject_content', 'subject_class',)
So in this picture (Subjects = Konular) I am adding a new subject. I will have a foreign key to Class. However I have same name for classes that are coming from different categories. So in this dropdown how can I know which class belongs to which category ?
Try this...
class KonularAdmin(admin.ModelAdmin):
fields = ('subject_title', 'subject_content', 'subject_class', 'get_classes_category_title')
def get_classes_category_title(self, obj):
subject_object = Subjects.objects.get(id=obj.subject_class)
return str(subject_object.classes_category.category_title)
It returns the category title name
If I understood you correctly, This should work.
class Classes(models.Model):
classes_title = models.CharField(max_length=200)
classes_content = models.TextField()
classes_category = models.ForeignKey(Category, on_delete=models.SET_DEFAULT)
def __str__(self):
return self.title
class Subjects(models.Model):
subject_title = models.CharField(max_length=200)
subject_content = models.TextField()
subject_class = models.ForeignKey(Classes, on_delete=models.SET_DEFAULT)
def __str__(self):
return f"{self.subject_title} - {str(self.subject_class)}"
You can use __str__() method to change the string representation of an object:
class Subjects(models.Model):
subject_title = models.CharField(max_length=200)
subject_content = models.TextField()
subject_class = models.ForeignKey(Classes, on_delete=models.SET_DEFAULT)
def __str__(self):
return f"{self.subject_title} - {self.subject_content} - {self.subject_class}"
# shorter version:
# return f"{self.subject_title[:10]} - {self.subject_content[:10]} - {self.subject_class[:10]}"
Check it with:
>>> print(Subjects.objects.first())

Unread posts Django

I've build a blog using Django (very minimal functional blog) and I want to be able to show to the user in my blog only the posts he hasn't read yet.
I have 10,000+ posts and I want to show the user every time he log in a random posts he has not seen yet/
I am new with Django and I not sure I should do it the right way.
I have the Post model:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
Thank you!
You should use ManyToManyField:
class Post(models.Model):
author = models.ForeignKey('auth.User',on_delete=models.CASCADE)
title = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(default=timezone.now)
published_date = models.DateTimeField(blank=True, null=True)
read_users = models.ManyToManyField(User) # Add this line
def publish(self):
self.published_date = timezone.now()
self.save()
def approve_comments(self):
return self.comments.filter(approved_comment=True)
def get_absolute_url(self):
return reverse("post_detail",kwargs={'pk':self.pk})
def __str__(self):
return self.title
You have to keep record of user and which posts he has read. Just like this
class UserReadPost(models.Model):
user = models.ForeignKey(User, releated_name='user_read_posts')
post = models.ForeignKey(Post, releated_name='posts_read_by_users')
read_at = models.DateTimeField(auto_now=True)
You will have to add a record in this table every time a user read some post. You can get all posts which user have not read yet like this.
from django.db.models import OuterRef, Subquery, Exists
post_read_status = UserReadPost.objects.filter(post=OuterRef('post'), user=current_user_object)
Post.objects.all().annotate(has_read=Exists(post_read_status)).exclude(has_read=True).order_by('?')
This can be done using ManyToManyField but adding your own table will give you ability to check when that user read that specific post.

'Registered_Courses' object has no attribute 'course_set' Django

I am really stuck on this error and it does not make sense why it does not follow the relationship backward on Registered_Courses on the foreign key for Courses when i use course_set
views.py
def registered_coursesView(request, username):
'''Page to display the registered courses of a user.'''
registeredCourses = Registered_Courses.objects.get(owner = request.user)
courseInfo = registeredCourses.course_set.all()
context = {'registeredCourses': registeredCourses, 'courseInfo':courseInfo}
return render(request, 'safetyCourseApp/registered_courses.html', context)
models.py
class Course(models.Model):
'''Offered Course information.'''
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
name = models.CharField(max_length=200, primary_key=True)
description = models.TextField()
date_added = models.DateTimeField(auto_now_add=True)
start_date = models.DateField()
end_date = models.DateField()
price = models.DecimalField(max_digits=10, decimal_places=2)
capacity = models.IntegerField()
registered_ppl = models.IntegerField()
def __str__(self):
"""Return a string representation of the model."""
return self.name
class Registered_Courses(models.Model):
"""Something specific learned about a Course."""
registered_course = models.ForeignKey(Course, on_delete=models.CASCADE, null=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE, null=True)
def __str__(self):
"""Return a string representation of the model."""
return f'{self.owner}'
Please let me know what you guys think. I cannot think of a reason why this is not working. Thanks!
As you have specified in your models, each Registered_Courses will have a FK to Course, So each Course can have multiple Registered_Courses.
But you are trying to get multiple Course objects from a single Registered_Courses
The backward relationship is something like:
>>> course = Course.objects.first()
>>> course.registered_courses_set

Django Python m2m_change does not work when removing the relation

I am writing a project related to courses. However, the save() does not work when I use Django admin to add CourseSession. But when I edit it and then save, it will work. Please help me. Followings are class CourseSession and Course. What I am doing here is to update instructors of each course automatically when related course session is added.(update: I have used the m2m_change function but it wont work when removing course session)
def course_session_instructor_changed(sender, instance, action, **kwargs):
superCourse = instance.course
superCourse.instructors.clear()
course_session_set = superCourse.course_session.all()
for each_course_session in course_session_set:
# add instructor
if action=="post_add":
instructors = each_course_session.instructors.all()
for instructor in instructors:
if not instructor in superCourse.instructors.all():
superCourse.instructors.add(instructor)
# remove instructor
elif action=="pre_remove" :
if not each_course_session == instance:
instructors = each_course_session.instructors.all()
for instructor in instructors:
if not instructor in superCourse.instructors.all():
superCourse.instructors.add(instructor)
superCourse.save()
m2m_changed.connect(course_session_instructor_changed, sender=CourseSession.instructors.through)
class CourseSession(models.Model):
course = models.ForeignKey('Course', related_name='course_session')
instructors = models.ManyToManyField(User, related_name = 'instructor_course_session')
enrollment = models.ManyToManyField(User, related_name = 'course_enrollment')
start = models.DateField()
# Weeks of duration
duration = models.IntegerField()
# capacity of the session
max_cap = models.IntegerField()
questionSet = models.ManyToManyField(QuestionSet, blank=True, null=True, related_name='session_questionSet')
class Meta:
verbose_name = _('Session')
verbose_name_plural = _('Sessions')
get_latest_by = "start"
def __unicode__(self):
return unicode(self.instructors.all())+unicode(self.course)+unicode(self.start)
def is_started(self):
return date.today()> self.start
def is_expired(self):
length = timedelta(days = self.duration*7)
return self.start+length< date.today()
def get_enrollment(self):
return self.enrollment.count()
**class Course(models.Model):
name = models.CharField(_('Course Name'),max_length=256)
# Simple Introduction
brief_intro = models.CharField(_('Brief Intro'),max_length=1024)
intro = models.TextField()
learning_obj = models.TextField()
creator = models.ForeignKey(User, related_name = 'course_creator')
created = models.DateTimeField(auto_now_add=True)
cover = models.ImageField(upload_to = 'course/covers/')
institute = models.ForeignKey('Institute', related_name='institute_courses')
workload = models.IntegerField()
assignments = models.IntegerField()
exams = models.IntegerField()
knowledge_tree_root = models.ForeignKey(Topic, related_name='knowledge_tree_root')
instructors = models.ManyToManyField(User, related_name='courses', null=True, blank=True)
#tree_root = models.ForeignKey('Topic')
class Meta:
verbose_name = _('Course')
verbose_name_plural = _('Courses')
def __unicode__(self):
return self.name
It won't work the first time, as many-to-many fields can't be set until the instance has been saved once (since they're saved in a separate table, and have to have an ID to link to). So the admin doesn't set the values until after the save.
Rather than override save, you probably want to use the m2m_changed signal.

Categories

Resources