I am trying to build a page that displays all the friend requests for a user. Everything seems to work until I get to the line where I render the page.
I am using Django.
View
def friend_requests(request):
current_user = request.user.username
user_id = (User.objects.get(username=current_user)).id
all_requests = FriendshipRequest.objects.filter(to_user_id=user_id)
friend_requests = []
for request in all_requests:
from_user_id = request.from_user_id
from_user_id_username =(User.objects.get(pk=from_user_id)).username
friend_requests.append(from_user_id_username)
# for some reason i'm getting an attribute error here
return render(request, 'Users/friend_requests.html', {'friend_requests': friend_requests})
Template (friend_requests.html)
{% for request in friend_requests %}
{{request}}
{% endfor %}
I think the variable request you create when looping through friend_requests is shadowing the context processor {{request}} which represents the current request client has made.
Change your variable name sth different than request and you'll probably be good to go:
{% for friend_request in friend_requests %}
{{friend_request}} object of the current user {{request.user}}
{% endfor %}
Related
I'm creating a simple CRUD application without using the admin page of Django. I only have one template, index.html that displays all the list of student information. I have two views below, one is for displaying only when the user visited the index page. The other view is executed when a user in the index page clicks a submit button for registering a new student (via POST) then redirects to the index view again. I want to display an error message if the student already exists in the database (by using student number). My problem is how can I pass the error message in the index.html template after the HttpRedirect. Or am I doing it the wrong way?
def index(request):
studentList = Student.objects.all()
return render(request, "crud/index.html", {"student_list": studentList})
def addStudent(request):
data = request.POST
# print(data)
if data:
try:
newStudent = Student.objects.get(student_number=data['student_number'])
return HttpResponseRedirect(reverse("crud:index"))
except Student.DoesNotExist:
newStudent = Student(student_number=data['student_number'],
first_name=data['first_name'],
last_name=data['last_name'],
age=data['age'],
sex=data['sex'],
email=data['email']
)
newStudent.save()
return HttpResponseRedirect(reverse("crud:index"))
You should use .get_or_create for this:
from django.core.exceptions import SuspiciousOperation
def addStudent(request):
data = request.POST
student, created = Student.objects.get_or_create(
student_number=data['student_number'],
first_name=data['first_name'],
last_name=data['last_name'],
age=data['age'],
sex=data['sex'],
email=data['email']
)
if created:
return HttpResponseRedirect(reverse("crud:index"))
else:
raise SuspiciousOperation("student with id {} already exists!".format(data['student_number']))
Update
If you want to continue the redirect, and still send an alert to the user, you should use Django's built-in messages middleware.
Here is an example:
from django.contrib import messages
def addStudent(request):
...
if not created:
messages.warning(request, 'Student with ID {} already exists!'.format(data['student_number']))
return HttpResponseRedirect(reverse("crud:index"))
Now on your index.html, you need to check if any messages exist, and if they do, display them:
{% if messages %}
<ul class="messages">
{% for message in messages %}
<li{% if message.tags %} class="{{ message.tags }}"{% endif %}>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
If you want to customize how the message look and behave, see the docs for more details.
(Django , Python) I have created a list of book objects and it is being passed as context in my views.py along with the current session. On my template, i was to check if the books in that list are stored in the session, and if they are i want to access some info relating to that book within that session. how do i access the books in the session dynamically? is there a way?
i know i can access them by using "request.session.name" (where "name" is the same of the space in the session it is stored)
There are several book titles saved in the session, the way they are saved are as follows (in a function under views.py)
request.session["random book title"] = "random dollar price"
i want to access that "random dollar price" dynamically in a template.
this is the block of code in the template
{% for book in book_list %}
{% if book.title in request.session %}
{{ request.session.??? }}
{% endif %}
{% endfor %}
Thank you in advance!
You can make a custom template tag to look up by attribute like here
Performing a getattr() style lookup in a django template:
# app/templatetags/getattribute.py
import re
from django import template
from django.conf import settings
numeric_test = re.compile("^\d+$")
register = template.Library()
def getattribute(value, arg):
"""Gets an attribute of an object dynamically from a string name"""
if hasattr(value, str(arg)):
return getattr(value, arg)
elif hasattr(value, 'has_key') and value.has_key(arg):
return value[arg]
elif numeric_test.match(str(arg)) and len(value) > int(arg):
return value[int(arg)]
else:
return settings.TEMPLATE_STRING_IF_INVALID
register.filter('getattribute', getattribute)
Now change your template to
{% load getattribute %}
{% for book in book_list %}
{% if book.title in request.session %}
{{ request.session|getattribute:book.title }}
{% endif %}
{% endfor %}
This is a basic custom template tag example:
Django - Simple custom template tag example
and docs:
https://docs.djangoproject.com/en/1.11/howto/custom-template-tags/
From what I remember from my django days should work
You can put session data in a dictionary and send this data to target template when you want to render it in view function.
def some_function(request):
context={
'data':sessionData #put session data here
}
return render(request,"pass/to/template.html",context)
Now you can access 'data' in your template.html
I think you should just send a list of book names from your view instead of a queryset so when you are crosschecking with session you use the title directly instead.
{% for book in book_list %}
{% if book in request.session %}
{{ request.session.book }}
{% endif %}
{% endfor %}
I've got a function that is creating a list:
import feedparser
import ssl
def rss(self):
if hasattr(ssl, '_create_unverified_context'):
ssl._create_default_https_context = ssl._create_unverified_context
rss = 'https://news.google.com/news?q=fashion&output=rss'
feed = feedparser.parse(rss)
articles = []
for entry in feed.entries:
articles.append({
"summary" : str(entry.summary),
"link" : str(entry.link),
"title" : str(entry.title),
})
return articles
on the return of articles, I am then trying to display this in the view
My views.py code is:
def results(request):
rss_feed = RSS()
articles = rss_feed.rss()
return render(request, 'app/index.html', articles)
and then my template code is:
<ul>
{% for article in articles %}
<li>{{ article['title'] }}</li>
{% empty %}
<li>Sorry, no athletes in this list.</li>
{% endfor %}
</ul>
but I keep getting an error that reads:
TemplateSyntaxError at /app/results Could not parse the remainder:
'['title']' from 'article['title']'
I created a separate script and just print to console and it prints without issue. But doesn't show in Django.
I'm new to Python and Django. Not sure what I've missed.
Update:
Using {{ article.title }} returns an error context must be a dict rather than list.
You were passing the wrong context to the return function as you passed in your list directly to render. You have to pass your article list as a member of the context dictionary like this:
return render(request, 'app/index.html', {"articles": articles})
After this you can address the title of article as
{{ article.title }}
in your template.
I have an UpdateView in which I edit a single object. When the form is valid I am redirecting the user to a list with many objects.
In this list I want to highlight the object that was just successfully edited. I know Django's message framework where I can transfer messages from a view to another but how can I send which id to highlight?
Messages aren't really the right solution. Instead, use the sessions framework.
# in editing view:
obj = data.save() # or whatever
request.session['edited_object_id'] = obj.id
return ....
# in list view:
highlighted_id = request.session['edited_object_id']
# and in template:
{% for obj in objects %}
<li class="{% if obj.id == highlighted_id %}">...</li>
{% endif %}
I'm just starting with django (and python too, to be honest)
I am trying to get a model method that would cut the self.slug from current URL and return it to template.
This is the method I tried:
class Category(models.Model):
...
def remove_filter(self):
url = HttpRequest.get_full_path()
slug = '/' + self.slug
return url.replace(slug, '')
But as you can imagine, it doesn't work.
Template's snippet:
{% for object in active_filters %}
<li><i class="icon-remove"></i>{{ object }}</li>
{% endfor %}
My core goal here is to have a front-end icon with a url altered by removing current object's slug.
I have no idea how to do it through views, but I'm open to any suggestions.
def category_page(request, url):
slugs = url.split('/')
active = Category.objects.filter(slug__in=slugs)
sorted_slugs = []
for i in active:
sorted_slugs.append(i.slug)
if slugs != sorted_slugs:
url = '/'.join(sorted_slugs)
return redirect('http://127.0.0.1:8000/catalog/' + url)
inactive = Category.objects.exclude(slug__in=slugs)
return render(request, 'category.html', {'active_filters': active,
'inactive_filters': inactive})
Thanks.
You can send a list of all active slugs to the template and then build a custom template filter to construct the modified url.
views.py
# Send your list of active slugs to the template
return render(request, 'category.html', {
'active_filters': active,
'inactive_filters': inactive,
'slugs': slugs,
})
tags_and_filters.py
import copy
from django import template
register = template.Library()
#register.filter(name='remove_filter')
def remove_filter(category, slugs):
copied_slugs = copy.copy(slugs)
slug = category.slug
if slug in copied_slugs:
copied_slugs.remove(slug)
return '/'.join(copied_slugs)
your template
{% for object in active_filters %}
<li>
<i class="icon-remove"></i>{{ object }}
</li>
{% endfor %}
Your remove_filter method has no access to the current request. HttpRequest is the class, not the current request instance.
I suggest that you rewrite remove_filter as a custom tag or filter. That way your function can access the category and request instance. You will have to activate the request template context processor in your settings as well.