I have a model for forum. There I have a field for question, body, pub_date, image, creator, likes. From the admin, I can add the likes for a given user for a particular forum. But i'm confused all now, how to add likes for the request.user in the views?
models.py:
class Forum(models.Model):
question = models.CharField(max_length=150)
body = models.TextField()
pub_date = models.DateTimeField(default=datetime.now)
image = models.ImageField(upload_to=get_upload_file_name)
creator = models.ForeignKey(User, related_name="creator_set")
likes = models.ManyToManyField(User, through="Like")
def __unicode__(self):
return self.question
class Like(models.Model):
forum = models.ForeignKey(Forum)
liked = models.ForeignKey(User)
liked_date = models.DateTimeField(default=datetime.now)
def __unicode__(self):
return "%s likes %s" % (self.liked, self.forum)
I thought of doing like this:
>>>forum = Forum.objects.get(id=1)
>>>user = request.user
>>>user.like_set.add(forum)
But, it didn't help. Please, any help will be appreciated. Thank you.
First you need to create a URL that targets the view. The URL would pass a forum_id as a URL parameter.
from datetime import datetime
from django.shortcuts import get_object_or_404
#login_required
def update_likes(request, forum_id):
forum = get_object_or_404(Forum, id=forum_id)
like, _ = Like.objects.get_or_create(user=request.user, forum=forum,
defaults={'liked_date': datetime.now()})
#rest of the code here.
This is one way. You could also do it in the way you thought of doing it, but you will have to manually control the duplicates that could get generated. (you could specify a unique_together on the ('forum', 'liked') )
and to delete
#login_required
def delete_likes(request, forum_id):
forum = get_object_or_404(Forum, id=forum_id)
like = get_object_or_404(Like, user=request.user, forum=forum)
like.delete()
#rest of the code here.
Related
I would really appreciate some help on this because I'm completely stuck. I've started up a simple django app (trying to make an instagram clone). However, when I try to display the post objects (which I created in the django admin page) nothing is displayed in index.html, so I tried printing out the objects in the views.py and it's returning to me an empty query set. I don't quite understand what I'm doing wrong and why I can't access the objects? When I print out the username I am able to get that, but then nothing for both post and stream objects. Please I'm so stuck any advice would be appreciated.
views.py
from django.shortcuts import render
from django.contrib.auth.decorators import login_required
from django.template import loader
from django.http import HttpResponse
# Create your views here.
from post.models import post, stream
#login_required
# we are getting all of the string objects that are created for the user
def index(request):
user = request.user
print(user)
posts = stream.objects.filter(user=user)
print(posts)
group_ids = []
#then looping through and getting post id to a list
for posted in posts:
group_ids.append(posted.post_id)
print(group_ids)
#then filtering them so that you can display it in the index
#selecting a specific post by id
post_items = post.objects.filter(id__in=group_ids).all().order_by('-date')
template = loader.get_template('index.html')
context = {'post_items' : post_items}
return(HttpResponse(template.render(context, request)))
models.py
from django.db import models
from django.contrib.auth.models import User
import uuid
# Create your models here.
from django.db.models.signals import post_save
from django.utils.text import slugify
from django.urls import reverse
def user_directory_path(instance,filename):
# this file is going to be uploaded to the MEDIA_ROOT /user(id)/filename
return('user_{0}/{1}'.format(instance.user.id,filename))
class tag(models.Model):
title = models.CharField(max_length = 80, verbose_name = 'tag')
slug = models.SlugField(null = False, unique = True)
class Meta:
verbose_name = 'tag'
verbose_name_plural = 'tags'
# for when people click on the tags we can give them a url for that
# def get_absolute_url(self):
# return(reverse('tags', args = [self,slug]))
def __str__(self):
return(self.title)
def save(self,*args, **kwargs):
if not self.slug:
self.slug = slugify(self.title)
return(super().save(*args, **kwargs))
class post(models.Model):
# will create a long id for each post
id = models.UUIDField(primary_key=True, default = uuid.uuid4, editable = False)
image = models.ImageField(upload_to = user_directory_path, verbose_name= 'image', null = True)
caption = models.TextField(max_length = 2000, verbose_name = 'caption')
date = models.DateTimeField(auto_now_add = True)
tags = models.ManyToManyField(tag, related_name='tags')
user = models.ForeignKey(User, on_delete=models.CASCADE)
likes = models.IntegerField()
def get_absolute_url(self):
return reverse('postdetails', args=[str(self.id)])
# def __str__(self):
# return(self.user.username)
class follow(models.Model):
follower = models.ForeignKey(User, on_delete=models.CASCADE, related_name='follower')
following = models.ForeignKey(User, on_delete=models.CASCADE, related_name='following')
class stream(models.Model):
following = models.ForeignKey(User, on_delete=models.CASCADE, related_name='stream_following')
user = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(post, on_delete=models.CASCADE)
date = models.DateTimeField()
def add_post(sender, instance,*args, **kwargs):
# here we are filtering all the users that are following you
post = instance
user = post.user
followers = follow.objects.all().filter(following=user)
for follower in followers:
streams = stream(post=post, user=follower.follower, date = post.date, following = user)
streams.save()
post_save.connect(stream.add_post, sender=post)
output from print statements
user
<QuerySet []>
[]
I figured it out. It wasn't an issue with the code, but the way that I was creating posts in the admin panel. So because you can only view posts from users that you are following, the posts that I was creating weren't showing up. So I had to create another user, and follow that user, then have the new user post something. Then the post shows up in the page!
I have two models (Post and Display). Both have Datetime-auto fields. My problem is that i want to update all display objects related to a post, once a post is updated.
I have read here that you could override one models save method, but all the examples are About updating the model with the foreign key in it and then call the save method of the other model. In my case it's the other way arround. How can i do this ?
class Post(models.Model):
title = models.CharField(max_length=40)
content = models.TextField(max_length=300)
date_posted = models.DateTimeField(auto_now=True)
author = models.ForeignKey(User, on_delete=models.CASCADE)
rooms = models.ManyToManyField(Room, related_name='roomposts', through='Display')
def __str__(self):
return self.title
def get_absolute_url(self):
return "/post/{}/".format(self.pk)
class Display(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE)
room = models.ForeignKey(Room, on_delete=models.CASCADE)
isdisplayed = models.BooleanField(default=0)
date_posted = models.DateTimeField(auto_now=True)
def __str__(self):
return str(self.isdisplayed)
i want to update the date_posted of all related Display-objects once their related post is changed. I do not know if overriding the save-method works here.
in this case you should have a look at django's reverse foreign key documentation
https://docs.djangoproject.com/en/2.2/topics/db/queries/#following-relationships-backward
in your case you can override the save method on your Post model
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
#either: this excutes many sql statments
for display in self.display_set.all():
display.save()
#or faster: this excute only one sql statements,
#but note that this does not call Display.save
self.display_set.all().update(date_posted=self.date_posted)
The name display_set can be changed using the related_name option
in Display, you can change it:
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='displays')
Then, instead of using self.display_set in your code, you can use self.displays
Overriding save method works, but that's not were you should go, imo.
What you need is signals:
#receiver(post_save, sender=Post)
def update_displays_on_post_save(sender, instance, **kwargs):
if kwargs.get('created') is False: # This means you have updated the post
# do smth with instance.display_set
Usually it goes into signals.py.
Also you need to include this in you AppConfig
def ready(self):
from . import signals # noqa
I am trying to pass the PK of a blog post but I am having difficulty with it. If possible I would like to pass the PK without putting it in the URL.
I am trying to let my user edit their posts which are displayed in a list like below:
I need to make sure that when the user presses edit under a post, it allows them to edit that specific post. I believe where I am going wrong is in the get_object function when I try and get the PK. Any help with this would be much appreciated!
View
class EditPost(UpdateView):
model = ProjectPost
form_class = ProjectPostForm
template_name = 'howdidu/edit_post.html'
def get_object(self):
return ProjectPost.objects.get(pk=self.request.Get.get('pk'))
def get_success_url(self):
project_username = self.request.user.username
project_slug = self.object.project.slug
return reverse('user_project', kwargs={'username':project_username, 'slug': project_slug})
model
class ProjectPost(models.Model):
project = models.ForeignKey(UserProject)
title = models.CharField(max_length=100)
post_overview = models.CharField(max_length=1000)
date_created = models.DateTimeField(auto_now_add=True)
post_views = models.IntegerField(default=0)
post_likes = models.IntegerField(default=0)
url
url(r'^edit_post/$', login_required(views.EditPost.as_view()), name='edit_post'),
link used for edit post template
Edit post
I have a model for forum. Its just the basics, and I am trying the grasp the relationship and how to query with them. So, I have a forum with field for question, body, published date, image, and likes. I guess my model design is correct, if not please correct me. So, everything is works as I wanted. Just that, how do I get all the Users who liked the forum and count the likes? How can i query it? Please guide me through.
Thank you.
models.py:
class Forum(models.Model):
question = models.CharField(max_length=150)
body = models.TextField()
pub_date = models.DateTimeField(default=datetime.now)
image = models.ImageField(upload_to=get_upload_file_name)
creator = models.ForeignKey(User, related_name="creator_set")
likes = models.ManyToManyField(User, through="Like")
def __unicode__(self):
return self.question
class Like(models.Model):
forum = models.ForeignKey(Forum)
liked = models.ForeignKey(User)
liked_date = models.DateTimeField(default=datetime.now)
def __unicode__(self):
return "%s likes %s" % (self.liked, self.forum)
Isn't this suppose to work?:
Forum.objects.get(pk=1).likes.all()
Forum.objects.get(pk=1).likes.count()
I am new in django programming, and I have simple question.
I have model
class Dhcp(models.Model):
class Meta:
ordering = ('gateway',)
verbose_name = _(u'DHCP Configuration')
verbose_name_plural = _(u'DHCP Configurations')
gateway = models.IPAddressField(_(u'Gateway'), null=True)
dns_primary = models.IPAddressField(_(u'DNS Primary'), null=True)
dns_second = models.IPAddressField(_(u'DNS Second'), blank=True)
leases_time = models.IntegerField()
nat = models.IPAddressField(_(u'NAT'), blank=True)
max_time = models.IntegerField()
def __unicode__(self):
return self.gateway
and my question is :
And I want to list all my dhcp objects which are in database, and add more object. But I want do that on same template.
For example: If I have 3 objects in database, show that and show form for add more obj. When I add one more object from form, I want to show the added object.
Thanks!
Dusan Ristic
Have a look into Class Based Views, more specifically the ListView and CreateView. This question comes up quite often, so you should find the answer on here somewhere. Check this post out.
What you're looking for is something like this:
class DHCPView(forms.CreateView):
model = Dhcp
template_name = "list_and_create_dhcp.html"
def get_context_data(self, **kwargs):
kwargs["object_list"] = Dhcp.objects.all()
return super(DHCPView, self).get_context_data(**kwargs)