I would like to create a variable that I can pass through as context which will count
how many posts a user liked.
Here is my models.py
class post(models.Model):
title = models.CharField(max_length = 255)
title_tag=models.CharField(max_length=255)
author = models.ForeignKey(User, on_delete = models.CASCADE)
body = models.TextField()
post_date = models.DateTimeField(auto_now_add=True)
category = models.CharField(max_length=255, default = "coding")
likes = models.ManyToManyField(User, related_name='blog_posts')
def __str__(self):
return self.title + ' | ' + str(self.author) + ' | ' + str(self.category)
def get_absolute_url(self):
from django.urls import reverse
return reverse('article-detail',args=[self.id] )
def total_likes(self):
return self.likes.count()
Here is my views.py
class ArticleDetailView(DetailView):
model = post
template_name = 'article_details.html'
def get_context_data(self,*args,**kwargs):
cat_menu = Category.objects.all()
#amount_of_user_likes = ????
context = super(ArticleDetailView,self).get_context_data(*args,**kwargs)
'''context allows us to access these values on our page'''
stuff=get_object_or_404(post,id=self.kwargs['pk'])
total_likes= stuff.total_likes()
liked = False
if stuff.likes.filter(id=self.request.user.id).exists():
liked = True
context['cat_menu'] = cat_menu
context['total_likes']=total_likes
context['liked'] = liked
context['amount_of_user_likes']=amount_of_user_likes
return context
I am not sure how to query the Database in order to get the amount of posts that a user liked since the liked column is on the post table and not on the user table. However, since it is a many to many relationship then we can access the user somehow but I am unsure.
You can count the number of times myuser liked a post with:
myuser.blog_posts.count()
so if you want to do that for the logged in user, we can work with:
context['amount_of_user_likes'] = self.request.user.blog_posts.count()
Related
I'm creating a dashboard to edit a tour app.
Per tour I have a child record in which I define steps. The 2 models look like this:
models.py
class Tour(models.Model):
tour_id = models.CharField(primary_key=True,unique=True, max_length=10)
country = models.ForeignKey(Countries, models.DO_NOTHING, db_column='country')
language = models.ForeignKey(Language, models.DO_NOTHING, db_column='language')
lastupddtm = models.DateTimeField(default=timezone.now)
productid = models.CharField(max_length=50)
title = models.CharField(max_length=50)
description = models.CharField(max_length=100)
descrlong = models.CharField(max_length=1000)
live = models.CharField(max_length=1)
image = models.ImageField(upload_to=upload_tour_image, storage=OverwriteStorage(), blank=True, null=True)
class Meta:
db_table = 'tour'
verbose_name_plural = "tour"
def get_language_flag(self):
return self.language.flag.url
def __str__(self):
return str(self.tour_id) + ' - ' + str(self.title) + ' - ' + str(self.description)
class Toursteps(models.Model):
# tour_id = models.OneToOneField(Tour, models.DO_NOTHING, db_column='tour_id')
tour = models.ForeignKey(Tour, related_name='toursteps', on_delete=models.CASCADE)
step = models.IntegerField(unique=True)
title = models.CharField(max_length=50)
description = models.CharField(max_length=100)
descrlong = models.CharField(max_length=1000)
audiotext = models.TextField()
latitude = models.FloatField()
longitude = models.FloatField()
radius = models.FloatField()
image = models.ImageField(upload_to=upload_tour_step_image, blank=True, null=True)
class Meta:
db_table = 'tourSteps'
verbose_name_plural = "tourSteps"
def __str__(self):
return str(self.tour) + "|" + str(self.step)
After I created a Tour, I go to a detail page. From there I can click a link to add a step for this tour.
This is where the problem is. I pass the tour_id as a variable into the url, but I can't find a way to pick it up in the CreateView of the step.
urls.py
urlpatterns = [
path('tour/<str:pk>/detail', views.TourDetailView.as_view(), name='tour_detail'),
path('tour/<str:pk>/edit', views.UpdateTourView.as_view(), name='tour_edit'),
path('tour/<str:pk>/remove', views.DeleteTourView.as_view(), name='tour_remove'),
path('tour/<str:tour_id>/step/new', views.CreateTourStepView.as_view(), name='tour_step_new')
]
Tour detail view
<p><span class="glyphicon glyphicon-plus"></span></p>
views.py
class CreateTourStepView(LoginRequiredMixin,CreateView):
login_url = '/login/'
redirect_field_name = 'tour_admin/tour_list.html'
success_url = '/'
form_class = TourStepForm
model = Toursteps
def get_context_data(self, **kwargs):
context = super(CreateTourStepView, self).get_context_data(**kwargs)
print(context['tour_id'])
return context
forms.py
class TourStepForm(forms.ModelForm):
class Meta():
model = Toursteps
#fields = '__all__'
exclude = ('tour',)
def form_valid(self, form):
if form.is_valid():
form.instance.tour_id = self.request.GET("tour_id")
form.instance.save()
return HttpResponseRedirect(self.get_success_url())
def get_success_url(self):
return reverse('tour_detail', kwargs={'pk':form.instance.tour_id})
First, your form_valid() and get_success_url() methods belong in your view, not in your form.
Second, the tour_id is passed to the view's kwargs, it's not a query parameter, hence not in self.request.GET. You can find it in self.kwargs.
Third, you need to actually fetch the Tour from your database, not just assign the tour_id. I could post to any tour_id if I wanted and there's no guarantee the tour_id belongs to an actual Tour object. Return a 404 if the tour doesn't exist. And if it exists, assign it to the tour step.
Finally, you should not assign to and save form.instance. You should get the instance using step = form.save(commit=False), then assign to step and save step.
I'm incrementing two different fields in User models which are the number of likes given to user's post and number of likes received by the user's post. I did this through adding two methods in class model. It is working when I'm liking other posts but however, if I liked my own post it is not working. Anyone know how to solve this problem?
Code snippet for user models
class User(models.Model):
username = models.CharField(max_length=100)
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
email = models.EmailField(null=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
datetime_joined = models.DateTimeField(auto_now_add=True)
num_likes_received = models.IntegerField(default=0)
num_dislikes_received = models.IntegerField(default=0)
num_likes_given = models.IntegerField(default=0)
num_dislikes_given = models.IntegerField(default=0)
total_votes = models.IntegerField(default=0)
prediction = models.BooleanField(default=True)
def add_total_votes(self, vote):
self.total_votes += vote
self.save()
def inc_num_likes_received(self):
self.num_likes_received += 1
print("1 like received")
self.save()
def inc_num_likes_given(self):
self.num_likes_given += 1
print("1 like given")
self.save()
Code snippet for Post Model
class Post(models.Model):
post = models.TextField()
num_likes = models.IntegerField(default=0)
num_dislikes = models.IntegerField(default=0)
username = models.ForeignKey(User, on_delete=models.CASCADE)
datetime_comments = models.DateTimeField(auto_now_add=True)
def add_num_likes(self):
self.num_likes+=1
self.save()
def __str__(self):
return str(self.id)
Function for submitting like to certain post and at the same time this is where I executed the created two method from the models. (inc_num_likes_received and inc_num_likes_given)
def submit_like(request):
User_PK = User.objects.get(username=request.user)
User_Give_Like = get_object_or_404(User, pk=User_PK.id)
pk = request.POST.get('Status', None)
post = get_object_or_404(Post, pk=pk)
post.add_num_likes()
User_PK_Receive = User.objects.get(id=post.username.id)
User_Receive_Like = get_object_or_404(User, pk=User_PK_Receive.id)
LikeObject = Likes(username = User_Give_Like, post = post, liked=True, disliked=False)
LikeObject.save()
User_Give_Like.inc_num_likes_given()
User_Receive_Like.inc_num_likes_received()
return HttpResponse(200)
To become more specific these two lines of code below are the methods. The problem here is that the first line of code are not actually working but the last line are the only working. Whenever I rearranged these two lines of code the only executed was the last line of code.
....
User_Give_Like.inc_num_likes_given()
User_Receive_Like.inc_num_likes_received()
Example:
In this case, User_Receive_Like.inc_num_likes_given() are working but User_Receive_Like.inc_num_likes_received() are not working and vice-versa.
....
User_Receive_Like.inc_num_likes_received()
User_Give_Like.inc_num_likes_given()
The expected output is both fields num_likes_given and num_likes_received must incremented by 1.
Appologies for the beginner question and/or stupidity - I'm learning as I go.... I'm trying to pass a user entered url of a PubMed article to access the metadata for that article. I'm using the following code, but I cannot access anything form the save method in he 'Entry' model. For example in my html form I can display {{entry.date_added }} in a form but not {{ entry.title}}. I suspect it's a simple answer but not obvious to me. Thanks for any help.
models.py
from django.db import models
from django.contrib.auth.models import User
import pubmed_lookup
from django.utils.html import strip_tags
class Topic(models.Model):
"""Broad topic to house articles"""
text = models.CharField(max_length=200)
date_added = models.DateTimeField(auto_now_add=True)
owner = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
"""Return a string representation of the model"""
return self.text
class Entry(models.Model):
"""Enter and define article from topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
pub_med_url = models.URLField(unique=True)
date_added = models.DateTimeField(auto_now_add=True)
def save(self, *args, **kwargs):
query = self.pub_med_url
email = "david.hallsworth#hotmail.com"
lookup = pubmed_lookup.PubMedLookup(query, email)
publication = pubmed_lookup.Publication(lookup)
self.title = strip_tags(publication.title)
self.authors = publication.authors
self.first_author = publication.first_author
self.last_author = publication.last_author
self.journal = publication.journal
self.year = publication.year
self.month = publication.month
self.day = publication.day
self.url = publication.url
self.citation = publication.cite()
self.mini_citation = publication.cite_mini()
self.abstract = strip_tags(publication.abstract)
super().save(*args, **kwargs)
class Meta:
verbose_name_plural = 'articles'
def __str__(self):
return "{} - {} - {} - {} [{}]".format(self.year,
self.first_author, self.journal, self.title, str(self.pmid), )
In Django ORM, you have to manually specify all fields that need to be saved. Simply saving it as self.foo = bar in the save method is stored in the Entry instance object (=in memory), but not in the database. That is, there is no persistence. Specify all the fields that need to be saved in the model and run python manage.py makemigrations,python manage.py migrate. Assigning fields to the model is actually the task of designing the relational database.
class Entry(models.Model):
"""Enter and define article from topic"""
topic = models.ForeignKey(Topic, on_delete=models.CASCADE)
pub_med_url = models.URLField(unique=True)
date_added = models.DateTimeField(auto_now_add=True)
title = models.CharField(...)
authors = models.CharField(...)
...
def assign_some_data_from_pubmed(self):
email = "david.hallsworth#hotmail.com"
lookup = pubmed_lookup.PubMedLookup(query, email)
publication = pubmed_lookup.Publication(lookup)
self.title = strip_tags(publication.title)
self.authors = publication.authors
self.first_author = publication.first_author
self.last_author = publication.last_author
self.journal = publication.journal
self.year = publication.year
self.month = publication.month
self.day = publication.day
self.url = publication.url
self.citation = publication.cite()
self.mini_citation = publication.cite_mini()
self.abstract = strip_tags(publication.abstract)
Usage:
entry = Entry(...)
entry.assign_some_data_from_pubmed()
entry.save()
I have models.py like below:
class Profile(models.Model):
user = models.OneToOneField(User)
def __unicode__(self):
return "%s" % self.user
class Student(models.Model):
user = models.ForeignKey(Profile)
phone_num = models.CharField(max_length=15)
def __unicode__(self):
return "%s" % (self.user)
class Teacher(models.Model):
user = models.ForeignKey(Profile)
phone_num = models.CharField(max_length=15)
def __unicode__(self):
return "%s" % (self.user)
class Complaint(models.Model):
user = models.ForeignKey(Student)
complaint = models.TextField()
teacher = models.ForeignKey(Teacher, null=True)
def __unicode__(self):
return "%s : %s" % (self.complaint)
How can I display teacher's name which is eventually stored in class Profile
What I get is a column teacher_id in _complaint table when I do
student_obj = Student.objects.get(name=user_profile_instance)
and then
compaint = student_obj.complaint_set.values()
in complaint.html
{{complaint.teacher_id}}
what I want is teacher name instead of id
This should work -
{{ complaint.teacher.user.user.first_name }}
First of all Please Update your style of coding to make your App Optimised
Use
student_obj = Student.objects.select_related().get(name=user_profile_instance)
The Above one will Cache Datas . After that each time when u call Datas from fields it Wont HIT your database :) , Hence Your App will Fly
instead of
student_obj = Student.objects.get(name=user_profile_instance)
and i'm Agreeing with #Bibhas Answer
{{ complaint.teacher.user.user.first_name }}
Teacher's Profile is Inheriting Django's Auth Model User
That wise
user.user.first_name
I've inherited an app created with Django. There is a problem with it: in admin interface, the page lists not all entities (videos), but some (16 of 25). I have no idea, what is this.
Then I run python manage.py shell, and there Video.objects.all(), there are all 25 objects (counted them using len and by iterating them with for loop).
I have found no managers or whatever (maybe I just don't know where to look for them).
On the bottom of admin page: 25 videos, while there are only 16 rows.
Then I add to VideoModelAdmin class list_per_page = 10, paginator show three pages, but only first two of them has any Videos, third shows no rows.
Here are some code.
# admin.py
class VideoModelAdmin(admin.ModelAdmin):
list_display = ['title', 'short_desc', 'author', 'redactor_choise', 'views_num', 'rating', 'is_published']
list_filter = ['is_published', 'redactor_choise']
list_per_page = 10
actions = ['make_published', 'update_comments_count']
exclude = ('file_lq', 'file_hq', )#'thumb',)
def make_published(self, request, queryset):
queryset.update(is_published=1)
make_published.short_description = "Опубликовать выделенные"
def save_model(self, request, obj, form, change):
instance = form.save(commit=False)
instance.author = request.user
instance.save()
return instance
def update_comments_count(self, request, queryset):
for video in queryset:
video.update_comments_count()
update_comments_count.short_description = "Пересчитать комментарии!"
# later there
admin.site.register(Video, VideoModelAdmin)
# models.py
class Video(models.Model):
def make_upload_path(instance, filename):
return 'video/thumbs/' + generate_random_name(filename)
category = models.ManyToManyField(Category, limit_choices_to = {'is_published': 1})
title = models.CharField(max_length=128)
short_desc = models.CharField(max_length=255)
long_desc = tinymce_models.HTMLField(blank=True)
file_lq = models.FileField(upload_to='video/lq/', null=True, blank=True)
file_hq = models.FileField(upload_to='video/hq/', null=True, blank=True)
thumb = models.FileField(upload_to=make_upload_path, blank=True, null=True)
#thumb = fields.ThumbnailField(upload_to=make_upload_path, sizes=settings.VIDEO_THUMB_SIZE, blank=True, null=True)
author = models.ForeignKey(User, editable=False)
redactor_choise = models.BooleanField(default=False)
views_num = models.SmallIntegerField(default=0, editable=False)
comments_num = models.SmallIntegerField(default=0, editable=False)
rating = models.SmallIntegerField(default=0, editable=False)
voters = fields.PickledObjectField(blank=True, editable=False)
created = models.DateTimeField(auto_now_add=True)
is_published = models.BooleanField(default=False)
def get_absolute_url(self):
return "/video/%d" % self.id
def views_num_plus(self):
cursor = connection.cursor()
cursor.execute('update soctv_video set views_num=views_num+1 where id=%d', [self.id])
cursor.close()
def update_comments_count(self):
from threadedcomments.models import ThreadedComment as Comment
self.comments_num = Comment.objects.filter(video=self).count()
self.save()
#cursor = connection.cursor()
#cursor.execute('update soctv_video set comments_num = (select count(*) from soctv_comment where video_id = %s) where id = %s', [self.id, self.id])
#cursor.close()
def update_categories_counts(self):
cursor = connection.cursor()
cursor.execute('update soctv_category set num_items = (select count(*) from soctv_video_category where category_id = soctv_category.id)')
cursor.close()
def is_user_voted(self, uid):
try:
if self.voters[uid]:
return self.voters[uid]
except Exception:
return False
def increment_view_count(self, token):
import md5
token = md5.new(token).hexdigest()
if VideoView.objects.filter(uniquetoken=token).count() == 0:
VideoView(uniquetoken = token, video = self).save()
def view_count(self):
return self.views_num + VideoView.objects.filter(video=self).count()
def __unicode__(self):
return unicode(self.title)
The problem can be that some FK in some of your videos points to something that does not exist.
I had the same problem and this was the reason.
Django will silently fail if the value is not there in the foreign key column.
Add both null and blank attribute to the column
null=True, blank=True
Make sure that you are logged in to the correct account aswell.
In my case, My account did not have permissions to modify <Model>