I want to do two things at once:
Display the attributes of a class in its docstring, so that, for example, it will available in a Jupyter notebook when I hit Shift + Tab + Tab.
However, in the Sphinx output, the docs generated with the .. autoclass:: directive contain the attributes section, which takes up a lot of real estate and I do not want it to be there.
So let's say I have a class as follows:
class TestClass:
"""
This is a brief summary.
Here are a few more sentences. Probably more than two.
Attributes
----------
a1 : Any
This is the first attribute, I do not want to see it here.
a2 : TestClass
Oh look a recursive class
"""
def __init__(self, a1, a2):
"""
Initialize self
Parameters
----------
a1 : Any
The first attribute.
a2 : TestClass
The second attribute.
"""
self._a1 = a1
self._a2 = a2
#property
def a1(self):
"""
The first attribute, I want to see it here.
Returns
-------
Any
The first attribute
"""
return self._a1
#property
def a2(self):
"""
The second attribute.
Returns
-------
TestClass
The second attribute
"""
return self._a2
I also have a class documentation template, with the following content:
{{ objname | escape | underline }}
.. currentmodule:: {{ module }}
.. autoclass:: {{ objname }}
{% block attributes %}
{% if attributes %}
.. rubric:: {{ _('Attributes') }}
.. autosummary::
{% for item in attributes %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
{% block methods %}
{% if methods %}
.. rubric:: {{ _('Methods') }}
.. autosummary::
{% for item in methods %}
~{{ name }}.{{ item }}
{%- endfor %}
{% endif %}
{% endblock %}
{% if attributes %}
.. rubric:: {{ _('Attribute details') }}
{% for item in attributes %}
.. autoattribute:: {{ name }}.{{ item }}
{% endfor %}
{% endif %}
{% if methods %}
.. rubric:: {{ _('Method details') }}
{% for item in methods %}
.. automethod:: {{ name }}.{{ item }}
{% endfor %}
{% endif %}
which finally results in docs which look like this:
I am looking for a solution which would
retain the attribute list, or some information about the attributes, in the docstring, and
omit this information in the docs.
I am OK with trying unorthodox solutions, but I cannot find any good guides on how to use Sphinx (ironically, the Sphinx docs don't help much). However, I need high levels of automation for the docs, which is why I would like a solution which uses a template, similar to what I pasted above.
Related
I have a python dictionary:
settings = {
"foo" : "baz",
"hello" : "world"
}
This variable settings is then available in the Jinja2 template.
I want to check if a key myProperty exists in the settings dict within my template, and if so take some action:
{% if settings.hasKey(myProperty) %}
takeSomeAction();
{% endif %}
What is the equivalent of hasKey that I can use?
Like Mihai and karelv have noted, this works:
{% if 'blabla' in item %}
...
{% endif %}
I get a 'dict object' has no attribute 'blabla' if I use {% if item.blabla %} and item does not contain a blabla key
You can test for key definition this way:
{% if settings.property is defined %}
#...
{% endif %}
This works fine doesn't work in cases involving dictionaries. In those cases, please see the answer by tshalif.
Otherwise, with SaltStack (for example), you will get this error:
Unable to manage file: Jinja variable 'dict object' has no attribute '[attributeName]'
if you use this approach:
{% if settings.myProperty %}
note:
Will also skip, if settings.myProperty exists, but is evaluated as False (e.g. settings.myProperty = 0).
Actually, in the style of Python, if you do a simple if statement, it will work:
{% if settings.foo %}
Setting Foo: {{ settings.foo }}
{% endif %}
{% if settings.bar %}
Setting Bar: {{ settings.bar }}
{% endif %}
{% if settings.hello %}
Setting Hello: {{ settings.hello }}
{% endif %}
Output:
Setting Foo: baz
Setting Hello: world
Cheers!
I am making some generic templates for my projects like the message template given below.
{% extends base_name %}
{% block main-contents %}
<h2>{{ message_heading }}</h2>
<div class="alert alert-{{ box_color|default:"info" }}">
{{ message }}
{% if btn_1_text and btn_1_url %}
{{ btn_1_text }}
{% endif %}
{% if btn_2_text and btn_2_url %}
{{ btn_2_text }}
{% endif %}
</div>
{% endblock %}
I can set the name of the base template through template variables. My question is whether there is a method to set the name of the block using template variables. Usually I use the block name main-contents for almost all of my project. But that is not granted for all the projects. If this is not possible using template is there a way to rename the block using python code ?
I found a hack. I dont know if this has any after effects. Can any one verify this ?
def change_block_names(template, change_dict):
"""
This function will rename the blocks in the template from the
dictionary. The keys in th change dict will be replaced with
the corresponding values. This will rename the blocks in the
extended templates only.
"""
extend_nodes = template.nodelist.get_nodes_by_type(ExtendsNode)
if len(extend_nodes) == 0:
return
extend_node = extend_nodes[0]
blocks = extend_node.blocks
for name, new_name in change_dict.items():
if blocks.has_key(name):
block_node = blocks[name]
block_node.name = new_name
blocks[new_name] = block_node
del blocks[name]
tmpl_name = 'django-helpers/twitter-bootstrap/message.html'
tmpl1 = loader.get_template(tmpl_name)
change_block_names(tmpl1, {'main-contents': 'new-main-contents})
This seems to work for now. I want to know if this method has any after effects or other issues.
After fiddling with wtforms, fields use widgets to actually render them to html. I wrote some custom field/widget to draw html in a way that I'd more like to. But here's a question:
suppose I want to render them with pre-defined css class or give actual details myself.
How can I achieve this? and on what phase of handling requests(at Form class declaration? or when setting attributes to give Form some Fields? or when I'm actually calling them in jinja2 templates) I should do that?
I use a Jinja macro something like this:
{% macro field_with_errors(field) %}
{% set css_class=kwargs.pop('class', '') %}
{% if field.type in ('DateField', 'DateTimeField') %}
{{ field(class='date ' + css_class, **kwargs) }}
{% elif field.type == 'IntegerField' %}
{{ field(class='number ' + css_class, **kwargs) }}
{% else %}
{{ field(class=css_class, **kwargs) }}
{% endif %}
{% if field.errors %}
<ul class="errors">{% for error in field.errors %}<li>{{ error|e }}</li>{% endfor %}</ul>
{% endif %}
{% endmacro %}
usage is something like:
{{ field_with_errors(form.foo, placeholder='bar') }}
This lets me avoid boilerplate, but also lets me keep the display decisions in the template space.
Have a look at the rendering fields section.
Alternatively, you can add attributes to be rendered in the Jinja2 (etc.) template:
<div class="input-prepend">
{{ form.address(placeholder="example.com", id="address", autofocus="autofocus", required="required") }}
</div>
There's nothing to prevent you from using a variable for the ID value above, instead of address, then rendering the template with a keyword argument to populate it.
I have for example a JSON File
{
"Google":{
"Web":"www.web.de",
"Apps":{
"Drive": "DriveLink",
"Dropbox": "DropboxLink"
},
"Google Main":"http://mail.google.com",
"G+":"http://plus.google.com"
},
"Social":{
"Facebook":"http://www.facebook.de",
"G+":"https://plus.google.com",
"Xing":"http://www.xing.de",
"LinkedIn":"http://www.linkedin.com",
"Tumblr":"http://www.tumblr.com"
},
"Fun":{
"Reddit":"http://www.reddit.com"
}
}
As you can see I have under the section Google a Nested Section named Apps
With CherryPy I hand over this JSON Object as following with the name linksList:
#cherrypy.expose
def index(self):
linksFile = open('links.json', 'r')
linksList = json.load(linksFile)
template = jinjaEnv.get_template('index.html')
return template.render(linksList=linksList)
What I want is to render following:
Google
Web (as a link)
Google Main
G+
Apps
Drive
Dropbox
Social
Facebook
G+
Xing
and so on
What I don't understand is to do is to render this nested Objects like "Apps" recursively
The documentation reads:
It is possible to use loops recursively. This is useful if you are
dealing with recursive data such as sitemaps. To use loops recursively
you basically have to add the recursive modifier to the loop
definition and call the loop variable with the new iterable where you
want to recurse.
In your case this would be accomplished with the following:
<ul>
{% for key, value in linksList.items() recursive %}
<li>
{% if value is string %}
{{ key }}
{% else %}
{{ key }}
<ul>{{ loop(value.items()) }}</ul>
{% endif %}
</li>
{% endfor %}
</ul>
My 2 cents, just if someone comes here looking for rendering a JSON using Jinja, and complementing the response from #Ryon Sherman :)
Since JSON may have int values as well as strings, you can use if value is mapping (and flip the if-condition)
If your output must feel like a JSON you can use {{key|indent(width)}} + loop.depth
In my case, the template was for an email and key|indent() didn't work as expected so I ended up using an auxiliar {% for %} loop:
<div>
<code>{
{% for key, value in dic.items() recursive %}
{% if value is mapping %}
<p>
{% for it in range(loop.depth) %} {% endfor %}{{key}}: {
</p>
{{ loop(value.items()) }}
<p>
{% for it in range(loop.depth) %} {% endfor %}}
</p>
{% else %}
<p>
{% for it in range(loop.depth) %} {% endfor %}{{key}}: {{value}},
</p>
{% endif %}
{% endfor %}
}</code>
</div>
I'm relatively new to Django and I'm trying to build up my toolbox for future projects. In my last project, when a built-in template tag didn't do quite what I needed, I would make a mangled mess of the template to shoe-horn in the feature. I later would find a template tag that would have saved me time and ugly code.
So what are some useful template tags that doesn't come built into Django?
I'll start.
http://www.djangosnippets.org/snippets/1350/
Smart {% if %} template tag
If you've ever found yourself needing more than a test for True, this tag is for you. It supports equality, greater than, and less than operators.
Simple Example
{% block list-products %}
{% if products|length > 12 %}
<!-- Code for pagination -->
{% endif %}
<!-- Code for displaying 12 products on the page -->
{% endblock %}
smart-if. Allows normal if x > y constructs in templates, among other things.
A better if tag is now part of Django 1.2 (see the release notes), which is scheduled for release on March 9th 2010.
James Bennet's over-the-top-dynamic get_latest tag
edit as response to jpartogi's comment
class GetItemsNode(Node):
def __init__(self, model, num, by, varname):
self.num, self.varname = num, varname
self.model = get_model(*model.split('.'))
self.by = by
def render(self, context):
if hasattr(self.model, 'publicmgr') and not context['user'].is_authenticated():
context[self.varname] = self.model.publicmgr.all().order_by(self.by)[:self.num]
else:
context[self.varname] = self.model._default_manager.all().order_by(self.by)[:self.num]
return ''
<div id="news_portlet" class="portlet">
{% get_sorted_items cms.news 5 by -created_on as items %}
{% include 'snippets/dl.html' %}
</div>
<div id="event_portlet" class="portlet">
{% get_sorted_items cms.event 5 by date as items %}
{% include 'snippets/dl.html' %}
</div>
I call it get_sorted_items, but it is based on James' blog-post
In come case {% autopaginate queryset %} (http://code.google.com/p/django-pagination/) is useful. For example:
#views.py
obj_list = News.objects.filter(status=News.PUBLISHED)
# do not use len(obj_list) - it's evaluate QuerySet
obj_count = obj_list.count()
#news_index.html
{% load pagination_tags %}
...
# do not use {% if obj_list %}
{% if obj_count %}
<div class="news">
<ul>
{% autopaginate obj_list 10 %}
{% for item in obj_list %}
<li>{{ item.title }}</li>
{% endfor %}
</ul>
</div>
{% paginate %}
{% else %}
Empty list
{% endif %}
Note, that obj_list must be lazy - read http://docs.djangoproject.com/en/dev/ref/models/querysets/#id1