Django fieldset.html customization. How to customize a single field? - django

In my app, I need to add javascript to the admin template "fieldset.html" in order to create a widget for a single field.
But, in the fields iteration (for), when I try to catch the specific field, I fail.
I'm doing by the ifequal tag (fieldset.html):
{% for line in fieldset %}
<div class="form-row{% if line.errors %} errors{% endif %}{% for field in line %} {{ field.field.name }}{% endfor %}">
{% for field in line %}
(...)
{% ifequal field.label_tag "name" %}
#do something
{% endifequal%}
(...)
{% endfor %}
</div>
{% endfor %}
Any sugestions? The field stores the recurrence of a schedule. So I need to do something dinamic, that's why I'm thinking about using javascript.

"Form Media"

Related

Overriding django admin pagination along with url parameters

I would like to implement custom pagination for my admin panel.
My url looks like the following:
http://localhost:8000/admin/items/?group_id=20
On this URL I do some work to filter the results using the parameter group_id (by overriding get_changelist method).
The page results are corrects, the problem is my pagination ending up like this http://localhost:8000/admin/items/?p=1 whereas I would like the URL to be http://localhost:8000/admin/items/?group_id=20&p=1 and keep the parameter.
Basically I want the same result as How to paginate Django with other get variables? but using Django admin.
How can I keep the parameter along with the pagination?
I've tried overriding pagination.html file but without any success.
Thank you.
Edit
I've tried overriding pagination.html but request.GET.items is still empty (even if my settings file is well configured)
{% load admin_list %}
{% load i18n %}
{% load content_extras %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
{{ i }}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
{% if show_all_url %}{% trans 'Show all' %}{% endif %}
{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
</p>
FOUND A SOLUTION:
1/ Override changelist_view on admin.py and pass the extra data
def changelist_view(self, request, extra_context=""):
response = super(ItemAdmin, self).changelist_view(request, extra_context)
group_id = request.GET.get('group_id', None)
if group_id:
extra_context = {
'group_id': group_id,
}
response.context_data.update(extra_context)
return TemplateResponse(request, "admin/changelist.html", response.context_data)
2/ Create changelist.html file based on django admin template (copy/paste)
Add {% load content_extras %} at the top of the file (line 3)
Change line {% block pagination %}{% pagination cl %}{% endblock %} with {% block pagination %}{% custom_pagination cl %}{% endblock %}
3/ Create content_extras.py under templatetags folder and write custom_pagination function
from django import template
from django.contrib.admin.templatetags import admin_list
register = template.Library()
#register.inclusion_tag('admin/pagination.html', takes_context=True)
def custom_pagination(context, cl):
pagination = admin_list.pagination(cl)
if 'group_id' in context:
params = (('group_id', context['group_id']),)
pagination['params'] = params
return pagination
4/ Create pagination.html (same location as changelist.html)
{% load admin_list %}
{% load i18n %}
{% load content_extras %}
<p class="paginator">
{% if pagination_required %}
{% for i in page_range %}
{{ i }}
{% endfor %}
{% endif %}
{{ cl.result_count }} {% if cl.result_count == 1 %}{{ cl.opts.verbose_name }}{% else %}{{ cl.opts.verbose_name_plural }}{% endif %}
{% if show_all_url %}{% trans 'Show all' %}{% endif %}
{% if cl.formset and cl.result_count %}<input type="submit" name="_save" class="default" value="{% trans 'Save' %}">{% endif %}
</p>
If you activated django.template.context_processors.request in your settings, you can access parameters from your request directly from your template.
And then you can access the parameters in your templates directly. Something like:
href="?page={{ data.next_page_number }}{% for key, value in request.GET.items %}{% if key != 'page' %}&{{ key }}={{ value }}{% endif %}{% endfor %}"
Research (context_processors.request was moved from django.core to django.templates some time ago)

Adding div directly into ModelForm in django

Is there way to add div tag directly into ModelForm in django?
I want to get something like this:
<input></input>
<input></input>
.
.
<div class="someClass">
<input></input>
<div>
<input></input>
Or i need to do this in html page?
UPDATE
This is generated by:
{% for field in formFields %}
{{field}}
{% endfor %}
I want for some inputs to be div around it.
Add div in your for loop like this:
{% for field in formFields %}
{% if field.name == 'xxx' %}
<div class="someClass">{{ field }}</div>
{% else %}
{{ field }}
{% endif %}
{% endfor %}

ListField is showing <ul> instead of <input> in edit/create post

I am using Flask, mongoengine for a project and I am trying to get basic stuff working from http://docs.mongodb.org/manual/tutorial/write-a-tumblelog-application-with-flask-mongoengine/
After implementing everything from above link I added a new field for "tags" in Post and when I try to create a post, my tags doesn't show a input box.
Any help is appreciated.
My code and screenshot below
class Post(db.DynamicDocument):
created_at = db.DateTimeField(default=datetime.datetime.now, required=True)
title = db.StringField(max_length=255, required=True)
slug = db.StringField(max_length=255, required=True)
comments = db.ListField(db.EmbeddedDocumentField('Comment'))
tags = db.ListField(db.StringField(max_length=30)) # New field I added
template form
{% macro render(form) -%}
<fieldset>
{% for field in form %}
{% if field.type in ['CSRFTokenField', 'HiddenField'] %}
{{ field() }}
{% else %}
<div class="clearfix {% if field.errors %}error{% endif %}">
{{ field.label }}
<div class="input">
{% if field.name == "body" %}
{{ field(rows=10, cols=40) }}
{% else %}
{{ field() }}
{% endif %}
{% if field.errors or field.help_text %}
<span class="help-inline">
{% if field.errors %}
{{ field.errors|join(' ') }}
{% else %}
{{ field.help_text }}
{% endif %}
</span>
{% endif %}
</div>
</div>
{% endif %}
{% endfor %}
</fieldset>
{% endmacro %}
rendering form code
{% extends "admin/base.html" %}
{% import "_forms.html" as forms %}
{% block content %}
<h2>
{% if create %}
Add new Post
{% else %}
Edit Post
{% endif %}
</h2>
<form action="?{{ request.query_string }}" method="post">
{{ forms.render(form) }}
<div class="actions">
<input type="submit" class="btn primary" value="save">
Cancel
</div>
</form>
{% endblock %}
From what I can gather, your problem is you're telling WTF to render the tags field, but WTForms doesn't know how to handle that information.
From looking at the Flask-MongoEngine documentation, it seems the ListField is just a FieldList as WTForms refers to it.
Currently you're not actually defining the form independently in WTForms, you're just using the magic included in Flask-MongoEngine, so my first attempt would be to add some more logic to your macro, add a {% elif field.type == 'ListField' %} and try and discover what's contained in there to iterate through to produce your form. From having a quick look at the source-code, something like the following might work.
{% elif field.type == 'ListField %}
{# render_the_group_label #}
{% for subfield in field.entries %}
{% if subfield.type == 'StringField' %}
{# render_the_subfield #}
{% endif %}
{% endfor %}
...
That code will need to be worked on, but hopefully it'll point you in the right direction. Otherwise, I'd actually define the form seperately in WTForms to give you a bit more control on the code-side. Luckily they provide a csv tag example which should help you if you need to go that route. I wrote a guide that takes a different route using #property decorators to achieve a similar effect, which again, might at least point you towards the finish line.

Django admin add custom button in change form depending on a form field value

I have an application that overrides het Django change form. What I want to change is the submit buttons on the bottom. Underneath is change_form.html in a django app:
{% extends "admin/change_form.html" %}
{% block submit_buttons_bottom %}
## add some buttons
{% endblock %}
The button I want to show/add depends on the value of a certain field in the form names 'status'. How can I get the value of a field in the template... something like:
{% if form.field.status == 'unresolved' %}
<input type="submit" value="Mark as resolved" class="default" name="_save" />
{% endif %}
UPDATE:
I'm not getting any errors. There is simply nothing displayed.
Looping through var 'adminform' will get me to the field I need
{% for fieldset in adminform %}
{% for line in fieldset %}
{% for field in line %}
{% if field.field.name == 'status' %}
this is status {{ field.field.name }} - {{ field.contents }}
{% endif %}
{% endfor %}
{% endfor %}
{% endfor %}
But I want to access it directly. Something like:
{% if adminform.0.0.field.status == 'unresolved' %}
<input type="submit" value="Mark as resolved" class="default" name="_save" />
{% endif %}
This should work:
{% if adminform.form.status.value == 'unresolved' %}
or if the field is readonly, there's another way:
{% if adminform.form.instance.status == 'unresolved' %}
Try changing your if statement to -
{% if adminform.status.value == 'unresolved' %}
I'm guessing, but I think the adminform variable is probably just a form. Have a look at this section of the docs to see the atributes of the form fields.

Django form template

If there were field.errors in django, how to to add css class to {{ field }}, example at bottom
{% for field in form %}
{{ field }}
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Aiming for {{ field }} input type that would have "class=error" when ever there was an error
<input class="error">
You can add the class to a wrapper around the field. Django also does this by itself when defining classes in forms.py or views.py
{% for field in form %}
<p {% if field.errors %}class="error"{% endif %}
{{ field }}
</p>
{% if field.errors %}{{ field.errors }}{% endif %}
{% endfor %}
Unfortunately this seems to be the only way.
Even when Django adds the classes itselt, it prefers to add them to a wrapper of some sort.
http://docs.djangoproject.com/en/dev/ref/forms/api/#more-granular-output
Scroll down to read about the new thing in 1.2 about adding css classes.
Using this, you can just use form.as_p (or whatever suits you) as the elements will have all the classes as you define them.
Hope this was a little bit of help.
You can use widget_tweaks api to do that.
Instead of rendering a form with
{{ form.field }}
You should use:
{% load widget_tweaks %}
{% render_field form.field class="error" %}