Code
engine.py ==>
class YearGroupCount():
def __init__(self, year, count, months):
self.year = year
self.count = count
self.months = months
class MonthGroupCount():
def __init__(self, month, count):
self.month = month
self.month_name = calendar.month_name[month]
self.count = count
class BlogCountsEngine():
def __init__(self):
self.year_group_counts = {}
def _add_date(self, year, month):
if str(year) in self.year_group_counts:
year_obj = self.year_group_counts[str(year)]
else:
year_obj = YearGroupCount(year, 0, {})
year_obj.count += 1
if str(month) in year_obj.months:
month_obj = year_obj.months[str(month)]
else:
month_obj = MonthGroupCount(month, 0)
month_obj.count += 1
year_obj.months[str(month)] = month_obj
self.year_group_counts[str(year)] = year_obj
def get_calculated_blog_count_list(self):
if not Blog.objects.count():
retval = {}
else:
for blog in Blog.objects.all().order_by('-posted'):
self._add_date(blog.posted.year, blog.posted.month)
retval = self.year_group_counts
return retval
views.py ==>
def outer_cover(request):
archives = BlogCountsEngine().get_calculated_blog_count_list()
retdict = {
'categories': Category.objects.all(),
'posts': posts,
'archives': archives,
}
return render_to_response('blog/blog_list.html', retdict, context_instance=RequestContext(request))
template html ==>
<div class="well">
<h4>Arşivler</h4>
<ul>
{% if archives %}
{% for y_key, yr in archives %}
<li>{{ yr.year }} ({{ yr.count }})</li>
{% for m_key,mth in yr.months %}
<li> - {{ mth.month_name }} ({{ mth.count }})</li>
{% endfor %}
{% endfor %}
{% endif %}
</ul>
</div>
Question:
I am building my own blog with django. I want to iterate in archives to show them in main page but i cannot reach instances' attributes in dictionary
When i run the code over in here the result html is ==>
<div class="well">
<h4>Arşivler</h4>
<ul>
<li> ()</li>
</ul>
</div>
What am i missing or doing wrong?
You can use dict.items method. In python 2.x better use dict.iteritems instead.
{% for y_key, yr in archives.items %}
<li>{{ yr.year }} ({{ yr.count }})</li>
{% for m_key, mth in yr.months.items %}
<li> - {{ mth.month_name }} ({{ mth.count }})</li>
{% endfor %}
{% endfor %}
Related
I have a questionnaire, containing many questions with their answers. My main objective is to create a webpage where I can show the details of a questionnaire with the list of rules (question/answer) and in the bottom of the page I want to call the create rule page:
def create_rule_view(request, id, sc_id):
if request.method == "POST":
input = InputForm(request.POST)
answer = AnswerForm(request.POST)
rule = RuleForm(request.POST)
if rule.is_valid() and input.is_valid() and answer.is_valid():
r = rule.save()
i = input.save(commit=False)
a = answer.save(commit=False)
i.rule_id = r
i.save()
a.rule_id = r
a.save()
question = input.cleaned_data["patterns"]
else:
input = InputForm()
answer = AnswerForm()
rule = RuleForm()
return render(request, "rule/create_rule.html", {
'rule': rule,
'input': input,
'answer': answer
})
def detail_scenario(request, id, sc_id):
object = get_object_or_404(Scenario, id=sc_id)
# TODO : add rule in the same view
create_rule_div = create_rule_view(request, id, sc_id)
print("content", create_rule_div)
context = {
'scenario': object,
'create_rule_div': create_rule_div
}
return render(request, "scenario/detail_scenario.html", context)
This is rule_create.html:
{% block content %}
<form method="POST"> {% csrf_token %}
<h2>Create Rule</h2>
{{ rule.name}}
{{ input.patterns }}
{{ answer.text }}
<input type="submit" value="Save Rule"/>
</form>
{% endblock %}
This is detail_senario.html:
{% block content %}
<h2>Scenario {{ scenario.id }}</h2>
<p>Scenario for : {{ scenario.chatbot_id }}</p>
<p>Name: {{ scenario.name }}</p>
<p>Description: {{ scenario.description }}</p>
<p>State: {{ scenario.state }}</p>
{% for rule in scenario.rule_ids.all %}
<li>{{ rule }}</li>
{% endfor %}
<div>{% block rule %}
{{ create_rule_div.content }}{% endblock %}
</div>
{% endblock %}
when I call url of detail_scenario I got an html code in navigator like this:
How can I fix this?
Thanks.
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'm trying to detect if the button is clicked and store the value of a retrieved info in session from def detail.
views.py:
def job_display(request):
job_list = Job.objects.filter(Publication_Status="A").order_by('- Job_Position')
context = {'job_list': job_list}
return render(request, 'frontend/jobs.html', context)
def detail(request, job_id):
jreq = get_object_or_404(Job, pk=job_id)
if request.POST.get(jreq.Job_Position):
request.session['jpos'] = jreq.Job_Position
return HttpResponseRedirect('apply')
return render(request, 'frontend/details.html', {'jreq': jreq})
template:
<h1>{{ jreq.Job_Position }}</h1>
<h2>{{ jreq.Job_Description }}</h2>
{{ jreq.Available_Slots }}
<ul>
{% for req in jreq.job_requirement_set.all %}
<li>{{ req.Job_Requirements }}</li>
{% endfor %}
<p> BLA BLA BLA <p/>
{% for req in jreq.skill_requirement_set.all %}
<li>{{ req.Skill_Requirements }}</li>
{% endfor %}
<input name="form-type " name = {{ jreq.Job_Position }} value={{ jreq.Job_Position }} type="submit"/>
In short, you need to put your <input> into a <form>. Without a form you cannot POST any data.
Sounds like you need to learn how a form works in web development. While it's hard to give you a concrete example, django original document is always your friend: https://docs.djangoproject.com/en/1.8/topics/forms/
I have successfully added pagination to a list_contacts view (obviously for a Contact model). And am now trying to setup the template context so that I can limit the pagination display to look like this :
< 1 ... 5 6 7 8 9 ... 42 >
I went from this answer and tried to use a "paginator" template tag, unsuccessfully. The main problem is that I'm using ListView instead of the old object_list, and these two don't set the context the same way.
Here's my view :
from django.views.generic import ListView
from app.models import Contact
list_contacts = ListView.as_view(
model=Contact,
http_method_names = ['get'],
template_name='contacts.html',
context_object_name='contacts',
paginate_by=6
)
And my template "contacts.html" :
<ul class="pagination">
{# Previous page link #}
{% if page_obj.has_previous %}
<li>
«
</li>
{% else %}
<li class="disabled">
«
</li>
{% endif %}
{# First page #}
{% if show_first %}
<li>
1
</li>
<li>...</li>
{% endif %}
{# List of pages (with current "active") #}
{% for page in page_numbers %}
{% ifequal page page_obj.number %}
<li class="active">
{{ page }}
</li>
{% else %}
<li>
{{ page }}
</li>
{% endifequal %}
{% endfor %}
{# Last page #}
{% if show_last %}
<li>...</li>
<li>{{ page_obj.pages }}</li>
{% endif %}
{# Next page link #}
{% if page_obj.has_next %}
<li>
»
</li>
{% else %}
<li class="disabled">
»
</li>
{% endif %}
</ul>
EDIT: here's my view code that ended up working
class ListContactsView(ListView):
model = Contact
http_method_names = ['get']
template_name = 'contacts.html'
context_object_name = 'contacts'
paginate_by = 6
def get_context_data(self, **kwargs):
_super = super(ListContactsView, self)
context = _super.get_context_data(**kwargs)
adjacent_pages = 2
page_number = context['page_obj'].number
num_pages = context['paginator'].num_pages
startPage = max(page_number - adjacent_pages, 1)
if startPage <= 3:
startPage = 1
endPage = page_number + adjacent_pages + 1
if endPage >= num_pages - 1:
endPage = num_pages + 1
page_numbers = [n for n in xrange(startPage, endPage) \
if n > 0 and n <= num_pages]
context.update({
'page_numbers': page_numbers,
'show_first': 1 not in page_numbers,
'show_last': num_pages not in page_numbers,
})
return context
list_contacts = ListContactsView.as_view()
There are different ways to achieve this (or even a combination of some):
Override or extend get_context_data by calling super
Write a templatetag
Write a template filter
Override or extend the PaginationMixin
An example of the first
class MyListView(ListView):
def get_context_data(self, **kwargs):
context = super(MyListView, self).get_context_data(**kwargs)
context['foo'] = 'bar'
return context
I'm having some trouble using get_absolute_url in a template. It seems to work fine if I just pass in one of my store objects and say {{ store.get_absolute_url }}, but if I have to iterate through a dictionary of stores and then use the get_absolute_url function, it returns nothing. Exactly what I'm doing is below:
class Store(EthicalObject):
type = "Store"
name = models.CharField(max_length=50)
company = models.ForeignKey(Company, verbose_name="Company", null=True, blank=True)
location = models.OneToOneField(Location, verbose_name="Location", null=True, blank=True)
products = models.ManyToManyField('Product', related_name="%(class)s_related", db_table=u'ethicsdb_products_to_stores', blank=True)
companies = models.ManyToManyField('Company', related_name="%(class)s_related", db_table=u'ethicsdb_companies_to_stores', blank=True)
def get_absolute_url(self):
return ('store_details', [str(self.id)])
get_absolute_url = models.permalink(get_absolute_url)
This works:
views.py:
def fetch_sidebar_data(shop_object):
sidebar_modules = {}
if shop_object.content_type.name == 'company':
sidebar_modules['related_stores'] = shop_object.stores.all()
sidebar_modules['related_products'] = shop_object.products.all()
if shop_object.content_type.name == 'store':
sidebar_modules['related_companies'] = shop_object.companies.all()
sidebar_modules['related_products'] = shop_object.products.all()
if shop_object.content_type.name == 'product':
sidebar_modules['related_stores'] = shop_object.stores.all()
sidebar_modules['related_companies'] = shop_object.companies.all()
sidebar_modules['tags'] = shop_object.tags
return sidebar_modules['related_stores'][1]
def company_details(request, company_id):
company = get_object_or_404(Company, id=company_id)
sidebar_modules = fetch_sidebar_data(company)
return render_to_response('company/details.html', {'company': company, 'sidebar_modules': sidebar_modules}, context_instance=RequestContext(request))
template:
{% extends "base-onecol.html" %}
{% block page_div_extra_attr %}class="twocol"{% endblock %}
{% block sidebar_content %}
<div id="sidebar-right">
<h1>{{ sidebar_modules.name }}{{sidebar_modules.get_absolute_url }}</h1>
</div>
{% endblock %}
This doesn't work:
views.py:
def fetch_sidebar_data(shop_object):
sidebar_modules = {}
if shop_object.content_type.name == 'company':
sidebar_modules['related_stores'] = shop_object.stores.all()
sidebar_modules['related_products'] = shop_object.products.all()
if shop_object.content_type.name == 'store':
sidebar_modules['related_companies'] = shop_object.companies.all()
sidebar_modules['related_products'] = shop_object.products.all()
if shop_object.content_type.name == 'product':
sidebar_modules['related_stores'] = shop_object.stores.all()
sidebar_modules['related_companies'] = shop_object.companies.all()
sidebar_modules['tags'] = shop_object.tags
return sidebar_modules
template:
{% extends "base-onecol.html" %}
{% block page_div_extra_attr %}class="twocol"{% endblock %}
{% block sidebar_content %}
<div id="sidebar-right">
{% for module_name,module in sidebar_modules.items %}
{% ifequal module_name "related_stores" %}
<h3>Sold Here</h3>
{% for related_store in module.values %}
{{ related_store.name }}<br/>
{% endfor %}
{% endifequal %}
{% ifequal module_name "related_products" %}
<h3>Buy Local</h3>
{{ module }}<br/>
{% endifequal %}
{% ifequal module_name "related_companies" %}
<h3>
{{ module }}<br/>
{% endifequal %}
{% ifequal module_name "tags" %}
{{ module }}<br/>
{% endifequal %}
{% endfor %}
</div>
{% endblock %}
In the second one, I just get no return from get_absolute_url. I know it's working in other places when I print it out. Is this a Django bug, the inability to use get_absolute_url in a dictionary of dictionaries?
Wow, that was a rather convoluted question.
Your problem is here: {% for related_store in module.values %}
module is a QuerySet. .values is calling the QuerySet method which returns a dictionary containing the field values for each row. A dictionary has no get_absolute_url attribute, and get_absolute_url isn't a field in the model.
Just use {% for related_store in module %} and you'll be dealing with actual model instances rather than dictionaries, which means {{ related_store.get_absolute_url }} will work fine.