How to pin posts in django? - python

So i want to know how to pin posts in django. When i click on check, and click create post, it should pin the post to the top. And newer posts will just appear bottom, without interfering with the pinned post. The pin system should also be able to pin multiple posts. So if i pin another post, both posts should stay at the top. The other not pinned posts should just appear below.
models.py
class AskSection(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
user = models.ForeignKey(User, on_delete=models.CASCADE)
is_pin = models.BooleanField()
likes = models.ManyToManyField(User, related_name='likes', blank=True)
is_marked = models.BooleanField(default=False)
date_posted = models.DateTimeField(default=timezone.now)
class Meta:
ordering = ['-date_posted']
verbose_name_plural = "Ask Section"
def __str__(self):
return str(self.title)
forms.py
class AskSectionCreateForm(forms.ModelForm):
is_pin = forms.BooleanField(label="pin ask post", required=False)
class Meta:
model = AskSection
fields = ('title', 'description', 'is_pin')
widgets = {
'title': forms.TextInput(attrs={
'class': 'form-control'
}),
'description': forms.Textarea(attrs={
'class': 'form-control'
}),
}
views.py
#login_required
def create_ask_post(request):
if request.method == "POST":
form = AskSectionCreateForm(request.POST or None)
if form.is_valid():
title = form.cleaned_data.get('title')
description = form.cleaned_data.get('description')
is_pin = form.cleaned_data.get('is_pin')
obj = form.save(commit=False)
obj.title = title
obj.description = description
obj.is_pin = is_pin
obj.user = request.user
obj.save()
messages.success(request, f'You have posted {title} successfully')
return redirect('/details_ask/' + str(title) + '/')
else:
form = AskSectionCreateForm()
else:
form = AskSectionCreateForm()
context = {
'form': form
}
return render(request, "editor/create_ask_post.html", context)
html file
{% for question in all_questions %}
<!-- random HTML not important code --> <!-- code is related to just the styling of posts and just model fields -->
{% endfor %}
so please let me know how to do this. The HTML file isn't really important. It just contains the card, and model fields.
Thanks!

So you don't really need another field in your model you could just work with your DateTimeField but as commented before I would add a rank = models.Integerfield(default=0) to the AskSection model. (Don't forget to migrate)
you have a views.py file with a function where you set the context for your html (not the one you showed in your answer but the other one where you define all_questions). here you can set an order for all_questions like so all_questions = AskSection.objects.filter(user=request.user).order_by("rank", "-is_pin"). Your code might look a little different now I dont know if you filter by user I just assumed that...
When a User adds a new question you increase your the rank on the new question so you always have a clean order. Whenever a user "Pins" a question you take highest rank and add a number + set the Boolean to True.
An alternative way would be working with the Datefield date_posted like so
all_questions = AskSection.objects.filter(user=request.user).order_by("date_posted", "-is_pin"). in that case the date would act as a "rank". saves you a migration but its not as flexible as a Integerfield.

Related

Liked time of request.user is not showing

