I'm accomplishing this at the moment by doing:
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
Which seems crazy counter intuitive to me.
Say if i was already at the urls of players/one/two/three
Is there an already prebuilt way to get current kwargs of one, two & three for use in templates?
Edit
urls.py
urlpatterns = patterns('',
url(
r'^$',
NationListView.as_view(),
name='index'
),
url(
r'^(?P<slug>[a-z-]*)/$',
NationDetailView.as_view(),
name='nation'
),
url(
r'^(?P<slug>[a-z-]*)/(?P<card_type>[a-z]*)/(?P<role_line>[a-z]*)/(?P<sort_by>[a-z0-9]*)/$',
NationDetailFilteredView.as_view(),
name='nation_filter'
),
)
The mixin that builds the context
class CoreDetailFilteredMixin(object):
def get_context_data(self, **kwargs):
# Call the base implementation first to get a context
context = super(CoreDetailFilteredMixin, self).get_context_data(**kwargs)
base_objects(context)
# Pull all the players that belong to the object_type
context['players'] = Player.objects.filter(
**{filters: context['object'].asset_id}
)
# Define the available card types
card_types = {
'if': {'card_type__gte': 2},
'gold': {'overall_rating__gte': 75},
'silver': {'overall_rating__range': (65, 74)},
'bronze': {'overall_rating__lte': 64}
}
# Check if the given card type is in the dictionary because 'all' throws an KeyError
if self.kwargs['card_type'] in card_types:
context['players'] = context['players'].filter(**card_types[self.kwargs['card_type']])
# Don't show inform cards for specific colour card types
if self.kwargs['card_type'] not in ['if', 'all']:
context['players'] = context['players'].exclude(card_type__gte=2)
# Define available role lines
role_lines = {
'att': 3,
'mid': 2,
'def': 1,
'gk': 0
}
# Check if the given role line is in the dictionary because 'all' throws an KeyError
if self.kwargs['role_line'] in role_lines:
context['players'] = context['players'].filter(role_line=role_lines[self.kwargs['role_line']])
# Define the available sort by keys
sorts = {
'ovr': 'overall_rating',
'att1': 'card_att1',
'att2': 'card_att2',
'att3': 'card_att3',
'att4': 'card_att4',
'att5': 'card_att5',
'att6': 'card_att6r'
}
# Add a descending order to the existing queryset
context['players'] = context['players'].order_by('-' + sorts[self.kwargs['sort_by']])
# Create pagination
cbv_pagination(self, context, context['players'], 28, 'players')
context['card_type'] = self.kwargs['card_type']
context['role_line'] = self.kwargs['role_line']
context['sort_by'] = self.kwargs['sort_by']
return context
How i use it currently in the template
{% with object.get_class_name|add:'s'|add:':'|add:object.get_class_name|add:'_filter'|lower as url_string %}
<dl class="sub-nav">
<dt>Card Type:</dt>
{% with 'all if gold silver bronze' as card_types %}
{% for ct in card_types.split %}
{% cycle 'All' 'Inform' 'Gold' 'Silver' 'Bronze' as card_type_name silent %}
{% if card_type == ct %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug ct role_line|default:'all' sort_by|default:'ovr' %}">
{{ card_type_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Role Line:</dt>
{% with 'all att mid def gk' as role_lines %}
{% for rl in role_lines.split %}
{% cycle 'All' 'Attackers' 'Midfielders' 'Defenders' 'Goalkeepers' as role_lines_name silent %}
{% if role_line == rl %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' rl sort_by|default:'ovr' %}">
{{ role_lines_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
<dl class="sub-nav">
<dt>Sort By:</dt>
{% with 'ovr att1 att2 att3 att4 att5 att6' as sorts %}
{% for sort in sorts.split %}
{% ifequal role_line 'gk' %}
{% cycle 'Overall' 'Diving' 'Handling' 'Kicking' 'Reflexes' 'Speed' 'Positioning' as sorts_name silent %}
{% else %}
{% cycle 'Overall' 'Pace' 'Shooting' 'Passing' 'Dribbling' 'Defending' 'Heading' as sorts_name silent %}
{% endifequal %}
{% if sort_by == sort %}
<dd class="active">
{% else %}
<dd>
{% endif %}
<a href="{% url url_string object.slug card_type|default:'all' role_line|default:'all' sort %}">
{{ sorts_name }}
</a>
</dd>
{% endfor %}
{% endwith %}
</dl>
{% endwith %}
As I learnt here, the view is already passed to the context (for class-based views). So you can do the following in the template without needing to explicitly pass the kwargs from the view:
{{ view.kwargs.card_type }}
{{ view.kwargs.role_line }}
{{ view.kwargs.sort_by }}
You can use dict.update():
update([other])
Update the dictionary with the key/value pairs from other, overwriting existing keys.
context.update(self.kwargs)
Related
Is it possible to iterate over a list of three context variables shown below so that depending on the user's attribute (in this instance grade, Grade 10, Grade 11, Grade 12). If current user's grade attribute is Grade 10 then they only get: context['grade10'] from below.
Current view:
class SumListView(ListView):
model = Summaries
template_name = 'exam/summary.html'
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['grade10'] = Summary.objects.filter(grade='Grade 10')
context['grade11'] = Summary.objects.filter(grade='Grade 11')
context['grade12'] = Summary.objects.filter(grade='Grade 12')
return context'''
Current html template block:
{% block content %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% endblock content %}
I tried this but it breaks the code since for loops and iterations are mixing:
{% block content %}
{% if grade10 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% elif grade11 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% else grade12 %}
{% for summary in grade10 %}
<div class="container>
{{ summary.content }}
</div>
{% endfor %}
{% enif %}
{% endblock content %}
What is the best way to go about this?
I know I can write different urls for each context which in turn renders a different template but that does not seem efficient and I hope there is a better way to do that. Any help highly appreciated, including documentation pointers.
You can perform this logic in your view, you can use a single context variable but change it's contents based on your logic
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
user_grade = self.request.user.get_grade() # Replace with how you access the user's grade
context['grades'] = Summary.objects.filter(grade=user_grade)
return context
Then loop over grades in your template
The title says everything. Two days ago the following code worked fine but now journeys is not set or empty or ...
def map(request, jid):
journeys = None
if request.user.is_authenticated:
journeys = Journey.objects.filter(user_id=request.user.id)
#some stuff
context = {
'jc': len(journeys), #only for testing
'journeys': journeys
}
return render(request, 'JourneyMap/map.html', context)
map.html extends base.html
Inside base.html:
<div class="dropdown-menu" aria-labelledby="dropdown05">
<p>{{ jc }}</p> <-- only for testing
{% for journey in journeys %}
{% if journey.user_id == user.user_id %}
{% if forloop.counter < 4 %}
<a class="dropdown-item"
href="{% url 'JourneyMap_journey' jid=journey.id %}">{{ journey.title }}</a>
{% endif %}
{% endif %}
{% endfor %}
</div>
Result:
It seems like journeys length is 1, so the variable is actually set.
I think that your user check fails here.
{% if journey.user_id == user.user_id %}
What is user.user_id here? Is user another variable that lives somewhere outside of the given context? Then probably it's not set.
Otherwise, if you want to check for current user's id, perhaps you should do:
{% if journey.user_id == request.user.id %}
I'm not sure if the question title is ok or need to be changed but my problem is this:
In views.py file:
def four(request):
mavared1 = PDivContent.objects.filter(chest='1', divv='1')
mavared2 = PDivContent.objects.filter(chest='1', divv='2')
return render(request, 'four.html', {'mavared1': mavared1, 'mavared2': mavared2})
And in four.html:
<div id="first">
{% for i in mavared1 %}
<li>{{ i.txt }}</li>
{% endfor %}
</div>
<div id="second">
{% for i in mavared2 %}
<li>{{ i.txt }}</li>
{% endfor %}
</div>
And the output of the code is something like this:
(for mavared1):
red
blue
black
pink
(for mavared2):
a
b
c
d
I have set mavared1 and mavared2 in my views.py function manually. Its ok for now that there is only 2, mavared1 and mavared2, but what if I have 50?!
Do I have to type like this: ??!!
mavared1 = PDivContent.objects.filter(chest='1', divv='1')
.
.
mavared50 = PDivContent.objects.filter(chest='1', divv='50')
Is there any other way?!
Of course not, you write loops and use data structures dict to do that:
def four(request):
divv = [str(i) for i in range(1, 51)]
marvared_dict = {}
for divv in divvs:
marvared_dict[divv] = PDivContent.objects.filter(chest='1', divv=divv)
return render(request, 'four.html', {'marvared_dict': marvared_dict})
four.html
{% for divv, marvareds in marvared_dict.items %}
<div id="{{ divv }}">
{% for i in mavareds %}
<li>{{ i.txt }}</li>
{% endfor %}
</div>
{% endfor %}
I am using Django 1.8 with Postgres 9.2 on a Windows 8 machine.
I have two pieces of nearly identical code from two of my projects. One works and the other doesn't.
Here's the code that works:
# views.py
from django.shortcuts import render
from models import Artist, Track
def music(request):
artists = Artist.objects.all().order_by('orderName')
artistTrackCollections = []
for artist in artists:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
artistTrackCollections.append(artist)
return render(request, 'music.html', {'artistTrackCollections': artistTrackCollections,})
And the relevant template code:
{% for artist in artistTrackCollections %}
<dl>
<dt>
{% if artist.website %}
<h2>{{ artist.name }}</h2>
{% else %}
<h2>{{ artist.name }}</h2>
{% endif %}
</dt>
<dd>
<ul>
{% for track in artist.tracks %}
<li>“{{ track.title }}”
<i>({{ track.album.title }})</i>
{% endfor %}
</ul>
</dd>
</dl>
{% endfor %}
Now here's pretty much the exact same code from a different project of mine that doesn't work anymore:
def index(request):
productList = PartModel.objects.filter(isBuild=True, isActive=True).order_by('name')
productCollection = []
for product in productList:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
productCollection.append(product)
return render(request, 'index.html', { 'productCollection': productCollection, })
and its corresponding template:
{% for product in productCollection %}
<p>{{ product.name }}
<p>${{ product.price }}
<ul>
{% for part in product.part_list %}
<li>{{ part.family.type.name }} | {{ part.name }}
{% endfor %}
</ul>
{% endfor %}
This code used to work but now it doesn't. In the code that works I succeed in going through each artist and attaching that artist's tracks. In the code that fails I try to go through each PartModel instance that is a build and get that PartModel instance's corresponding parts. They are identical as far as I can tell. productCollection gets populated but the part_list data for some reason is blank. This leads me to believe the problem is with this line:
product.part_list = product.buildpart.all().order_by('family__type')[:5]
But I cannot discern the difference from this line:
artist.tracks = Track.objects.filter(artist=artist).order_by('order')
Thanks in advance for any help!
I have a condition within a loop in my template like this:
{% for message in message_trash %}
<td><a href="#">
{% if request.session.user_email == message.message_user_reciever.user_email %}
{{ message.message_user_reciever.user_firstName }} {{ message.message_user_reciever.user_lastName }}
{% elif request.session.user_email == message.message_user_sender.user_email %}
{{ message.message_user_sender.user_firstName }} {{ message.message_user_sender.user_lastName }}
{% endif %}
</a><small>Friends</small></td>
{% endfor %}
but i don't know why i get this error when applying the url?
TemplateSyntaxError: Could not parse the remainder: '==message.message_user_reciever.user_email' from 'request.session.user_email==message.message_user_reciever.user_email'
Update:
this is the view and variables that i render to the template:
def trashMessages(request, userId):
if isMessageOwner(request, userId):
user = Users.objects.get(user_id=userId)
message_trash = Messages.objects.filter(Q(message_user_reciever= user, message_sender_type='TRASH') | Q(message_user_sender=user, message_reciever_type='TRASH'))
return render(request, 'navigation_messages.html', {'user': user, 'message_trash': message_trash, 'type': 'trash'})
On testing your code out, I can only replicate your issue is by swapping:
{% if request.session.user_email == message.message_user_reciever.user_email %}
for
{% if request.session.user_email ==message.message_user_reciever.user_email %}
Note the missing space. Is the snippet in your question exactly as it is in your template?