I'm new in django, I would like to display my view.py to index.html,
the view.py:
def index(request):
context_dict = {}
customers = Customer.objects.all()
carts = Cart.objects.select_related('customer')
goods = Good.objects.select_related('cart__customer')
context_dict['Cart']=carts
context_dict['Good']=goods
context_dict['Customer'] = customers
return render(request, 'index.html', context=context_dict)
and the index.html for loop is like this:
<ul>
{% for customer in Customer %}
<li>{{ customer.name }}</li>
{% for cart in Cart %}
{% if customer.id == cart.id %}
{% for good in Good %}
{% if cart.id == good.id %}
{{good.name}}--{{good.count}}--{{good.price}}
{% endif %}
{% endfor %}
{% endif %}
{% endfor %}
{% endfor %}
</ul>
but the result displayed like this:
Bob should have water--2--50 under it.
it seems customer.id == cart.id cannot match.
but I don't know how to fix it.
please help, thanks a lot!
customer.id should match card.customer_id and so on (cart.good_id == good.id)
if you have a single cart with a single good in it your solution will still return all of the customers, all of the goods to show a single line on the page - this is not really a good solution.
So try using joins and retrieve only needed data, e.g.:
actual_carts = Cart.objects.all().select_related('customer', 'good').order_by('customer_id', )
This will return only customers and goods mentioned in carts. select_related will let you access all the needed info from customers as well as from goods.
Related
I have a QuerySet with several entries order.order_items.all. I want to check in my template if any of these items in my list contain the foreign_key discount. After one is found, I want to display that a discount_code was used for the order. How would you solve this?
Example:
<QuerySet [OrderItem: #k9ukvrfvjk - 1x Test Ticket 1, OrderItem: #k9ukvrfvjk - 1x Test Ticket 2]>
Rather than doing it in Template, I think its better to do it in the view. For example:
context['discount'] = order.order_items.filter(discount_id=<discount_id>).exists()
return render(request, 'template', context=context)
and in template:
{% if discount %}
// discounted related codes
{% endif %}
Update
Maybe you can get it simply by:
{% item in order.order_items.all %}
{% if item.discount %}
{{ item.discount.discount_code }}
{% endif %}
{% endfor %}
I'm working on a Django web app and have the following query:
I have a model called 'AppQoSList' which lists the applications available to all users.
I have then another model called 'BasicAppSDWANProfiles' which has a ManyToMany relationship with 'AppQoSList' .
In short, it means a user can have multiple 'BasicAppSDWANProfiles' associated to his account and multiple AppQoS can be within a particular BasicAppSDWANProfiles:
class AppQoSList(models.Model):
app_qos_name = models.CharField(max_length=50, blank=None, null=True)
app_qos_description = models.CharField(max_length=500)
def __str__(self):
return u'%s' % self.app_qos_name
class BasicAppSDWANProfiles(models.Model):
profile_name = models.CharField(max_length=30)
profile_basic_app_qos = models.ManyToManyField(AppQoSList)
tenant_id = models.ForeignKey(Tenant, default=3)
I'm facing issue in my template when I try to display the list of apps available and the associated BasicAppSDWANProfile:
{% for app in apps %}
{% for profile_app in sdwan_prof %}
{% for specific_app in profile_app.profile_basic_app_qos.all %}
{% ifchanged specific_app.pk %}
{% if app.pk == specific_app.pk %}
<td><h4><span class="label label-primary">{{ profile_app.profile_name }}</span></h4></td>
{% else %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
{% endifchanged %}
{% endfor %}
{% endfor %}
{% endfor %}
Issue with this code is that 'Not Assigned' is displayed 6 times on each row (which corresponds to the number of Apps found in BasicAppSDWANProfiles associated with this user) whereas I would like to display it only once:
Would you have any solution for this ?
Thanks in advance.
I was able to address this issue.
First I did clean up my view code to remove duplicate 'Not Assigned' values.
I pass to my template context a dictionary with only apps that have a profile assigned such as below:
{'citrix-static': 'DPS-BLACKLIST',
'exchange': 'DPS-BLACKLIST',
'ms-lync-audio': 'DPS-WHITELIST',
'ms-update': 'DPS-GREYLIST',
'rtp': 'DPS-WHITELIST',
'share-point': 'DPS-WHITELIST'}
In my template, I only loop through this dictionary:
{% for k,v in app_prof_assign.items %}
{% if app.app_qos_name == k %}
<td><h4><span class="label label-primary">{{ v }}</span></h4></td>
{% endif %}
{% endfor %}
I then simply check if the app is not in the profile dictionary, outside the loop:
{% if app.app_qos_name not in app_prof_assign %}
<td><h4><span class="label label-warning">Not Assigned</span></h4></td>
{% endif %}
Finally, I can get the table populated as expected:
I have a recurring problem that I can't seem to solve adequately. My site is akin to a job site, where people can post jobs (and details within), and other people can bookmark tthem. Each job can obviously be bookmarked by more than one viewer.
So here's the model.py:
class Job(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
title = models.CharField(max_length=150)
description = models.CharField(max_length=5000)
class Bookmark(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
job = models.ForeignKey(Job, on_delete=models.CASCADE)
My intention is to display all jobs in the homepage, that means multiple jobs from multiple users. Other users can click on a little bookmark icon to bookmark it, or to unbookmark it. Like so:
Here's the view.py:
def index(request):
context = {}
populateContext(request, context)
jobs = Job.objects.all().order_by('-id')
context = {'jobs': jobs}
return render(request, 'templates/index.html', context)
Pretty simple I think, which is my intention. Here's how the template looks:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}
</div>
{% endfor %}
My question is, how do I display the bookmark state specific to each user? Here's my current solution:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}<br>
{% for watch in job.bookmark_set.all %}
{% if watch.user_id = request.user.id %}
You have bookmarked this! <a>Unbookmark!</a>
{% endif %}
{% endfor %}
<a>Bookmark</a>
</div>
{% endfor %}
The "Unbookmark!" link will be positioned over the "Bookmark" link by the way. The solution above works that way, because the bookmark table will contain zero or more bookmarks for a particular job, but under multiple users. I would handle this in the view.py, by filtering just jobs that the logged-in user has made. But I can't filter by which job specifically, because the index.html will be displaying them all. So for example, I could spit this out...:
bookmarked = Bookmark.objects.all().filter(user_id=request.user.id)
...and that would list out all bookmarks on different jobs that the logged-in user had made. I still need to filter that in the template, so that each project matches with each bookmark, and I understand this isn't possible.
Anyway, I think this is pretty inefficient. So I was wondering if there was an easier way to handle this? Preferably so that it works this way:
{% for job in jobs %}
<div>
{{ job.title }}<br>
{{ job.description }}<br>
by {{ job.user.username }}<br>
{% if job.id = bookmark.job.id %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
Thank you!
You can use conditional expressions to annotate your jobs with this information. In the view:
from django.db.models import Case, IntegerField, Sum, When
jobs = Job.objects.annotate(
is_bookmarked=Sum(Case(
When(bookmark__user=request.user, then=1),
default=0, output_field=IntegerField()
))).order_by('-id')
Each job now has an is_bookmarked property which is either 1 (the user has bookmarked the job) or 0. In your template:
{% for job in jobs %}
<div>
{% if job.is_bookmarked %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
Just for completeness, the other approach you had in mind would also work (although less efficient than the one above). In the view:
jobs = Job.objects.all().order_by('-id')
# Get a list of all Job IDs bookmarked by this user
user_bookmarks = Bookmark.objects.filter(user_id=request.user.id)\
.values_list('job__id', flat=True)
In the template:
{% for job in jobs %}
<div>
{% if job.id in user_bookmarks %}
You have bookmarked this! <a>Unbookmark!</a>
{% else %}
<a>Bookmark</a>
{% endif %}
</div>
{% endfor %}
Both these approaches are doing pretty much the same logic - the difference being that the first one does this at database level which is generally more efficient.
so i have a model which is,
class Category(SmartModel):
item=models.ManyToManyField(Item)
title=models.CharField(max_length=64,help_text="Title of category e.g BreakFast")
description=models.CharField(max_length=64,help_text="Describe the category e.g the items included in the category")
#show_description=check box if description should be displayed
#active=check box if category is still avialable
display_order=models.IntegerField(default=0)
def __unicode__(self):
return "%s %s %s %s " % (self.item,self.title, self.description, self.display_order)
and as you may see, it has a manytomany field
item=models.ManyToManyField(Item)
i want to return all the items in a template, here is my views.py for this
def menu(request):
categorys= Category.objects.all()
items= categorys.all().prefetch_related('item')
context={
'items':items,
'categorys':categorys
}
return render_to_response('menu.html',context,context_instance=RequestContext(request))
here is how am doing it in the templates,
<ul>
{% for item in items %}
<li>{{ item.item }}
</li>
</ul>
{% endfor %}
after all this,this is what it is returning in my web page,
<django.db.models.fields.related.ManyRelatedManager object at 0xa298b0c>
what am i doing wrong,I have really looked around but all in vain, hoping you can help me out and thanking you in advance
Exactly, you have a many to many manager. You need to actually query something... like all()
{% for item in items %}
{% for i in item.item.all %}
{{ i }}
{% endfor %}
{% endfor %}
Based on your variable naming, I think you're confusing the results of prefetch_related as a bunch of items. It is in fact returning a QuerySet of Category objects.
So it would be more intuitive to call them categories.
{% for category in categories %}
{% for item in category.item.all %}
{{ item }} {# ...etc #}
Try to use:
categorys= Category.objects.prefetch_related('item').all()
And then in template:
{% for category in categorys %}
{% for item in category.item.all %}
{{ item }}
{% endfor %}
{% endfor %}
I have two basic models, Story and Category:
class Category(models.Model):
title = models.CharField(max_length=50)
slug = models.SlugField()
...
class Story(models.Model):
headline = models.CharField(max_length=50)
slug = models.SlugField()
categories = models.ManyToManyField(Category)
...
And my view for story detail:
from django.views.generic import date_based, list_detail
from solo.apps.news.models import Story
def story_detail(request, slug, year, month, day):
"""
Displays story detail. If user is superuser, view will display
unpublished story detail for previewing purposes.
"""
stories = None
if request.user.is_superuser:
stories = Story.objects.all()
else:
stories = Story.objects.live()
return date_based.object_detail(
request,
year=year,
month=month,
day=day,
date_field='pub_date',
slug=slug,
queryset=stories,
template_object_name = 'story',
)
On the view for a given story object -- I'm using a generic detail view -- I'd like to display a list of stories related to the current story via the categories applied to the current story.
Here's how I'm doing this currently in the story detail template:
{% for category in story.category.all %}
<ul id="related_stories">
{% for story in category.story_set.all|slice:"5" %}
<li>{{ story.headline }}</li>
{% endfor %}
</ul>
{% endfor %}
This provides me what I need except I'd like to avoid displaying the linked headline for the story I'm viewing currently.
I believe this is done via the "exclude" filter, but I'm not sure if this belongs on the Category or Story model as a method, or how to construct it.
Any help would be appreciated!
Do this:
class Story(models.Model):
...
#property
def related_story_set(self):
category_id_list = self.category.values_list("id", flat=True)
return Story.objects.filter(category__id__in=category_id_list).exclude(id=self.id)
Then you can do this in the template:
<ul id="related_stories">
{% for related_story in story.related_story_set.all|slice:"5" %}
<li>{{ related_story.headline }}</li>
{% endfor %}
</ul>
You could just check in the template if the currently iterated story is the original story:
{% for category in story.category.all %}
<ul id="related_stories">
{% for substory in category.story_set.all|slice:"5" %}
{% if substory != story %}
<li>{{ story.headline }}</li>
{% endif %}
{% endfor %}
</ul>
{% endfor %}
You asked to put it in a model method:
class Story(models.Model):
...
def get_categories_with_stories(self):
categories = self.category.all()
for category in categories:
category.stories = category.story_set.exclude(id=self.id)[:5]
return categories
This doesn't solve your expensive query issue, but that wasn't a part of the question.
{% for category in story.get_categories_with_stories %}
<ul id="related_stories">
{% for substory in category.stories %}
<li>{{ story.headline }}</li>
{% endfor %}
</ul>
{% endfor %}