I just started learning Django. I am building a simple Blog App and I am trying to get the user liked time of post of request.user.
I made a Post model and a Like model. And when user like show the like time of user.
But it is not showing the liked time.
models.py
class Post(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=30, default='')
class Likepost(models.Model):
by_user = models.ForeignKey(User, on_delete=models.CASCADE)
post_of = models.ForeignKey(Post, on_delete=models.CASCADE)
date_liked = models.DateTimeField(auto_now_add=True)
views.py
def blog_post_detail(request, post_id):
obj = get_object_or_404(Post, pk=post_id)
accessLikes = obj.likepost_set.all()
for All in accessLikes:
if request.user == All.by_user
All.request.user.date_liked
context = {'obj':obj}
return render(request, 'blog_post_detail.html', context}
What i am trying to do :-
I am trying to access liked time of request.user
It is keep showing :-
Likepost' object has no attribute 'request'
I will really appreciate your help. Thank You
You can obtain the Likepost object of a user by filtering the queryset, and try to retrieve the corresponding like:
def blog_post_detail(request, post_id):
obj = get_object_or_404(Post, pk=post_id)
likepost = obj.likepost_set.filter(by_user=request.user).first()
context = {'obj':obj, 'likepost': likepost}
return render(request, 'blog_post_detail.html', context}
Next you can render this in the template with:
{% if likepost %}
Liked by you at {{ likepost.date_liked }}
{% endif %}
Normally one can prevent multiple Likeposts for the same object and the same user with a UniqueConstraint [Django-doc]:
class Likepost(models.Model):
by_user = models.ForeignKey(User, on_delete=models.CASCADE)
post_of = models.ForeignKey(Post, on_delete=models.CASCADE)
date_liked = models.DateTimeField(auto_now_add=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=['by_user', 'post_of'],
name='like_once_per_post'
)
]
If you plan to store both like and unlike events, you get the most recent Likemodel with:
def blog_post_detail(request, post_id):
obj = get_object_or_404(Post, pk=post_id)
likepost = obj.likepost_set.filter(by_user=request.user).order_by('-date_liked').first()
# …

how to show my post only to my friends in django

I want to show my post only to my friends, How can I filter my post only to my friends? I have tried to filter in html code but as my friends get more, it repeats my post more (I mean repeat one post few times )
My models.py
class PostUser(models.Model):
posttype = models.CharField(max_length=3000, default='postuser')
content = models.TextField(null = True, blank= True)
media_image = models.FileField(null = True, blank= True)
media_video = models.FileField(null = True, blank= True)
per_to = models.CharField(max_length=300, null=True, blank=True, default='everyone')
status = models.CharField(max_length=3000, default='active')
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
datetime = models.DateTimeField(auto_now_add=True)
like = models.IntegerField(null=True, blank=True)
comment = models.IntegerField(null=True, blank=True)
share = models.IntegerField(null=True, blank=True)
user_pk = models.IntegerField()
class Friends(models.Model):
# Sender
friend_one = models.IntegerField()
# Reciver
friend_two = models.IntegerField()
per_to = models.CharField(max_length=300, null=True, blank=True, default='everyone')
status = models.CharField(max_length=3000, default='active')
datetime = models.DateTimeField(auto_now_add=True)
date = models.DateField(auto_now_add=True)
time = models.TimeField(auto_now_add=True)
and this is my views.py
allmyfriends = Friends.objects.filter(Q(friend_one = request.user.pk) | Q(friend_two = request.user.pk))
You can do it like :-
models.py
Choices = (
(True,'Friends can see Post'),
(False,'Friends cannot see Post'),
)
class Friends(models.Model):
...................
only_friends = models.BooleanField(max_length=30,choices=Choices,default=True)
Accessing Friends model objects in views Because our BooleanField is in Friends model so we have to access Friends model first to access only_friends BooleanField
def some_view(request,user_id):
allmyfriends = get_object_or_404(Friends,user_user_id)
p = request.user
you = p.user
friends = p.friends.all()
context = {'allmyfriends':allmyfriends,'friends':friends}
return render(request, 'mains:your_template.html', context}
urls.py
path('some_view/<int:user_id>/',views.some_view,name='some_view'),
your_template.html
Now do work carefully here.
In showing post, I assume that you're using loop for showing all of users Post. like :-
{% for posts in post %}
{% if posts.user.only_friends == True and posts.user in request.user.friends.all %}
{{ post.posttype }}
{% endif %}
{% endfor %}
Note :- This FrontEnd will only work after you set your PostUser ForeignKey relationship with User like :-
from django.contrib.auth.models import User
class PostUser(models.Model):
..................
user = models.ForeignKey(User,on_delete=models.CASCADE,default='',unique=True)
Also Set your Friends model ForeignKey RelationShip with User
class Friends(models.Model):
.............
user = models.ForeignKey(User,on_delete=models.CASCADE,default='',unique=True)
Explanation :-
In models.py :- I add a BooleanField with Choices.
In views.py :- I access Friends model to access its objects with user_id. ( Check carefully in template urls while using user_id )
In template :- I use a for loop to show all the Posts. AND In for loop i started if statement that If the user who posted a post is in request.user's friends and have BooleanField True then Post will show and if request.user isnot in posted user then the post will not be shown.
#Ramin Zamani- Your friend model is messed up. Have a look at this.
Rename your model Friends to UserFriend. It's a model that shows the relation between 2 entities - The user and his/her friends/followers. The model name shouldn't be plural.
from django.conf import settings
class UserFriend(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL)
friend = models.ForeignKey(settings.AUTH_USER_MODEL)
................
Also, I could have used a many-to-many relation but I prefer the foreign key relation. It's up to your preference.
Your post model needs to be fixed
class Post(models.Model):
created_by= models.ForeignKey(settings.AUTH_USER_MODEL)
...............
And if you want only specific users to let's say view a post then you can do the following.
in your views.py
post = Post.objects.get(slug=self.kwargs.get('name'))
#to check if the user trying to access the post is a friend of the postcreator user.
friend = UserFriend.objects.get(user=post.created_by,friend=self.request.user)
if friend:
render()
else:
return HttpResponseForbidden()

