Code I'm working with:
class Message(models.Model):
from_who = models.ForeignKey(User, related_name='sent')
to = models.ForeignKey(User, related_name='recieved')
text = models.CharField(max_length=1000)
timestamp = models.DateTimeField(auto_now_add=True)
new = models.BooleanField(default=True)
Can I display in template User.recieved messages only with new = True when I'm using request.user not context? If yes, how?
If I understand the question - you want to show all new message to the logged in user without adding any additional context to the view? Try this (and note that I changed the spelling of "received":
{% for message in request.user.received.all %}
{% if message.new %}
{{ message }}<br />
{% endif %}
{% endfor %}
For someone who is looking an answer:
#models.py
class Message(models.Model):
from_who = models.ForeignKey(User, related_name='sent')
to = models.ForeignKey(User, related_name='recieved')
text = models.CharField(max_length=1000)
timestamp = models.DateTimeField(auto_now_add=True)
new = models.BooleanField(default=True)
new_messages = NewMessageManager()
#managers.py
class NewMessageManager(models.Manager):
def new_messages(self):
return super(NewMessageManager, self).get_queryset().filter(new=True)
#template.html
{% if request.user.recieved.new_messages %}
<span class="badge badge-danger">{{ request.user.recieved.new_messages.count }}</span>
{% endif %}
Related
In my Django project, I am trying to create a website that streams TV shows. Each show belongs in many categories, hence the use of many to many relations in my model. What I want to do with a certain page on my website is dynamically load a page of shows belonging to a specific category. However, all of my attempts have ended in failure as I am unable to figure out a way on how to access the actual category data from each show.
In views.py
def shows_in_category(request, category_slug):
category = get_object_or_404(Category, slug=category_slug)
showsall = theShow.objects.all()
shows = []
for show in showsall:
print(show.category.name, category.name)
if show.category.name == category.name:
shows.append(show)
print(shows)
return render(request, 'show/show_list_view.html', {'category':category, 'shows': shows})
In models.py
class Category(models.Model):
name = models.CharField(max_length=255, db_index=True)
slug = models.SlugField(max_length=255, unique=True)
class Meta:
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
def get_absolute_url(self):
return reverse("theshowapp:shows_in_category", args=[self.slug])
class theShow(models.Model):
english_name = models.CharField(max_length=400)
show_type = models.CharField(max_length=200, blank=True)
is_active = models.BooleanField(default=False)
category = models.ManyToManyField(Category)
slug = models.SlugField(max_length=400,unique=True)
class Meta:
verbose_name_plural = 'Shows Series'
def __str__(self):
return self.english_name
In the template (show_list_view.html)
{% for show in shows %}
<script> console.log("I'm trying to get in")</script>
<script> console.log("{{ show.name }} {{show.category.name}}")</script>
<script> console.log("I'm in")</script>
<div class="row">
<div class="col-lg-4 col-md-6 col-sm-6">
<div class="product__item">
<div class="product__item__text">
<ul>
{% for genre in show.category %}
<li>{{ show.category }}</li>
{% endfor %}
</ul>
<h5>{{ show.english_name }}</h5>
</div>
</div>
</div>
</div>
{% endfor %}
Any insight on this matter would be much appreciated.
What you're doing here violates some of the best practices of Django and also isn't using the Django ORM to its full potential. Please replace the lines
showsall = animeShow.objects.all()
shows = []
for show in showsall:
print(show.category.name, category.name)
if show.category.name == category.name:
shows.append(show)
print(shows)
with
shows = animeShow.objects.filter(category__name=category.name)
Also in the template change <li>{{ show.category }}</li> to <li>{{ genre }}</li> since that's the iterating variable.
I read up a bit more on the many to many fields examples in Django's documentation and figured out that I should use this:
shows = animeShow.objects.all().filter(category__name=category)
I would like to create a simple forum with Python Django. The main thing I can not figure out is getting informations from two models.
I want to display: Post title, content, author, published date and signature. This is my post_detail.html
{% extends 'Homepage/base.html' %}
{% block content %}
<h1>{{ post.title }}</h1>
<h6>Kategoria: {{ post.category }} | Autor: {{ post.author }} | {{ post.published_date }}</h6>
<p>{{ post.description|linebreaksbr }}</p>
<p><hr>{{ HERE I DON'T KNOW HOW TO SHOW SIGNATURE }}</p>
{% endblock %}
</body>
</html>
Homepage app models.py
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
class Category(models.Model):
title = models.CharField(max_length=100)
description = models.TextField()
def __str__(self):
return self.title
class Post(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=100)
description = models.TextField()
category = models.ForeignKey(Category, on_delete=models.CASCADE)
published_date = models.DateTimeField(default=timezone.now)
updated = models.DateTimeField(blank=True, null=True)
views = models.IntegerField(default=0)
def __str__(self):
return self.title
accounts app models.py
from django.db import models
from django.contrib.auth.models import User
from django.db.models.signals import post_save
class UserProfile(models.Model):
user = models.OneToOneField(User, related_name='user', on_delete=models.CASCADE)
website = models.URLField(default='', blank=True)
city = models.CharField(max_length=100, default='', blank=True)
signature = models.TextField(default='', blank=True)
def create_profile(sender, **kwargs):
user = kwargs["instance"]
if kwargs["created"]:
user_profile = UserProfile(user=user)
user_profile.save()
post_save.connect(create_profile, sender=User)
def __str__(self):
return self.user.username
My full code is on https://github.com/Incybro/Forum
You can just follow the relationships:
<p>{{ post.author.user.signature }}</p>
(Note, you've set the related_name from User to UserProfile to user, which makes no sense. You should leave it as the default, which would be userprofile.)
I guess your {{post.author}} won't be returning anything, change in to {{post.author.get_full_name}}
For signature, in your model you don't need to add any related name,
user = models.OneToOneField(User, on_delete=models.CASCADE)
in template,
{{post.author.userprofile.signature}}
Why not just return the relevant UserProfile model when you send the request?
def my_view(request):
context = {}
my_post = Post.objects.all.get(0) # get the post here
my_user = UserProfile.objects.get(user=my_post.author)
context['post'] = my_post
context['user'] = my_user
return TemplateResponse(request, 'my_template.html', context)
Then, in your html, you can use those template tags.
{% block content %}
<h1>{{ post.title }}</h1>
<h6>Kategoria: {{ post.category }} | Autor: {{ post.author }} | {{ post.published_date }}</h6>
{% autoescape on %}
<p>{{ post.description|linebreaksbr }}</p>
<p><hr>{{ user.signature }}</p>
{% endautoescape %}
{% endblock %}
You want the autoescape so people can't change the look or function of your site by injecting malicious HTML/JS into your site.
I want to display all the users, in my template but I cannot. I think there is a mistake in my codes but I cannot find it. Here is codes.
views.py
class UsersView(TemplateView):
template_name = 'users.html'
def get_context_data(self, **kwargs):
context = super(UsersView, self).get_context_data(**kwargs)
context['object_list'] = UserList.objects.all()
return context
models.py
class UserList(AbstractBaseUser):
first_name = models.CharField(max_length=200, blank=True, help_text="The first name of the user.")
last_name = models.CharField(max_length=200, blank=True, help_text="The last name of the user.")
email = models.EmailField(
verbose_name='email address',
max_length=255,
unique=True,
help_text="The email and username of the user. Required."
)
users.html
{% extends 'blog/base.html' %}
{% block content %}
<h1>Users:</h1>
<ul>
{% for users in object_list %}
<li class="user">{{ user }}</li>
{% endfor %}
</ul>
{% endblock %}
And this is the page that I get:
Where is my mistake? Thank you.
Your code includes the following:
{% for users in object_list %}
<li class="user">{{ user }}</li>
{% endfor %}
The trouble with this is that the user template variable is not defined. Change users to user in the loop header and you should be OK.
You can use django.contrib.auth.models.User on your view with request.user.get_username() with this you use a standard user with Django. If go go admin URL you see user default.
For call in template :
{{ user.get_username }}
I'm learning Django after having built some basic apps in Flask. One thing I want to do is show users a list of all posts and whether or not they follow that given post. However, Jinja or Django is throwing some error that I don't quite know how to debug.
Models.py
class User(models.Model):
id = models.AutoField(primary_key=True)
username = models.CharField(unique=True, max_length=120,blank=False)
password = models.CharField(max_length=120, blank=True, null=False)
class Record(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=120, unique=True, blank=True)
followers = models.ManyToManyField(User, through='Follow')
class Follow(models.Model):
id = models.AutoField(primary_key=True)
record = models.ForeignKey(Record)
user = models.ForeignKey(User)
date_followed = models.DateField(null=True, blank=True)
records.html
{% for i in records %}
{% if i.follow.filter(id='1').first() %}
DO SOMETHING
{% endif %}
{% endfor %}
error
TemplateSyntaxError at /records/
Could not parse the remainder: '(id='1').first()' from 'i.follow.filter(id='1').first()'
To test this out when I run the python manage.py shell and execute the following I have no issues:
>>> x = Record.objects.first()
>>> x.followers.filter(id='1').first()
<User: User object>
I had initially prototyped this app using Flask and had the following jinja template and never had an issue:
{% for i in accounts %}
{% if i.follow.filter_by(user_id='1').first() %}
DO SOMETHING
{% endif %}
{% endfor %}
You cannot do that logic in template. You can create a method in Record model that does it for you and you can call it in template
class Record(models.Model):
id = models.AutoField(primary_key=True)
name = models.CharField(max_length=120, unique=True, blank=True)
followers = models.ManyToManyField(User, through='Follow')
def first_follower(self):
if self.follow_set.filter(user_id=1).exists():
return True
return False
and in template:
{% for i in records %}
{% if i.first_follower %}
DO SOMETHING
{% endif %}
{% endfor %}
This is by design https://code.djangoproject.com/ticket/1199
The idea is that a django template should focus on design, for designers, and let the more complex code run in Python, not when the template renders.
So if this is a single instance when you use this check, add it to the view:
def get_context_data(self,*arg,**kwargs):
context = super(MyRecordView,self).get_context_data(*args,**kwargs)
context[has_follow] = self.object.follow.filter_by(user_id='1').exists()
return context
In the template:
{% if has_follow %}
...
{% endif %}
However, if you use this check a lot, you can add it to your model:
def has_follow(self):
return self.follow.filter_by(user_id='1').exists()
And then you can access it in a template, w/o any changes to the view context, since it's a model attribute:
{% if i.has_follow %}
...
{% endif %}
Given the following code:
Models.py
class Advertisement(models.Model):
title = models.CharField(null=True, blank=True, max_length=30)
created_by = models.ForeignKey(User)
class Gallery(models.Model):
advertisement = models.ForeignKey(Advertisement, related_name='images')
image = models.ImageField(upload_to=image_directory_path, help_text="Your ad image (Recommended size: 1024x768)")
creation_date = models.DateTimeField(editable=False, default=timezone.now)
Views.py
def do_foo(request):
search_result = Advertisement.objects.all().order_by('-creation_date')
return render(request, 'content_search.html',
{
'search_result': search_result
})
page.html
{% for ad in search_result %}
{% for ad_image in ad.gallery_set %}
<img src="{{ ad_image.image.url }}">
{% endfor %}
{% endfor %}
How do I access the backwards relation between Advertisement and Gallery? I tried ad.gallery_set and ad.images_set but I could not get the images.
I tried to follow what they say here Django Relation Objects Reference and in this topic.
Your code has related_name="images". So ad.images it is.
Edit: as shredding notes correctly, you can't use that directly if you want to loop over it, and need to add .all to get a queryset object:
{% for ad_image in ad.images.all %}
<img src="{{ ad_image.image.url }}">
{% endfor %}
Maybe related name "galleries" would be a bit more clear.