Conditions in IF Statements requires values to be specified explicitly - django

I have created a template that displays items from a loop, Within the loop there is a condition, but the condition does not work unless specified explicitly.
{% extends 'blog/base.html' %}
{% block content %}
<h3>{{ user.username }}</h3>
{% for project in projects %}
{% if user.username == 'testuser' %}
<h5>{{ project.title }}</h5>
<p>{{ project.description }}</p>
<p>{{ project.objectives }}</p>
<pre>{{ project.score }}</pre>
<pre>{{ project.student_id }}</pre>
{% endif %}
{% endfor %}
{% endblock content %}
The above code works perfectly and returns the records assigned to the user named testuser.
But if I write the code as below, it skips all records
{% extends 'blog/base.html' %}
{% block content %}
<h3>{{ user.username }}</h3>
{% for project in projects %}
{% if user.username == project.student_id %}
<h5>{{ project.title }}</h5>
<p>{{ project.description }}</p>
<p>{{ project.objectives }}</p>
<pre>{{ project.score }}</pre>
<pre>{{ project.student_id }}</pre>
{% endif %}
{% endfor %}
{% endblock content %}
I have added the code from the model
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Projects(models.Model):
title = models.CharField(max_length=150)
description = models.TextField()
objectives = models.TextField()
score = models.IntegerField()
#file = models.FileField()
date_posted = models.DateTimeField(default=timezone.now)
student_id = models.ForeignKey(User,on_delete=models.CASCADE)
def __str__(self):
return self.title

The student_id is a User object, not a string, so here you are comparing a string (the username) with a User object, and a User with username 'testuser', is not the same as a string 'testuser'.
The most elegant solution is probably to compare the user with the user, so:
{% if user == project.student_id %}
So we omit the .username, and compare a User object with a User object.
Note: enumeration (especially in a template, but also in the Django layer itself), is not efficient, you should make a query that
does the filtering for you.
You can filter a queryset with:
user_projects = Project.objects.filter(student_id=request.user)
in your view to obtain only projects for which the logged in user is
the student.
Note: A ForeignKey usually does not have an _id suffix. Django will automatically add an extra field named fieldname_id that
stores the primary key to which the foreign key refers. After all, a
ForeignKey in Django will lazy load the related object.

Related

Django - how to get all the users in team when using a costumised user model

I am new to django and have a question: I created a CustomUser model within a users app.
I tried
from users.models import CustomUser, Team
team1= Team.objects.first()
users_team1= team1.user.objects.all()
and it doesnt get me the list of users in this Team
class CustomUser(AbstractUser):
bio= models.CharField(max_length=300, null= True, blank=True)
class Team (models.Model):
title = models.CharField(max_length=200)
user= models.ManyToManyField(get_user_model())
date_created= models.DateTimeField(auto_now_add=True, blank=True, null=True)
date_updated= models.DateTimeField(auto_now=True,blank=True, null=True )
def __str__(self):
return self.title
def get_absolute_url(self): # new
return reverse('team_detail', args=[str(self.pk)])
I want created a HTML page
{% extends '_base.html' %}
{% block title %}{{ object.title }}{% endblock title %}
{% block content %}
<div class="team-detail">
<h2>{{ team.title }}</h2>
<p>Team tile : {{ team.title }}</p>
<p>user: {{ team.user }}</p>
</div>
{% endblock content %}
how can i show all the users in a specific Team?
Thanks in advance.
You should do:
from users.models import CustomUser, Team
team1= Team.objects.first()
# lets pass team1 to your template
return render(request, 'template/name.html', {'team': team1})
Your template should be sthg like:
{% extends '_base.html' %}
{% block title %}{{ object.title }}{% endblock title %}
{% block content %}
<div class="team-detail">
<h2>{{ team.title }}</h2>
<p>Team tile : {{ team.title }}</p>
{% for user in team.user.all %}
<p>user: {{ user }}</p>
{% endfor %}
</div>
{% endblock content %}

why i am not getting a followed_by(followers) entry showing up on my page