Show last uploaded file details on redirected page - Django

folks. In my application user uploads his/her document on upload_document page, submits the form and he/she should see details (for example, document name, document author and etc.) on redirected result page. Now I don't know where should I get document itself from POST request. Or I'm entirely in wrong way. Here are my codes.
views.py:
#login_required(login_url='sign_in')
def upload_document(request):
context = {}
form = UploadDocumentForm()
if request.method == 'POST':
form = UploadDocumentForm(request.POST or None, request.FILES or None)
if form.is_valid():
form.save()
return redirect('result')
context = {
'form':form
}
return render(request, 'upload_document.html', context)
#login_required(login_url='sign_in')
def result(request):
# Don't know what to do here.
return render(request, 'result.html', context)
models.py:
class OriginalDocument(models.Model):
document = models.FileField(upload_to='static/original_document', blank=False)
document_title = models.CharField(max_length=300)
student_name = models.CharField(max_length=100)
teacher_name = models.CharField(max_length=100)
document_type = models.CharField(max_length=100)
university = models.ForeignKey(University, on_delete=models.CASCADE, null=True, blank=True)
date_added = models.DateTimeField(auto_now_add = True)
checked_by = CurrentUserField()
def __str__(self):
return self.document_title
As a user, I'm using django's built-in user.
Finding solution with the help of #k33da_lets_debug become so easy. I've changed query to this:
last_uploaded = OriginalDocument.objects.latest('id')
And that's all.

Automatic field creation on form submission

