I wanted to pass two objects to templates, so I put theme in the context and try to send them but failed. I tried few times but it seems like user get objects but comment is always empty even though there are some data in db.
This is views.py
#login_required
def detail(request, article_no):
if not request.user.is_authenticated():
return redirect_to_login(next, 'blog/login.html')
else:
user = request.user
if 'username' in request.session:
username = request.session['username']
item = get_object_or_404(Article, pk=article_no)
item.hit = Article.objects.filter(pk=article_no).update(hit = item.hit+1)
#comment = Comment.objects.filter(pk=article_no).order_by('comment_no')
comment = Comment.objects.all()
context = {
'item': item,
'comment': comment,
}
return render(request, 'blog/detail.html', context)
this is models.py
from datetime import datetime
from django.db import models
from django.template.defaultfilters import default
class Article(models.Model):
no = models.AutoField(primary_key=True)
title = models.CharField(max_length=50)
content = models.CharField(max_length=300)
writer = models.CharField(max_length=50)
is_visible = models.BooleanField(default=True)
created_date = models.DateTimeField(editable=False, default=datetime.now())
hit = models.IntegerField(default=1)
class Comment(models.Model):
article_no = models.IntegerField(default=1)
comment_no = models.AutoField(primary_key=True)
comment_writer = models.CharField(max_length=50)
comment_body = models.CharField(max_length=300)
comment_date = models.DateTimeField(editable=False, default=datetime.now())
template
{{ item.title }}
{{ item.no }}
{{ item.writer }}
{{ item.hit }}
{{ item.created_date }}
{{ item.content }}
{% if comments %}
{% for comment in comments %}
{{ comment.comment_no }}
{{ comment.comment_writer }}
{{ comment.comment_body }}
{{ comment.comment_date }}
{% endfor %}
{% else %}
<div class="row">no comment.</div>
{% endif %}
The variable you're passing from the view with all the comments in is called comment, for some reason. But in the template you try to iterate over comments, which doesn't exist. You should use consistent naming; it would make more sense to use comments.
Your code
#login_required
def detail(request, article_no):
if not request.user.is_authenticated():
return redirect_to_login(next, 'blog/login.html')
else:
user = request.user
if 'username' in request.session:
username = request.session['username']
item = get_object_or_404(Article, pk=article_no)
item.hit = Article.objects.filter(pk=article_no).update(hit = item.hit+1)
#comment = Comment.objects.filter(pk=article_no).order_by('comment_no')
comment = Comment.objects.all()
context = {
'item': item,
'comment': comment,
}
return render(request, 'blog/detail.html', context)
Correction Code -->
#login_required
def detail(request, article_no):
if not request.user.is_authenticated():
return redirect_to_login(next, 'blog/login.html')
else:
user = request.user
if 'username' in request.session:
username = request.session['username']
item = get_object_or_404(Article, pk=article_no)
item.hit = Article.objects.filter(pk=article_no).update(hit = item.hit+1)
#comment = Comment.objects.filter(pk=article_no).order_by('comment_no')
comment = Comment.objects.all()
return render(request, 'blog/detail.html', {'item':item,
'comment':comment})
Details will be found here (pass multiple objects to RequestContext in django)
And in the template you use comments but in your code, there are no comments, rather then it is a comment.
Related
This is function for updating user's info.
views.py
def UpdateProfile(request):
context = {}
user = request.User
if not user.is_authenticated:
return redirect('login')
if request.POST:
form = PersonalInfo(request.POST, instance=user)
if form.is_valid():
obj = form.Save(commit=False)
user = user.id
obj.user = user
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
else:
form = PersonalInfo(instance=user)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
This is the model I have created for storing user info.
models.py:
class ApplicantInfo(models.Model):
infield = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
profile_pic = models.ImageField(upload_to='media/', blank= True, null= True)
father_name = models.CharField(max_length=30)
user = models.OneToOneField(User, on_delete=models.CASCADE)
This is the form class I have created.
forms.py:
from .models import Applicant, ApplicantInfo
from django import forms
class PersonalInfo(forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
This is the frontend template which I have created, this is working fine.
Template
{%block content%}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
<form method="POST">
{% csrf_token %}
{% for field in personal_form %}
<p>
{{field.label_tag}}
{{field}}
{% if field.help_text %}
<small style="color:gray">{{field.help_text}}</small>
{% endif %}
</p>
{% endfor %}
{% for field in personal_form %}
<p>
{% for error in field.errors %}
<p style="color:red">{{error}}</p>
{% endfor %}
</p>
{% endfor %}
<button type="submit">Submit</button>
</form>
</body>
</html>
{% endblock content %}
The app has been able to load the form without any trouble but it just not throwing data to the backend.
Updated function for UpdateProfile
views.py
def UpdateProfile(request, id=None):
context = {}
user_obj = request.user
if not user_obj.is_authenticated:
return redirect('login')
if request.method == "POST":
form = PersonalInfo(request.POST)
if form.is_valid():
obj = form.save()
user_id = Applicant.objects.filter(app_id = user_obj.app_id).first()
obj.user = user_id
obj.save()
return redirect('profile')
else:
#messages.error(request, ('Please correct the error below.'))
context['personal_form'] = form
elif request.method == 'GET':
form = PersonalInfo(instance=user_obj)
context['personal_form'] = form
return render(request, 'admission/signup.html', context)
Updated code for forms method, only add #def cleaned_data function
forms.py
class PersonalInfo( forms.ModelForm):
class Meta:
model = ProfileInfo
fields = [
'first_name',
'last_name',
'profile_pic',
#'date_birth',
'father_name',
'street_adr',
'city',
'zip_code',
]
def clean(self):
if self.is_valid():
first_name = self.cleaned_data['first_name']
last_name = self.cleaned_data['last_name']
father_name = self.cleaned_data['father_name']
street_adr = self.cleaned_data['street_adr']
city = self.cleaned_data['city']
zip_code = self.cleaned_data['zip_code']
And model does not need to be change, you have choice either to add and autofield(PrimaryKey) or use the default one
The problem was in view.py where i just removed instance attribute from the form object, then I called user_id from user model which is in this case #Applicant model, then assigned to the obj object and saved obj.
Thanks to all of you who has spent precious time in this problem.
Cheers!!!
I got a problem with my Django templates:
forms.py:
class SupportForm(forms.Form):
name = forms.CharField()
message = forms.CharField()
models.py:
class Message(models.Model):
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
name = models.CharField(max_length=100)
message = models.CharField(max_length=100)
def __str__(self):
return self.user.username
views.py:
class my_view(LoginRequiredMixin, View):
def get(self, request, *args, **kwargs):
try:
messages = Message.objects.filter(user=request.user)
context = {
'object': messages,
}
return render(self.request, 'my.html', context)
except:
return render(request, "my.html",{})
def post(self, request, *args, **kwargs):
form = SupportForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
message = form.cleaned_data['message']
message_model = Message(
user=request.user,
name = name,
message = message,
)
message_model.save()
return redirect('/my/')
my.html:
object:{{ objects }}<br>
name:{{objects.name.1}}<br>
message:{{objects.message.1}}<br>
{% for item in objects_list %}
{{ item.name }}
{% endfor %}
I want to post name and message in html and then show it under input. POST works fine. Then i want to display my name and message.
The problem is with viewing my objects in html: i can't see anything. What am i doing wrong?
in the context change
context = {
'objects': messages,
}
in the HTML
{% for object in objects %}
name:{{object.name}}<br>
message:{{object.message}}<br>
{% endfor %}
you have referred to it as object not objects
try it and let me know
EDIT: WORKING
views.py:
class my_view(ListView):
model = Message
template_name = "my.html"
def post(self, request, *args, **kwargs):
form = SupportForm(request.POST)
if form.is_valid():
name = form.cleaned_data['name']
message = form.cleaned_data['message']
message_model = Message(
user=request.user,
name = name,
message = message,
)
message_model.save()
return redirect('/my/')
my.html:
{% for item in object_list %}
{{ item.name }}
{{ item.message|safe }}
<br>
{% endfor %}
I'm building a post-comment model in one view, one page, something like facebook. I have two forms in my home.html and view.py: new post and new comment. In each post container, there is a new comment form.
I have a problem because I don't know how to relate comment to post - specifically how to pass post.id to my comment form.
Is it possible to pass my {{ post.id }} to my {{newCommentForm.field }}? That each comment has a default value of post's id?
My home.html:
{% for post in posts %}
<div class="container">
<a class="user" href="#">{{ post.author }}</a>, {{ post.date_posted }}
<img src="{{ post.author.profile.image.url }}" alt="{{ post.author }}"style="width:100%;">
<p>{{ post.content }}</p>
<form METHOD="POST" class="new_post">
{% csrf_token %}
{{ newCommentForm.content }}
{{ newCommentForm.post }}
<button type="submit" name="newCommentSubmit">Add</button>
</form>
</div>
{% endfor %}
models.py
class Post(models.Model):
content = models.TextField(max_length=1000)
date_posted = models.DateTimeField(default=timezone.now)
author = models.ForeignKey(User, on_delete=models.CASCADE)
def __str__(self):
return self.content
class Comment(models.Model):
post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='comments')
author = models.ForeignKey(User, on_delete=models.CASCADE)
content = models.TextField(max_length=500)
date = models.DateTimeField(default=timezone.now)
def add_coment(self):
self.date = timezone.now()
self.save()
def __str__(self):
return self.content
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.jpg', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username}'
views.py
#login_required()
def home(request):
newPostForm = newPost()
newCommentForm = newComment()
if request.method == 'POST':
if 'newPostSubmit' in request.POST:
newPostForm = newPost(request.POST, prefix='newpost')
if newPostForm.is_valid():
instance = newPostForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newCommentForm = newComment(prefix='newcomment')
elif 'newCommentSubmit' in request.POST:
newCommentForm = newComment(request.POST, prefix='newcomment')
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance.date_posted = timezone.now()
instance.save()
newPostForm = newPost(prefix='newpost')
else:
newPostForm = newPost(prefix='newpost')
newCommentForm = newComment(prefix='newcomment')
context = {
'newPostForm': newPostForm,
'newCommentForm': newCommentForm,
'posts': Post.objects.all().order_by('-date_posted'),
'comments': Comment.objects.all()
}
return render(request, 'blog/home.html', context)
def about(request):
return render(request, 'blog/about.html')
My model is working now, comments are added, but I need to choose my post (post.id) manually from the default dropdown field witch all posts.
Add your post to comment like this:
if newCommentForm.is_valid():
instance = newCommentForm.save(commit=False)
instance.author = request.user
instance,=.post = request.post
instance.date_posted = timezone.now()
instance.save()
And send post in request!
I have a comment form for my posts. It looks like this
view.py
def add_comment_to_post(request, pk):
post = get_object_or_404(Post, pk=pk)
if request.method == "POST":
form = CommentForm(request.POST)
if form.is_valid():
comment = form.save(commit=False)
comment.post = post
comment.author = request.user
#comment.author.photo = object.author.profile.image.url
comment.save()
return redirect('Post-detail', pk=post.pk)
else:
form = CommentForm()
return render(request, 'blog/add_comment_to_post.html', {'form': form})
models.py
class Comment(models.Model):
post = models.ForeignKey('blog.Post', on_delete=models.CASCADE, related_name='comments')
author = models.CharField(max_length=20)
text = models.TextField(max_length=200, verbose_name='内容')
created_date = models.DateTimeField(default=timezone.now)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
forms.py
class CommentForm(forms.ModelForm):
class Meta:
model = Comment
fields = ('text',)
widgets = { #size of textbox
'text': forms.Textarea(attrs={'rows':4}),
}
Where should I add pagination function to my comments to make it works?
I have a pagination for my posts, but posts are using a DetailView class and I dont know how to make it work for comment function
Basically you need to do that in Post-detail view. As DetailView does not provide pagination, so you need to provide them on your own. You can override the get context method. For example:
from django.core.paginator import Paginator
class PostDetailView(DetailView):
...
def get_context_data(self):
context = super(PostDetailView, self).get_context_data()
_list = Comment.objects.filter(post=self.kwargs.get('pk'))
paginator = Paginator(_list, 25) # Show 25 contacts per page
page = request.GET.get('page')
context['comments'] = paginator.get_page(page)
return context
And render comments in Template like this:
<div class="pagination">
<span class="step-links">
{% if comments.has_previous %}
« first
previous
{% endif %}
<span class="current">
Page {{ comments.number }} of {{ comments.paginator.num_pages }}.
</span>
{% if contacts.has_next %}
next
last »
{% endif %}
</span>
</div>
More information can be found in documentation as well.
This is how it can be done.
from rest_framework.pagination import PageNumberPagination
# Create a custom pagination class.
class CommentPagination(PageNumberPagination):
page_size = 1000
page_size_query_param = 'page_size'
max_page_size = 10000
# Define the Pagination class in PostDetailView.
class PostDetailView(DetailView):
pagination_class = CommentPagination
# This is how api can be called.
# something.com/comment/?page=4
this is what I'm trying to do: users can create community(or post) and I want in some where in my template, to display the community the user created.
So in models.py I have
class Category(models.Model):
name = models.CharField(max_length=128, unique=True)
description = models.TextField()
author = models.ForeignKey(settings.AUTH_USER_MODEL)
and in my views.py
#login_required
def add_category(request):
if not request.user.is_superuser and Category.objects.filter(author=request.user).exists():
return render(request,'main/category_already_exists.html')
if request.method == 'POST':
category = Category(author=request.user)
form = CategoryForm(request.POST, request.FILES, instance=category)
if form.is_valid():
form.save(commit=True)
return redirect('category', category_name_url=category.name)
else:
form = CategoryForm()
context = {
"form":form
}
return render(request, 'main/add_category.html',context)
and this is my simplified category view
def category(request, category_name_url):
category_name = decode_url(category_name_url)
category = Category.objects.get(name=category_name)
context = {
"category":category,
}
return render(request, "main/category.html", context)
so I tried this in my template with thinking it would work for sure
{% if user.is_authenticated == category.author %}
<h1>hello</h1>
{% else %}
<h1>nah</h1>
{% endif %}
but when it should print hello it prints nah, what's my fault here?
{% if user.is_authenticated == category.author %}
is not a valid check. user.is_authenticated returns a boolean (True/False), and category.author is a user object. You are checking for equality incorrectly.
Try this instead:
{% if user.is_authenticated and user == category.author %}
since category.author is a User instance