I have a list of assets, created by different users. I'd like to show the assets for each user in a template.
Right now, I have this (there's more code, but not relevant for this issue):
models.py:
from django.db import models
from django.contrib.auth.models import User
from tinymce import models as tinymce_models
class Asset(models.Model):
title = models.CharField(max_length=200)
description = tinymce_models.HTMLField()
dateadded = models.DateField(auto_now=True)
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
file = models.FileField(upload_to='images/', verbose_name='Image', null=True, blank=True)
url = models.URLField(max_length=500, blank=True, default='')
views.py
from .models import Asset
from django.contrib.auth.models import User
def assets(request):
assets = Asset.objects
users = User.objects
context = {'assets':assets, 'users':users}
return render(request, 'assets/assets.html', context)
But what should I put in my template? The following gives a list of all assets, but the second part should only show assets by 'bob' and eventually all assets listed by user (all assets by 'bob, all assets by 'pete', etc) regardless of the user being signed in.
{% for asset in assets.all %}
{% if asset.file %}
{{ asset.dateadded_pretty }} - {{ asset.title }} <span style="font-size:11px">
({{ asset.ext }} - {{ asset.size }})</span>
{% else %}
{{ asset.dateadded_pretty }} - {{ asset.title }} <span style="font-size:11px">
(external link)</span>
{% endif %}
<br>
{% endfor %}
<br><br><br>
Assets by Bob:
{% for asset in assets.all %}
{% if asset.user == "bob" %}
{{ user.title}}
{% endif %}
{% endfor %}
{% endblock %}
Thanks for any pointers!
First query all the users in view
def assets(request):
assets = Asset.objects.all()
users = User.objects.all()
context = {'assets':assets, 'users':users}
EDIT: you can filter the users who has assets like this.
users = User.objects.filter(id__in=assets)
Now in the template you can do like this to get the assets by individual user
{% for user in users %}
{{user.email}}
{% for asset in user.asset_set.all %}
{{ asset.title}}
{% endfor %}
{% endfor %}
Related
I'm working with flask and have a html page that contains of user name(user.html) which took from table, Now How can I see more detail by clicking on each of users(which route to profile)?
I don't use login for app So I don't want to use g
app.py
# am I doing it right?
#app.route('/profile/<int:id>')
def profile(id=None):
detail = Contacts.query.get(id)
return render_template('profile.html', detail= detail , id=id)
user.html
{% extends "layout.html" %}
{% block content %}
<h2>show user</h2>
{% for contact in contact %}
# I got error when I click on each user name to see their 'profile'
#I guess because of id How can Solve it?
#error BuildError: ('profile', {}, None)
<strong>name:</strong><a href={{url_for('profile')}}>
{{ contact.name}}</a><br>
{% endfor %}
{% endblock %}
profile.html
{% extends "layout.html" %}
{% block content %}
<h2>show user profile</h2>
# how can I make it specific for each row of table(each user)?
{% for detail in Contacts %}
<strong>name:</strong> {{ detail.name}} <br>
<strong>email:</strong> {{ detail.email }} <br>
<strong>age:</strong> {{ detail.age}} <br>
<br>
{% endfor %}
{% endblock %}
model.py
class Contacts(db.Model):
__tablename__ = "Contacts"
id = db.Column(db.Integer, primary_key = True)
name = db.Column(db.String(50))
email = db.Column(db.String(50))
age = db.Column(db.Integer)
submit = SubmitField("Submit")
I noticed two things in your code:
# this
<a href={{url_for('profile')}}>
# should be
<a href={{url_for('profile', id=contact.id)}}>
# otherwise Flask can't find the route, because it needs an id
And the other one:
{% for detail in Contacts %}
There is no such thing as a Contacts variable in your template, because your view function does not send it. Just get rid of the loop and use detail directly, because it's what you sent to the template.
I'm stuck on a problem. I need to filter all of the listings using the list.id in the for loop. Unfortunately, the filter function in Django could not be parsed. Is there another solution or is there a way to work around it? How can you run a function in Django HTML template. Thanks!
index.html
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
{% if not listing %}
<h3>Nothing listed...</h3>
{% endif %}
{% for list in listing %}
<h3>Listing: {{ list.title }}</h3>
{% if list.photo != "" %}
<img src="{{ list.photo }}">
{% endif %}
<p>{{ list.description }}</p>
{% if not bids.filter(listing=list.id) %} #This line could not be parsed
<h5>${{ list.price }}</h5>
{% else %}
<h5>${{ bids.filter(listing=list.id).order_by(-bids).first().bids }}</h5> #This line could not be parsed
{% endif %}
<p>
{% if not bids.filter(listing=list.id).count() %} #This line could not be parsed
0
{% else %}
{{ bids.filter(listing=list.id).count() }} #This line could not be parsed
{% endif %}
bid(s) so far.
{% if bids.filter(listing=list.id).order_by(-bids).first().bidder == user.username %} #This line could not be parsed
Your bid is the current bid.
{% elif not bids.filter(listing=list.id).order_by(-bids).first().bidder %} #This line could not be parsed
There is no bid.
{% elif bids.filter(listing=list.id).order_by(-bids).first().bidder != user.username %} #This line could not be parsed
{{ bids.filter(listing=list.id).order_by(-bids).first().bidder }} is the current bid. #This line could not be parsed
{% endif %}
</p>
{% if user.username != list.user and user.is_authenticated %}
<form action="{% url "index" %} method="post">
{% for form in forms %}
{{ form }}
<input type="submit" value="Bid">
</form>
{% endfor %%}
{% endif %}
<h4>Details</h4>
<ul>
{% if user.username == list.user %}
<li>Listed by: You</li>
{% else %}
<li>Listed by: {{ list.user }}</li>
{% endif %}
<li>Category: {{ list.category }}</li>
</ul>
<hr>
{% endfor %}
{% endblock %}
views.py
from .models import User, AuctionList, Bids, Comments
from .forms import AuctionForm, BidsForm
def index(request):
if request.method == "POST":
pass
else:
AL = AuctionList.objects.all()
Bd = Bids.objects.all()
forms = BidsForm()
return render(request, "auctions/index.html", {
"listing": AL.order_by("id"),
"bids": Bd,
"forms": forms
})
models.py
from django.contrib.auth.models import AbstractUser
from django.db import models
class User(AbstractUser):
pass
class AuctionList(models.Model):
CATEGORY_CHOICES = [
('Books', 'Books'),
('Business & Industrial', 'Business & Industrial'),
('Clothing, Shoes & Accessories', 'Clothing, Shoes & Accessories'),
('Collectibles', 'Collectibles'),
('Consumer Electronics', 'Consumer Electronics'),
('Crafts', 'Crafts'),
('Dolls & Bears', 'Dolls & Bears'),
('Home & Garden', 'Home & Garden'),
('Motors', 'Motors'),
('Pet Supplies', 'Pet Supplies'),
('Sporting Goods', 'Sporting Goods'),
('Sports Mem, Cards & Fan Shop', 'Sports Mem, Cards & Fan Shop'),
('Toys & Hobbies', 'Toys & Hobbies'),
('Antiques', 'Antiques'),
('Computers/Tablets & Networking', 'Computers/Tablets & Networking')
]
id = models.AutoField(primary_key=True)
user = models.CharField(max_length=20, default='None')
title = models.CharField(max_length=20)
category = models.CharField(
max_length=30, choices=CATEGORY_CHOICES, default='Books')
description = models.TextField()
price = models.FloatField()
photo = models.URLField(max_length=200, blank=True)
def __str__(self):
return f"({self.id}) | Title: {self.title} | Category: {self.category} | Price: {self.price} | Posted by: {self.user}"
class Bids(models.Model):
bidder = models.CharField(max_length=20, default='None')
listing = models.ForeignKey(
AuctionList, on_delete=models.CASCADE, related_name="bids")
bids = models.FloatField()
def __str__(self):
return f"Listing Key: {self.listing} | Bids: {self.bids}"
You can create another function in your views.py and pass it in your index function (example below to give you some idea in views.py & index.html)
def build_auctions_layout(username):
final_html = None
for list in listing:
final_html = '<h3>Listing: {}</h3>'.format(list.title)
if list.photo:
final_html += '<img src="{}"'.format(list.photo)
final_html += '<p>{}</p>'.format(list.description)
if not list.bids: #This line could not be parsed
final_html += '<h5>${}</h5>'.format(list.price)
else:
final_html += '<h5>${}</h5>'.format(list.bids.order_by(-bids).first().bids ) #This line could not be parsed
final_html += '<p>{} bid(s) so far'.format(list.bids.count())
if list.bids.order_by(-bids).first().bidder == username:
final_html += 'Your bid is the current bid.</p>'
else:
final_html += 'There is no bid.</p>'
return final_html
def index(request):
if request.method == "POST":
pass
else:
AL = AuctionList.objects.all()
Bd = Bids.objects.all()
forms = BidsForm()
return render(request, "auctions/index.html", {
"listing": AL.order_by("id"),
"bids": Bd,
"forms": forms,
"auctions_layout": build_auctions_layout(request.user.username)
})
#auctions/index.html
{% extends "auctions/layout.html" %}
{% block body %}
<h2>Active Listings</h2>
{% if not listing %}
<h3>Nothing listed...</h3>
{% endif %}
{{auctions_layout|safe}}
......
The answer is yes you can run filter function inside your html template. Infact filter functions are meant for and frequently used everywhere in django templates which you can find in django more precisely as Custom template filters
You can also create one filter function as per your requirement and use it anywhere inside your template which is known as Django Templatetags. These template tags are nothing but a sort of functions which you define yourself and implement in templates.Here I explain you step by step:
For referene, my project name is "working_blog_python" and app name is "branch"
1. open your terminal and type
(working_blog_python) $ cd branch
(working_blog_python) $ mkdir templatetags
(working_blog_python) $ touch templatetags/any_name_tags.py
2.Now inside your
any_name_tags.py
you can write your filter function like this
from django import template
register = template.Library()
#register.filter_function
def hrs(self):
return self.name.replace('-', ' ')
3.Now you can use this hrs() function anywhere in your templates, but don't forget to load {% load name_tags %} name_tag inside your template.
<p>Shop is located in {{branch.state | hrs | title}}.</p>
I have two model called organization and staff.Staff model have onetoone relation with user and Foreignkey relation to the organization.The problem what i got is to filter the staffs by their related organization.I have tried liked this but didn't worked out.
models.py
class Staff(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE, related_name='user')
name = models.CharField(max_length=255, blank=True, null=True)
organization = models.ForeignKey(Organization, on_delete=models.SET_NULL, blank=True, null=True,
related_name='organization')
.....other fields.....
views.py
def view_staff_users(request):
staff_users = User.objects.filter(is_staff=True)
organizations = Organization.objects.all()
staffs_by_org = Staff.objects.select_related('organization')
# tried this also:
# staffs_by_org = []
# print('staffff',staffs_by_org)
# for organization in organizations:
# staffs = Staff.objects.filter(organization=organization)
# staffs_by_org.extend(staffs)
# print('staaa',staffs_by_org)
Edited views:
def view_staff_users(request):
staff_users = User.objects.filter(is_staff=True)
organizations = Organization.objects.all()
staffs_by_org = []
for organization in organizations:
staffs_by_org = Staff.objects.filter(organization__name=organization).select_related('organization')
template
{% for user in staffs_by_org %}
# tried this also: {% for u in user.organization_set.all %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
Edit: My template looks like this.
<ul class="nav nav-tabs customtab" role="tablist">
<li class="nav-item"> <a class="nav-link active" data-toggle="tab" href="#all" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">All Staffs</span></a> </li>
{% for organization in organizations %}
<li class="nav-item"> <a class="nav-link" data-toggle="tab" href="#{{organization.name}}" role="tab"><span class="hidden-sm-up"></span> <span class="hidden-xs-down">{{organization.name}}</span></a> </li>
{% endfor %}
</ul>
<div class="tab-content">
<div class="tab-pane active" id="all" role="tabpanel">
{% for user in staff_users %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
</div>
{% for organization in organizations %}
<div class="tab-pane tab" id="{{organization.name}}" role="tabpanel">
{% endfor %}
{% for user in staffs_by_org %}
# tried this also: {% for u in user.organization_set.all %}
{{user.user.name}}
{{user.username}}
{{user.email}}
{{user.user.organization}}
{% endfor %}
</div>
You can filter for example with:
staffs_by_org = Staff.objects.filter(
organization__name='My organization'
).select_related('organization')
The staffs_by_org is a QuerySet of Staffs. I therefore stronly advice to use staff in the iterator. You can access the organization with staff.organization:
{% for staff in staffs_by_org %}
{{ staff.name }}
{{ staff.user.username }}
{{ staff.user.email }}
{{ staff.organization }}
{% endfor %}
If the organization has for example a name, you can render it with:
{% for staff in staffs_by_org %}
{{ staff.name }}
{{ staff.user.username }}
{{ staff.user.email }}
{{ staff.organization.name }}
{% endfor %}
Note that the related_name of a ForeignKey is the name of the relation in reverse. A better name is probably 'staff'. If you refer to the user model, it is better to use get_user_model() [Django-doc], since if you later change your mind, you can easily use another user model.
from django.contrib.auth import get_user_model
class Staff(models.Model):
user = models.OneToOneField(
get_user_model(),
on_delete=models.CASCADE,
related_name='staff'
)
name = models.CharField(max_length=255, blank=True, null=True)
organization = models.ForeignKey(
Organization,
on_delete=models.SET_NULL,
blank=True,
null=True,
related_name='staff'
)
I think one problem is that you created a loop that is rewriting itself instead of appending each batch of staff users to your queryset.
One way to do what you want (return all staff that belong to a set of organizations) is to use the in filter operator.
So, in your views.py:
organizations = Organization.objects.all()
staffs_by_org = Staff.objects.filter(
organization__in=organizations).select_related('organization')
This will return all staff from whatever organizations is.
If you want a dynamic filter for the organization name, then what you have to do is:
Pass the organization name to the request. This is usually done via
URL parameters or query strings.
Change the organizations variable
from objects.all() to objects.filter(URL_PARAMETER)
Then staffs_by_org will only return the staff from that organization.
I'm using django-taggit on one of my projects and I'm able to save and tie the tags with specific records. Now the question is how do I display the tags related to each record?
For example on my page I want to display a record which contains a title and content and then under it I want to show the tags tied to that record.
What goes in the views.py, and mytemplate.html? Real examples would be truly appreciated.
models.py
from django.db import models
from taggit.managers import TaggableManager
class MyObject(models.Model):
title = models.CharField(max_length=100)
content = models.TextField()
tags = TaggableManager()
views.py
from django.views.generic import simple
def show_object(request):
""" View all objects """
return simple.direct_to_template(request,
template="folder/template.html",
extra_context={
'objects':MyObject.objects.all(),
})
template.html
{% for object in objects %}
<h2>{{ object.title }}</h2>
<p>{{ object.content }}</p>
<ul>
{% for tag in object.tags.all %}
<li> {{ tag.name }} </li>
{% endfor %}
</ul>
{% endfor %}
If you are in a hurry you can also try:
{{context_name.tags.all|join:", "}}
Hay, is it possible to a get a request.session value from a model method in django?
MEGA UPDATE
Here is my model
class GameDiscussion(models.Model):
game = models.ForeignKey(Game)
message = models.TextField()
reply_to = models.ForeignKey('self', related_name='replies', null=True, blank=True)
created_on = models.DateTimeField(blank=True, auto_now_add=True)
userUpVotes = models.ManyToManyField(User, blank=True, related_name='threadUpVotes')
userDownVotes = models.ManyToManyField(User, blank=True, related_name='threadDownVotes')
votes = models.IntegerField()
def html(self):
DiscussionTemplate = loader.get_template("inclusions/discussionTemplate")
return DiscussionTemplate.render(Context({
'discussion': self,
'replies': [reply.html() for reply in self.replies.all().order_by('-votes')]
}))
def _find_users_who_have_voted(self):
user_list = []
for user in self.userDownVotes.all():
user_list.append(user.id)
for user in self.userUpVotes.all():
user_list.append(user.id)
return user_list
users_voted = property(_find_users_who_have_voted)
and my view is called like this
<ul>
{% for discussion in discussions %}
{{ discussion.html }}
{% endfor %}
</ul>
and the template
<li>
<small>
({{ discussion.votes }} votes)
{% if user_id not in discussion.users_voted %}
user not in list!
{% endif %}
</small>
<strong>{{ discussion.message }}</strong>
{% if replies %}
<ul>
{% for reply in replies %}
{{ reply }}
{% endfor %}
</ul>
{% endif %}
the value 'user_voted' returns a list of user ids who has voted on this discussion.
I want to see if the request.session['user'].id value is inside this list
Why don't you use Django's render_to_string inside a view, which would have request happily available to it, and avoid model method altogether?
UPDATE: after skimming your mega update, you should look into Django's inclusion tags and use the data from the model to fill a template, not use a model to render the template. Keep your model and your template separate - Django is an MVT / MCV framework for good reason :)
you can access the current user, and so their session using threadlocals middleware
http://code.arcs.org.au/gitorious/django/django-andsome/blobs/ee8447e3dad2da9383ff701ec640b44cd50d2b0a/middleware/threadlocals.py
but keep in mind:
http://code.djangoproject.com/wiki/CookBookThreadlocalsAndUser
There might be better solutions to your problem. Maybe you'd like to elaborate why you need request.session on model level?
UPDATE:
since you explicitly call some method - probably from a view - why don't you just put the request.user as parameter to your html method?
models.py:
def html(self, user):
your code...
views.py:
yourmodel.html(request.user)
UPDATE to your MEGA UPDATE:
This is exactly what {% include %} is for:
in your first template do this:
{% for discussion in discussions %}
{% include "discussion.html" }}
{% endfor %}
and the second template has request.user.id in its namespace:
{% if request.session.user.id not in discussion.users_voted %}
user not in list!
{% endif %}