I have been wrestling with something that I think is a bonehead oversight on my part. I have a form that feeds an input to a view that queries some SQL tables I have and returns a list back with columns from each table**.
The odd thing that is happening is the my list is appearing with
<QuerySet{[ ]}>
brackets around each list object. Can anyone tell me how to avoid this?
Much appreciated.
**I am using this list to combine these tables rather than ForeignKeys because I was having a terrible time getting my SQL databases to populate correctly using SQLAlchemy and Postgres and read that there were known issues with that, so I gave up on that method.
views.py
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse, Http404
from django.views import generic
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django.urls import reverse_lazy
from .models import *
from .forms import QuoteForm, RfqForm
def bom_result(request):
if request.method == 'POST':
form = RfqForm(request.POST)
if form.is_valid():
bom_list = []
rfq = {}
rfq_search = form.cleaned_data['rfq_entered']
rfq['rfq_num'] = rfq_search
rfq['bom'] = Quotereq.objects.values('bom_entered').filter(rfq_num__exact=rfq_search)
rfq['part_num'] = Bom.objects.values('partnum').filter(bom__exact='07-00-000019')
bom_list.append(rfq)
context = {'bom_list': bom_list}
return render(request, 'quote/result.html', context)
else:
return HttpResponse("<h1>Something Went Wrong</h1>")
else:
form = RfqForm()
context = {'form': form}
return render(request, 'quote/lookup.html', context)
result.html
{% extends "base.html" %}
{% load static %}
{% block title %}{{title}}{% endblock title %}
{% block sidenav %}
{% for page in page_list %}
<li>
{{page.title}}
</li>
{% endfor %}
{% endblock sidenav %}
{% block content %}
{% autoescape off %}
{{ content }}
{% endautoescape %}
{% if bom_list %}
{% for bom in bom_list %}
<table>
<tr>
<th><h1>RFQ Number</h1></th>
<th><h1>BOM</h1></th>
</tr>
<tr>
<td>
<ul style="list-style-type:none">
<li>{{ bom.rfq_num }}</li>
</ul>
</td>
<td>
<ul style="list-style-type:none">
<li>{{ bom.bom }}</li>
</ul>
</td>
<td>
<ul style="list-style-type:none">
<li>{{ bom.part_num }}</li>
</ul>
</td>
</tr>
</table>
{% endfor %}
{% else %}
<p>No Matching RFQ in Database</p>
{% endif %}
{% endblock content %}
Here is what the table outputs:
If we look at what part_num is, we see:
rfq['part_num'] = Bom.objects.values('partnum').filter(bom__exact='07-00-000019')
This is a QuerySet, a QuerySet is some sort of query that results in a set of objects. You construct such QuerySets by using the Django ORM (what you do here).
In order to obtain the elements in the QuerySet, you can iterate over the elements, and for example individually process these.
In the template we can for example write:
<td>
<ul style="list-style-type:none">
<li>{% for part in bom.part_num %} {{ part.part_num }} {% endfor %}</li>
</ul>
</td>
So we iterate over the QuerySet, we then each time obtain a dictionary (that was wrapped in the QuerySet, and we render the value that corresponds to the 'part_num' key in the dictionary. Of course we can make it more sophisticated (for example use HTML markup directives, like {% for part in bom.part_num %} <b>{{ part.part_num }}</b> {% endfor %} to put it in boldface.
I am using this list to combine these tables rather than ForeignKeys because I was having a terrible time getting my SQL databases to populate correctly using SQLAlchemy and Postgres and read that there were known issues with that, so I gave up on that method.
I would really advice to use ForeignKeys, ManyToManyFields, etc. to represent relations between entities. Not only will Django allow you to make more expressive queries, it also will add constraints to the database such that columns that correspond to a ForeignKey will always point to the primary key of the table where they point at, etc. In case you for example remove a referred entity, you can define triggers what to do (remove related objects, set the foreign key columnn to NULL, etc.). Perhaps following the Django tutorial can provide some required information to proceed.
Of course you are free to design and implement the project in the way you like, but my personal experience is that it will probably in the end result in more trouble.
Related
I am making kind of dynamic menu. when you click menu on the top, it show sub menu on the left side. I searched with keyword 'dynamic menu' from stackoverflow and google. I got idea to build that kind of menu. I made it like below.
1) render data(menu list) in context to template by custom context processor.
2) using custom template tag which is provided by django-mptt package.
3) show top menu in base template.
4) move to another template to show sub menu according to what top menu you click
I made custom context_processor to use menu in context in every template.
context_processor.py
from manager.models import Menu
def menu(request):
menu_list = list(Menu.objects.all())
return {'menu':menu_list}
template.py(example)
{% load mptt_tags %}
<nav id="{{ menu_id }}" class="tree-menu">
<ul>
{% recursetree menu %}
<li class="menu
{% if node.is_root_node %}root{% endif %}
{% if node.is_child_node %}child{% endif %}
{% if node.is_leaf_node %}leaf{% endif %}
{% if current_menu in node.get_descendants %}open{% else %}closed{% endif %}
">
{{ node.menu_name }}
{% if not node.is_leaf_node %}
<ul class="children">
{{ children }}
</ul>
{% endif %}
{% if node.items and node.items.exists %}
<ul class="items">
{% for item in node.items.all %}
{% if item_template %}
{% include item_template %}
{% else %}
{% include "menu/tree-item.html" %}
{% endif %}
{% endfor %}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
</nav>
mptt_tags.py
#register.tag
def recursetree(parser, token):
"""
Iterates over the nodes in the tree, and renders the contained block for each node.
This tag will recursively render children into the template variable {{ children }}.
Only one database query is required (children are cached for the whole tree)
Usage:
<ul>
{% recursetree nodes %}
<li>
{{ node.name }}
{% if not node.is_leaf_node %}
<ul>
{{ children }}
</ul>
{% endif %}
</li>
{% endrecursetree %}
</ul>
"""
bits = token.contents.split()
if len(bits) != 2:
raise template.TemplateSyntaxError(_('%s tag requires a queryset') % bits[0])
queryset_var = template.Variable(bits[1])
template_nodes = parser.parse(('endrecursetree',))
parser.delete_first_token()
return RecurseTreeNode(template_nodes, queryset_var)
My Question
If you see django manual about QuerySet, it says that "Each QuerySet contains a cache to minimize database access". It is obvious that, if you query same data in certain rule, it doesn't seem hit database again but return result from cache. Then I am querying Menu.objects.all() in custom context processor. This result(menu_list = Menu.objects.all()) will be in context every time, you can use menu data on every template repeately. So does it reuse the result from cache without hitting database again?
If menu_list = Menu.objects.all() in custom context processor hit database every time whenever template load this menu list, Does it work in this way to reuse menu data from cache without hitting database everytime?
context_processors.py
from manager.models import Menu
from django.core.cache import cache
def menu(request):
menu_list = cache.get_or_set('menu_list', list(Menu.objects.all()))
return {'menu':menu_list, 'redis':"Food"}
Lastly, I don't know if there are many people using django-mptt package. I guess just a few people have experience using it in person. It says "Only one database query is required (children are cached for the whole tree)" so does it mean if I use django-mptt package and get menu from it on template, it automatically cache its data?
Well, I am not clear about django cache system.
It would be really appreciate if you can give me answer and insight for my questions. Thanks for reading!
I'm trying to access a queryset array that I passed from the views in the templates. I want to index each entry using a numeric iterator. I'm using a django snippet to get the range of customers. Here is what I have done so far:
{% for cust in customer_comments %}
{% for i in cust|length|get_range %}
<tr>
<td>{{cust.i.customer_id}}</td>
<td>{{cust.i.feedback_detail}}</td>
</tr>
{% endfor %}
{% endfor %}
When I iterate using cust.i.customer_id it displays nothing. But when I use cust.0.customer_id or cust.1.customer_id, it displays what I want it to. Kindly help why i is not working.
Btw this is how I initialized the customer_comments object in views.
customer_comments = []
for i in all_features:
if OpenFeedback.objects.filter(feature_id = i.feature_id).exists():
feedback_obj = OpenFeedback.objects.filter(feature_id = i.feature_id)
customer_comments.append(feedback_obj)
You don't iterate like that in Python or in Django templates: you iterate through the list itself.
{% for customer in cust %}
<tr>
<td>{{customer.customer_id}}</td>
<td>{{customer.feedback_detail}}</td>
</tr>
{% endfor %}
I am currently writing a django app around a rather complex data model.
For many use cases, I need to build similar, but slightly differing templates (incl. graphviz etc..).
Now I wonder if there is a way to follow DRY and create the templates "on the fly", e.g. based on a nested tuple (of which one gets defined per use-case -> template).
Practically speaking I'd like to stop writing these:
static_template_case1.html
{% if program %}
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
{% endif %}
and replace it with something in the following direction:
template_generator.py
structure_case1 = ("program"("process"("step","control")))
def onTheFlyTemplate(structure):
# iterate through structure
# build template dynamically
# return template
onTheFlyTemplate(structure_case1)
I was not able to find something similar and also don't know yet where to start generating templates on the fly, nor how to integrate it.
Within the views feels like a good starting point, (instead of loader.get_template('static_template_case1.html')).
Thanks for any hint sending me into the right direction as well as your thoughts if DRY is being "overdone" here.
Ralph
Edit
I got a step closer, doing the following:
In the view:
from django.template import Template
def templateGen():
return Template("Program: {{program.count}}")
#login_required
def test(request):
program = Program.objects.all()
t = templateGen()
c = RequestContext(request,locals())
return HttpResponse(t.render(c))
So far this is only a proof of concept. The real work will be to write a smart "templateGen()" listening to the nested tuple.
How about an inclusion tag?
#register.inclusion_tag('<your-template.html>')
def get_program(program_id):
return {'program': <some logic to return your Program object>}
Your main template:
{%load my-template-tags%}
<div id="my-div">
{%get_program program_id %}
</div>
And your template file:
{{ program.name }}
{% for process in program.process_set.all %}
{{ process.name }}
{% for step in process.step_set.all %}
{{ step.name }}
{% endfor %}
{% for control in process.control_set.all %}
{{ control.name }}
{% endfor %}
{% endfor %}
You'd have to pass in your program_id to the main template.
I have a newsletter application where a newsletter has multiple articles within each issue. I want to display a summary page online that lists the newsletter year, volume and label, and then in an unordered list display all the articles in the issue. I am quite new to Django so I am trying to determine the best way to do this.
I have the models defined (just the relevant parts):
Models.py:
class Newsletter(models.Model):
volume = models.ForeignKey(Volume)
year = models.IntegerField()
season = models.CharField(max_length=6, choices=VOLUME_SEASON)
label = models.CharField(max_length=20)
number = models.IntegerField()
class Article(models.Model):
newsletter = models.ForeignKey(Newsletter)
section = models.ForeignKey(Section)
title = models.CharField(max_length=200)
What I want to see on the web looks like:
<h2>Spring 2012</h2>
<p>Volume 14, Number 1</p>
<ul>
<li>Foo</li>
<li>Bar</li>
<li>Baz</li>
</ul>
<h2>Winter 2011</h2>
<p>Volume 13, Number 4</p>
<ul>
<li>Boffo</li>
</ul>
Pretty simple. However, I am confused by the best way to write my view. Whether to use:
Two lists which I zip() and then iterate over in the template
Use the select_related() queryset
Use the prefetch_related() queryset
I have it working using the first option:
Views.py:
from django.shortcuts import render_to_response, get_object_or_404
from www.apps.newsletter.models import Newsletter, Article
def index(request):
article_group = []
newsletter = Newsletter.objects.all().order_by('-year', '-number')
for n in newsletter:
article_group.append(n.article_set.all())
articles_per_newsletter = zip(newsletter, article_group)
return render_to_response('newsletter/newsletter_list.html',
{'newsletter_list': articles_per_newsletter})
And then render it using the following template:
Newsletter_list.html:
{% block content %}
{% for newsletter, articles in newsletter_list %}
<h2>{{ newsletter.label }}</h2>
<p>Volume {{ newsletter.volume }}, Number {{ newsletter.number }}</p>
<p>{{ newsletter.article }}</p>
<ul>
{% for a in articles %}
<li>{{ a.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
Pretty straightforward, but as I am pretty new to Django I was wondering if what I am doing is completely inefficient in terms of its powerful ORM. I would love to not have to make a list on-the-fly and then zip() the two lists together if there is a faster way.
TIA.
The approach you are doing now will be heavily inefficient, because it will result in an 1+N number of queries. That is, 1 for the query of all your Newsletters, and then 1 for every single time you evaluate those n.article_set.all() results. So if you have 100 Newletter objects in that first query, you will be doing 101 queries.
This is an excellent reason to use prefetch_related. It will only result in 2 queries. One to get the Newsletters, and 1 to batch get the related Articles. Though you are still perfectly able to keep doing the zip to organize them, they will already be cached, so really you can just pass the query directly to the template and loop on that. :
view
newsletters = Newsletter.objects.prefetch_related('article_set').all()\
.order_by('-year', '-number')
return render_to_response('newsletter/newsletter_list.html',
{'newsletter_list': newsletters})
template
{% block content %}
{% for newsletter in newsletter_list %}
<h2>{{ newsletter.label }}</h2>
<p>Volume {{ newsletter.volume }}, Number {{ newsletter.number }}</p>
<p>{{ newsletter.article }}</p>
<ul>
{% for a in newsletter.article_set.all %}
<li>{{ a.title }}</li>
{% endfor %}
</ul>
{% endfor %}
{% endblock %}
I'm trying to display an HTML table of values with about 20 columns where say staff users see one subset of columns, and non-staff users see another subset of columns. I may want to define further types of users later. Now right now I have three static header rows so the template looks like
<table>
<tr>
<th>Col A</th>
{% if user.is_staff %}<th>Col B</th>{% endif %}
...
{% if not user.is_staff %}<th>Col K</th>{% endif %}
</tr>
<tr>
<td>Col A second header</td>
{% if user.is_staff %}<td>Col B second header</td>{% endif %}
...
{% if not user.is_staff %}<td>Col K second header</td>{% endif %}</tr>
<tr><td>Col A third header</td> ... </tr>
{% for obj in object_list %}
<tr>
<td>{{ obj.col_a }}</td>
{% if user.is_staff %}<td>{{ obj.col_b }}</td>{% endif %}
...
{% if not user.is_staff %}<td>{{ obj.col_k }}</td>{% endif %}
</tr>
{% endfor %}</table>
However, I find non-DRY as every time, if I want to change if a user-type can see a column, I have to change it in 4 places. Or if I want to define multiple different classes of users, I'd have to have complicated if statements. I'd prefer something like
{% if show_col_a %}<td>{{obj.col_a }}</td>{{% endif %}
Where I can define at the top of the template (or possibly in the view) that user.is_staff can see show_col_a. Is something like this possible? I'm using a generic view (object_list). Maybe modify all users to have attributes user.show_col_a somehow and do {% if user.show_col_a %}? I'm not sure how to add boolean attributes to users.
EDIT: May want multiple users with custom views (e.g., staff_view; admin_view, unprivileged, etc.), so if statements would get unwieldy. A cell's contents is typically more complicated than {{ obj.col_b }}; tried simplifying problem to get to the point. E.g.:
<td>{% if obj.custom_address %}
{{ obj.custom_address.webprint|safe }}
{% else %}
{{ obj.business.address.webprint|safe }}
{% endif %}</td>
Also while multiple templates would work with a simple switch like:
{% if user.is_staff %}
{% include "template_staff.html" %}
{% else %}{% if user.is_admin %}
{% include "template_admin.html" %}
{% else %}
{% include "template_other.html" %}
{% endif %}
{% endif %}
I find its not DRY at all; e.g., every edit to a template has to be replicated in three template. I guess I could make a script that read generates the three templates from some super_template outside of django but its getting very inelegant.
This depends a lot on what view you have and templates.
Ways to do:
make a public template and staff template and add a simple method to change the templates on the fly for the views.
make a template tag:
{% is_staff myvar %}
tag code:
class IsStaffNode(Node):
def __init__(self, var):
self.var = var
def render(self, context):
if context['user'].is_staff():
return var.resolve(context)
return ""
#register.tag
def is_staff(parser, token):
var = parser.compile_filter(token.split_contents()[1])
return IsStaffNode(var)
Homework: make it a block tag to include the td's so that it's shown either all or none.
{% isstaff myvar %}<td>{{ myvar }}</td>{% endisstaff %}
This way is more labor intensive than 2 different templates, but if you want to try, manipulating the context (or creating a separate context for the block only) might be useful.
Make a context processor that would fill the context with some variables if the user is staff, or not if not.
Make a tag that would include the template (inherit from IncludeNode) and manipulate the context.