I am trying to ad a condition into an html model in Django (python) and it is not working:
This is my HTML:
<p class="card-text text-muted h6">{{ post.author }} </p>
{% if post.author == 'John_Woo' %}
<p class="card-text text-muted h6"> NOK </p>
{% else %}
<p class="card-text text-muted h6"> ok </p>
{% endif %}
Not sure what is wrong here...
Even though I have a John_Woo author, I only get ok message
This is my models.py:
class Post(models.Model):
title = models.CharField(max_length=200, unique=True)
slug = models.SlugField(max_length=200, unique=True)
author = models.ForeignKey(User, on_delete= models.CASCADE,related_name='blog_posts')
This is my views.py:
from django.views import generic
from .models import Post
class PostList(generic.ListView):
queryset = Post.objects.filter(status=1).order_by('-created_on')
template_name = 'index.html'
class PostDetail(generic.DetailView):
model = Post
template_name = 'post_detail.html'
Post.author returns class's representation like(str, unicode, repr) function. You have to override this functions which is depends on your django version. But you have one way to compare this. Like if Post.author.first_name == "John_Woo"
You want post.author.name (where .name is whatever field of an User object that will sometimes contain the string 'John_Woo' )
Related
my code
views
class FollowView(LoginRequiredMixin, View):
def post(self, request, *args, **kwargs):
follow_from = request.user
follow_to_username = request.POST.get('follow_to')
follow_to = get_object_or_404(User, username=follow_to_username)
try:
follow_obj = Follow.objects.get(follow_from=follow_from, follow_to=follow_to)
follow_obj.delete()
except Follow.DoesNotExist:
follow_obj = Follow.objects.create(follow_from=follow_from, follow_to=follow_to)
return redirect(request.META.get('HTTP_REFERER'))
model
class Follow(models.Model):
follow_from = models.ForeignKey(
User, related_name='following', on_delete=models.CASCADE)
follow_to = models.ForeignKey(
User, related_name='follower', on_delete=models.CASCADE)
created = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.follow_from} follows {self.follow_to}"
template of user profile
<div class="card-body">
<p> {{ object.user }} </p>
<p> {{ object.state_message }}</p>
<p> following </p>
{% for follow in object.user.following.all %}
<p> {{ follow.follow_to }}</p>
{% endfor%}
<br>
<p> followers </p>
{% for follow in object.user.follower.all %}
<p> {{ follow.follow_from }}</p>
{% endfor%}
</div>
when i try to get one user's followers and following users
{% for follow in object.user.following(or follower).all %}
like this
i have to use ".follow_to" or ".follow_from" once more
This way is a bit confusing to use.
What i want is get "one user's follower" and "one user's following" using just keyword 'followers', and 'following'.
Should i try different way of making follow model?
please give me advice or idea.
If you use a custom user model you can add a ManyToManyField with 'self' and your model Follow as the through model, while keeping symmetrical=False:
class User(AbstractUser):
following = models.ManyToManyField('self', through='Follow', symmetrical=False, related_name='followers')
...
Now you can directly access the related models by {% for follow in user.following.all %} etc.
I created model Post and Comment, now I want to display comments from Post but I have a problem. In tutorial there is a line of code in html {% for comment in post.comments.all %} but isn't working in my app. If I set {% for comment in comments %} it works but displays all comments from models (I want only comments from the post). How to fix that? Below I pasted my code.
models.py
from django.db import models
class Post(models.Model):
title = models.CharField(max_length=64, blank=False, null=False)
short_text = models.TextField(blank=False, null=False)
text = models.TextField(blank=False, null=False)
image = models.TextField(blank=False, null=False)
date = models.DateTimeField(auto_now_add=True, blank=True)
views = models.IntegerField(default=0)
class Comment(models.Model):
post = models.ForeignKey('main.Post', on_delete=models.CASCADE)
author = models.CharField(max_length=200)
text = models.TextField()
created_date = models.DateTimeField(auto_now_add=True, blank=True)
approved_comment = models.BooleanField(default=False)
def approve(self):
self.approved_comment = True
self.save()
def __str__(self):
return self.text
views.py
from django.shortcuts import get_object_or_404, render, redirect
from .models import Post, Comment
def index_pl(request):
posts = Post.objects.all()
return render(request, 'index_pl.html', {'posts': posts})
def single_article_pl(request, id):
posts = get_object_or_404(Post, pk=id)
posts.views = posts.views + 1
posts.save()
comments = Comment.objects.all()
return render(request, 'single_article_pl.html', {'posts': posts, 'comments': comments})
html
{% for comment in post.comments.all %}
<div class="comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
admin.py
from django.contrib import admin
from .models import Post, Comment
admin.site.register(Post)
admin.site.register(Comment)
In tutorial there is a line of code in html {% for comment in post.comments.all %} but isn't working in my app.
This is likely because they specified the related_name=… parameter [Django-doc] in the ForeignKey from Comment to Post, like:
# Option 1: set the related_name to 'comments'
class Comment(models.Model):
post = models.ForeignKey(
'main.Post',
related_name='comments',
on_delete=models.CASCADE
)
# …
The related_name=… specifies the name of the relation in reverse, so in this case accessing the Comments of a given Post object. By default this is model_name_set, so in this case comment_set.
You thus can either specify a related name; or you can acces the comment_set manager:
Option 2: use the default related_name
{% for comment in post.comment_set.all %}
<div class="comment">
<div class="date">{{ comment.created_date }}</div>
<strong>{{ comment.author }}</strong>
<p>{{ comment.text|linebreaks }}</p>
</div>
{% empty %}
<p>No comments here yet :(</p>
{% endfor %}
Well, I am creating a user profile where the user can see his all posts which he has been uploaded. But I don't understand one thing that how could I possibly grab the fields of Post model from Posts/models.py and show them on the template which I have created in another app (Profiles) templates.
The reason I am trying to access them on other app is that I want to show them in the userprofile.html template. Just like Facebook posts. And please tell me if you know that it is not possible with django?
posts/models.py :
class Post(models.Model):
username = models.ForeignKey(User, verbose_name=("user name"), on_delete=models.CASCADE)
description = models.CharField(('Description'),max_length=250)
title = models.CharField(('Content Title'), max_length=250)
create_date = models.DateTimeField(default = timezone.now)
image_data = models.ImageField(upload_to='User_Posts', height_field=None, width_field=None, max_length=None)
def __str__(self):
return self.title
profiles/views.py
from posts.model import Post
from django.views.generic import ListView
class UserPostListView(ListView):
model = Post
context_object_name = 'userpost_list'
template_name = 'profiles/userprofile.html'
def get_queryset(self):
user = get_object_or_404(User, username = self.kwargs.get('username'))
return Post.object.filter(username = user).order_by('-create_date')
profiles/templates/profiles/userprofile.html
<div class="jumbotron">
{% for post in userpost_list %}
<div class="post">
<h1>{{ posts.post.title }} <img src="" alt="not found" height="60" width="60" style="float:right ;border-radius: 20px;" ></h1>
<div class="date">
<p>
<!-- Published on: {{ object.author.post.create_date|date:"D M Y" }} -->
</p>
</div>
</div>
{% endfor %}
</div>
</div>
You can access any app from any other app. You just need to do the necessary model imports which you are doing. Looks like you just need to tweak your line of code in the template from:
<h1><a href="">{{ posts.post.title }}...
to:
<h1><a href="">{{ post.title }}...
and when you decide to use it.
<!-- Published on: {{ object.author.post.create_date|date:"D M Y" }} -->
to:
<!-- Published on: {{ post.create_date|date:"D M Y" }} -->
The reason is that your queryset is returning a dataset of the Post model. So you are already in it.
It just done by importing model from the app you want to use model to other app. And that it. This is python OOP(object oriented programming) concept.
Im a newbie working on a news site (or at least trying to, a lot of "problems" in the last few days lol ) trying to learn Django the best I can.
This is what I want to do :
I have an Article Model, it used to have 6 image fields that I used to send to the template and render the images, each image field had its own name and all was well in the world.
Then I got tasked with puting the Article images in a separate Image model.
So I did this :
class Article(models.Model):
title = models.CharField('title', max_length=200, blank=True)
slug = AutoSlugField(populate_from='title', default="",
always_update=True, unique=True)
author = models.CharField('Author', max_length=200, default="")
description = models.TextField('Description', default="")
is_published = models.BooleanField(default=False)
article_text = models.TextField('Article text', default="")
pub_date = models.DateTimeField(default=datetime.now, blank=True)
article_category = models.ForeignKey(Category, on_delete="models.CASCADE", default="")
def __str__(self):
return self.title
class ArticleImages(models.Model):
article = models.ForeignKey(Article, on_delete="models.CASCADE", related_name="image")
image = models.ImageField("image")
name = models.CharField(max_length=50, blank=True)
But so far I wasnt able to access my images in my template using
{{ article.image.url }} or {{ article.image.image.url }}
or any other combination. Why is that ?
Did I set up my models correctly ? One person suggested that I should change the model field from ForeignKey to OneToOneField, but I didn't get much feedback on why and how ?
So, how would I make a for loop that loops through the Articles model and then gets the related images for each Article ? I essentially want it to behave like I still have the 6 different fields like I did before. ( I have to do it this way, it's a part of the task ).
here are my views and my "index" template that I used to loop through the Articles and display 6 latest news on my home page. (please ignore the tags,I am aware they aren't working like this..the template is just so you can understand what I am talking about )
my views.py:
class IndexView(generic.ListView):
template_name = 'news/index.html'
context_object_name = 'latest_article_list'
def get_queryset(self):
return Article.objects.all()
class CategoryView(generic.ListView):
template_name = 'news/categories.html'
context_object_name = 'category'
def get_queryset(self):
return Article.objects.filter(article_category__category_title="Politics")
class ArticlesView(generic.ListView):
context_object_name = 'latest_article_list'
template_name = 'news/articles.html'
paginate_by = 5
def get_context_data(self, **kwargs):
context = super(ArticlesView, self).get_context_data(**kwargs)
context['categories'] = Category.objects.all()
return context
def get_queryset(self):
category_pk = self.request.GET.get('pk', None)
if category_pk:
return Article.objects.filter(article_category__pk=category_pk).order_by("-pub_date")
return Article.objects.order_by("-pub_date")
def article(request, article_id):
article = get_object_or_404(Article, pk=article_id)
context = {'article': article,
'article_category': article.article_category.category_title}
return render(request, 'news/article.html', context)
template that I used with my old model :
{% for article in latest_article_list %}
<img class="single-article-img" src="{{ article.image.name.url }}" alt="">
<div class="container row">
<!-- Start Left Blog -->
<div class="article mt-10 col-md-4 col-sm-4 col-xs-12">
<div class="single-blog" style="margin:10px auto;">
<div class="single-blog-img">
<a href="{% url 'news:article' article.id %}#article-title">
<img class="for-imgs" src="{{ article.image.url }}" alt="">
</a>
</div>
<div class="blog-meta">
<span class="date-type">
<i class="fa fa-calendar"></i>{{ article.pub_date }}
</span>
</div>
<div class="xx blog-text">
<h4>
{{ article.title }}
</h4>
<p>
{{ article.description|truncatewords:30 }}
</p>
</div>
<span>
Read more
</span>
</div>
</div>
{% endfor %}
Thank you !
You need to loop over the images as you have many images against a single article object. You can have something like below to show images in your template:
{% if latest_article_list.articleimages %}
{% for articleimage in latest_article_list.articleimages.all %}
<img src="{{ articleimage.image.url }}" class="d-block w-100" alt="...">
{% endfor %}
{% endif %}
I am trying to setup a relation with another model using FK in django but I can't call FK related model fields in django templates. In template when I call "provider.name" it shows me "None" as result. I do have 5 different suppliers listed and can see from admin. I have providers and I got products like below:
class Product(models.Model):
title = models.CharField(max_length=500)
description = models.TextField(blank=True, null=True)
price = models.DecimalField(max_digits=20, decimal_places=2)
sku = models.CharField(null=True, max_length=100)
url = models.URLField(blank=True)
slug = models.SlugField(unique=True)
providers = models.ManyToManyField('Provider', blank=True)
def __unicode__(self):
return self.title
class Provider(models.Model):
name = models.CharField(max_length=200)
description = models.TextField(null=True, blank=True)
logo = models.ImageField(upload_to='products/')
shipping_method = models.CharField(max_length=250)
shipping_time = models.CharField(max_length=250)
return_policy = models.CharField(max_length=200)
free_delivery = models.CharField(max_length=200)
customer_service_number = models.CharField(max_length=200)
shipping_charges = models.CharField(max_length=200)
def __unicode__(self):
return self.name
In template the way I am calling it is:
{% with provider=object.providers %}
{{ provider.name }}
{% endwith %}
As result it shows "None". I am trying to call provider in a different template. In it's own List/Detail generic views it works just fine. I am trying to call it in different app templates. Please advise.
Update................
My search.html for whoosh search engine includes
{% for result in page.object_list %}
<div class="col-lg-1-5 col-md-3 col-sm-4 col-xs-12">
<div class="pbox">
<div class="photo">
<img src="{{ result.object.get_image_url }}" alt="product">
</div>
<div class="info">
<div class="url">
name
{% for item in result.object.providers.all %}
{{ result.provider.name }}
{% endfor %}
</div>
<div class="description">
{{ result.object.description|truncatewords:7 }}
</div>
<div class="price">
{{ result.object.price|intcomma }}
</div>
</div>
</div>
</div>
As I am not using any ModelManager or just using default Managers pre-defined for models. I've added a line of code under Product App model like this:
def get_provider(self):
item = self.providers.all()
return item
I case of calling provider you call related manager so it return None because manager have no method like this.
If you want to retrieve objects from managers, you should call self.providers.all()
In your case, template tags should looks like this:
{% for item in object.providers.all %}
{{ provider.name }}
{% endfor %}