i am making a twitter like clone(just to learn how things works in django)
so i am basically trying to set up a many_to_many relationship.
i want to add the functionality of showing 'FOLLOWED_BY' and 'FOLLOWING' to a user profile but list of 'FOLLOWED_BY' is not showing on the page please someone help me!
in the models.py i have define two relationship
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL, related_name='profile', null=True,
blank=True)
following = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='followed_by', blank=True)
and in the user_detail.html i have the code for how a profile should look like
this is the models.py module:
from django.conf import settings
from django.db import models
# Create your models here.
class UserProfile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL, related_name='profile',
null=True,
blank=True)
following = models.ManyToManyField(settings.AUTH_USER_MODEL,
related_name='followed_by', blank=True)
def __str__(self):
return str(self.following.all().count())
below is the code for user_detail.html file:
{% extends "base.html" %}
{% block content %}
<div class="row">
<div class="col-sm-3 col-xs-12" style="background-color: yellow">
<h1>{{ object.username }}</h1>
<p>Followers: {{ object.followed_by.count }}</p>
</div>
<div class="col-sm-9 col-xs-12">
<h1>Tweets</h1>
{% for tweet in object.tweet_set.all %}
{{ tweet }}<br/>
{% endfor %}
<hr/>
<h1>Following</h1>
{% for user in object.profile.following.all %}
<a href='/{{ user.username }}'>{{ user.username }}</a><br/>
{% empty %}
<h4>Not following any users</h4>
{% endfor %}
<hr/>
<h1>Followed By</h1>
{% for profile in object.profile.followed_by.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not followed by any user</h4>
{% endfor %}
</div>
{% endblock content %}
for user profile i am getting the FOLLOWING field as i want but FOLLOWED_BY field is not showing how can i do that (what changes should i do in my code)??
You defined a following field that points to the user model, not to a Profile. As a result a Profile has no followed_by relation, a User object has.
I think it probably is better to let following point to Profile, like:
class UserProfile(models.Model):
user = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.SET_NULL,
related_name='profile',
null=True,
blank=True
)
following = models.ManyToManyField(
'self',
related_name='followed_by',
symmetrical=False,
blank=True
)
def __str__(self):
return str(self.following.all().count())
Then you can render this like:
<div class="col-sm-3 col-xs-12" style="background-color: yellow">
<h1>{{ object.username }}</h1>
<p>Followers: {{ object.followed_by.count }}</p>
</div>
<div class="col-sm-9 col-xs-12">
<h1>Tweets</h1>
{% for tweet in object.tweet_set.all %}
{{ tweet }}<br/>
{% endfor %}
<hr/>
<h1>Following</h1>
{% for profile in object.profile.following.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not following any users</h4>
{% endfor %}
<hr/>
<h1>Followed By</h1>
{% for profile in object.profile.followed_by.all %}
<a href='/{{ profile.user.username }}'>{{ profile.user.username }}</a><br/>
{% empty %}
<h4>Not followed by any user</h4>
{% endfor %}
</div>
Your code has however some (serious) anti-patterns. The most important one is that you should not write business logic in the template. You should use the view for that. For example you can specify in the view a context like:
context = {
'tweets': object.tweet_set.all()
'followers': object.profile.following.select_related('user').all()
'followed_by': object.profile.followed_by.select_related('user').all()
}
We here can also use a .select_related() [Django-doc] that will boost performance significantly, since now all the users are fetched in the same query.
You also better use the {% url ... %} template tag [Django-doc] to construct queries. So instead of writing:
<a href="/{{ profile.user.username }}">
it is better to construct the query using a reverse lookup like:
<a href="/{% url 'profile_view' username=profile.user.username %}">

Django Image by Foreign Key and {% if / else %}

I trying to access the ImageField of a Model which is assigned via ForeignKey to another Model.
I have different Animal Apps in my Projects, with almost the same structure, like the following models.py. On the landingpage of My Project I want to display the last 3 entry of every (Species) Models with Name and Picture. If the Species has no Picture I would like to display the ImageField of the Farm, which is connected via ForeignKey to my species.
cows/models.py
class Farm(models.Model):
name = models.CharField(max_length=100)
farm_img = models.ImageField(upload_to='farm_images/',
max_length=255, null=True, blank=True)
class Cows(models.Model):
farm = models.ForeignKey(Farm, on_delete=models.CASCADE, null=True)
name = models.CharField(max_length=100)
entry_date = models.DateField(null=True, blank=True)
cow_img = models.ImageField(upload_to='farm_images/',
max_length=255, null=True, blank=True)
Views.py
class HomeIndex(TemplateView):
template_name = 'home.html'
def get_context_data(self, **kwargs):
context['chickens'] = Chicken.objects.order_by('-entry_date')[:3]
context['cows'] = Cows.objects.order_by('-entry_date')[:3]
context['cats'] = Cats.objects.order_by('-entry_date')[:3]
return context
home.html
<….>
{% for somecow in cows %}
<div class="col-3" id="p1">
<h2>{{ somecow.name }}</h2>
<h2>{{ somecow.entry_date }}</h2>
{% if somecow.cow_img %}
<img src="{{ somecow.cow_img.url }}" alt="Mod" height="100">
{% endif %}
</div>
{% endfor %}
<….>
Until here it worked.
But how can i access the FK.Model of the Model?
Or in other Words how can I tell Django:
“If you found no cow Picture in Cow.Model,then show a Farm picture from the assigned Farm.Model?”
As I understand I can access the assigned FK Models via
{% for something in MyModel1.MyModel2_set.all %}.
my approach for home.html
<….>
{% for somecow in cows %}
<div class="col-3" id="p1">
<h2>{{ somecow.name }}</h2>
<h2>{{ somecow.entry_date }}</h2>
{% if somecow.cow_img %}
<img src="{{ somecow.cow_img.url }}" alt="Mod" height="100">
{% else %}
{% for farm in somecow.farm_set.all %}
{% if farm.farm_img %}
<img src="{{ farm.farm_img.url }}" alt="Mod" height="100">
{% endif %}
{% endfor %}
{% endif %}
</div>
{% endfor %}
<….>
So far I received no error Message, but I also see no Farm Image. I am sure I mixed something up in home.html. On the other Side I think I maybe I missed something in my view, something like MyModel.objects.all()
I am thankful for every hint.
You're overcomplicating things. There is only a single farm per cow: you just need to access it directly.
{% else %}
{% if cow.farm.farm_img %}
<img src="{{ cow.farm.farm_img.url }}" alt="Mod" height="100">
{% endif %}
{% endif %}

I can't display extended values of my user model

On this case my problem arise displaying extended values of my user model in my index.html
here my models.py
from django.db import models
from django.contrib.auth.models import User
def url(self,filename):
ruta = "MultimediaData/Users/%s/%s"%(self.user.username,filename)
return ruta
class userProfile(models.Model):
user = models.OneToOneField(User)
photo = models.ImageField(upload_to=url)
telefono = models.CharField(max_length=30)
email = models.EmailField(max_length=75)
def __unicode__(self):
return self.user.username
my index.html:
{% extends 'base.html' %}
{% block title %} Inicio - Bienvenidos {% endblock %}
{% block content %}
<p>Dracoin, el portal que facilitará tu vida</p>
{% if user.is_authenticated %}
<p>Bienvenido {{ user.username }}</p>
{% if user.get_profile.photo %}
<img src="/media/{{user.get_profile.photo}}" width="100px" height="100px"/>
{% endif %}
{% if user.get_profile.telefono %}
<p>Numero Tel: {{user.get_profile.telefono}}</p>
{% endif %}
{% endif %}
{% endblock %}
I don't have problem managing that information in my admin panel but i cant view that information in my index. I believe the mistake is in {% if user.get_profile.xxxx %} calling but I cant solve it.
apologizeme in advance if I overlook something.
Thanks!!
get_profile() was deprecated in django 1.5, and removed in django 1.7.
Try {{ user.userprofile.xxxx }} instead.

django view - all categories and all entries

I'm trying to build a page with all of the model's categories and associated entries in one view. I followed tips from here django class based views for all categories with all entires and here Get all categories and items in category but I still can't get it to work. Any ideas ?
-- models
class Category(models.Model):
name = models.CharField(max_length=50)
def __unicode__(self):
return self.name
class Feed(models.Model):
name = models.CharField(max_length=100)
url = models.CharField(max_length=100)
category = models.ForeignKey(Category)
user = models.ManyToManyField(User)
def __unicode__(self):
return self.url
-- views
def category_page(request):
object_list = Category.objects.all()
context = {'object_list': object_list,}
return render(request, 'category_page.html', context)
-- template category_page.html
{% block content %}
{% for category in object_list %}
{{ category.name }}
{% for entry in category.entry_set.all %}
{{ category.name}}
{% endfor %}
{% endfor %}
{% endblock content %}
I'm getting list of all categories displayed but no entries.
thanks
-M
Here
{% for entry in category.entry_set.all %}
{{ category.name}}
{% endfor %}
should be
{% for entry in category.feed_set.all %}
{{ entry.name}}
{% endfor %}
{{ category.name}} inside the forloop for entries is what is not displaying the correct name.
Also, what is entry_set ? If you are not specifying a related_name, you need to use the lower-case model name to get the related objects (feed_set in this case).
Something like this:
category.feed_set.all
Summing it up,
{% block content %}
{% for category in object_list %}
{{ category.name }}
{% for entry in category.feed_set.all %}
{{ entry.name}}
{% endfor %}
{% endfor %}
{% endblock content %}
You can read more on related objects here
If this is your actual code, the problem is variable names in your template.
{% for category in object_list %}
{{ category.name }}
{% for entry in category.feed_set.all %}
{{ entry.name}}
{% endfor %}
{% endfor %}
Specifically, you refer to entry_set, but that's not the reverse name for the relationship since your model name is Feed rather than Entry and you haven't declared a non-default related_name argument.
Also, you're re-printing your category name instead of the name of the Feed instances.