I am writing a simple blog app and I'm currently in the position where I need to implement comments on a blog post. So, I have two models:
from django.db import models
from django.shortcuts import reverse
# Create your models here.
class Article(models.Model):
title = models.CharField(max_length=120)
author = models.CharField(max_length=50)
content = models.TextField()
date = models.DateField(auto_now=True)
def get_absolute_url(self):
return reverse('articles:article-detail', kwargs={'id': self.id})
class Comment(models.Model):
author = models.CharField(max_length=50)
content = models.TextField()
date = models.DateField(auto_now=True)
post_id = models.IntegerField()
and a ModelForm:
from django import forms
from .models import Article, Comment
class CommentModelForm(forms.ModelForm):
class Meta:
model = Comment
fields = [
'content',
'author',
]
...when I submit the form, I want my Comment's post_id field to be automatically generated and correspond to my Article's id, i.e. the comment should be located on the page where it was submitted.
Here is my views.py:
def article_detail_view(request, id):
obj = get_object_or_404(Article, id=id)
comments = Comment.objects.filter(post_id=id)
comment_form = CommentModelForm(request.POST or None)
if comment_form.is_valid():
comment_form.save()
comment_form = CommentModelForm()
context = {
'object': obj,
'comments': comments,
'comment_form': comment_form
}
return render(request, 'articles/article_detail.html', context)
Any ideas how can I do that?
I suggest to change the Comment model in order to replace post_id with a foreignkey field. It allows to keep a better link between comments and articles.
class Comment(models.Model):
author = models.CharField(max_length=50)
content = models.TextField()
date = models.DateField(auto_now=True)
post_id = models.ForeignKey(Article, on_delete=models.CASCADE) # cascade will delete the comments if the article is deleted.
Then you only have to change the comment_form validation :
if comment_form.is_valid():
comment = comment_form.save(commit=False)
comment.post_id = obj
comment.save()
comment_form = CommentModelForm()
save(commit=False) allows to create the Comment instance without saving it to database and allow us to specify the post_id with the article instance obj defined above. Then comes the final commit comment.save().
If you prefer to not change your model, you can follow the same logic and replace
comment.post_id = obj by comment.post_id = id.

Django: Populating ModelChoiceField

I have been searching up and down and I can't seem to find the right answer.
I have been playing around with django and with my test project and I can't figure out how to implement this, I am trying to display dropdown contents dynamically based on foreign key from my views
Here is my sample views:
def job_display(request):
job_list = Job_Posting.objects.filter(Publication_Status="A", Available_Slots__gt=0).order_by('-Urgency_Status', '-Date_Modified')
context = {'job_list': job_list}
return render(request, 'frontend/home.html', context)
def save_page(request, job_id):
jreq = get_object_or_404(Job_Posting, fkey=job_id)
form = application_form(request.POST)
if request.method == 'POST':
.....
else:
.....
return render(request, 'frontend/apply.html ... )
My urls:
urlpatterns = patterns('',
url(r'^$', views.job_display, name='job_display'),
url(r'^(?P<job_id>[0-9]+)/apply$', views.save_page, name='save_page'),
)
My froms:
class edbackgound(ModelForm):
COURSE = forms.ModelChoiceField(queryset=Educational_Requirement.objects.all())
my models:
class Course_Selection(models.Model):
Course = models.CharField(max_length=30, unique=True)
Abbreviation = models.CharField(max_length=100, unique=True)
class Job(models.Model):
Job_Position = models.CharField(max_length=30, null=True, unique=True)
class Job_Posting(models.Model):
fkey = models.OneToOneField(Job, verbose_name="Job Positions")
....
class Educational_Requirement(models.Model):
fkey = models.OneToOneField(Job_Posting, verbose_name="Job Positions")
Ed_req = models.OneToOneField(Course_Selection, verbose_name = 'Educational Requirement')
def __unicode__(self):
return self.Ed_req
My problem is displaying the choices in modelform, in my views I can get the currently selected job_list through save_page's jreq via jreq.fkey where I can just get it's Job_position then save my form. How can I populate my form's ModelChoiceField through my selected job_list.
If my post is not clear, please, feel free to comment what my post lacks
EDIT
I have found out that you can set your queryset via views like this:
form.fields['COURSE'].queryset = Educational_Requirement.objects.filter(fkey=jreq.fkey_id)
My problem with that is I am using an inlineformset_factory to generate my fields dynamically, and if I do this:
for form in myinlineform:
form.fields['COURSE'].queryset = Educational_Requirement.objects.filter(fkey=jreq.fkey_id)`
I am raising an error that says: [u'ManagementForm data is missing or has been tampered with']
Make sure you have included the management form for your inline formset in your template:
{{ my_formset.management_form }}
Read more on it here: https://docs.djangoproject.com/en/dev/topics/forms/formsets/#understanding-the-managementform

Categories

Resources