Reducing size of columns in Flask-Admin - python

Is there a way to limit the size (length/width) of a ModelView column? I am using a WYSIWYG editor and this creates really long text, therefor making the column for the ModelView very long.
Here is picture of what it looks like. Look on the right hand side the last column. It is even longer than the screenshot could handle.

Don't show the column (by exclusion):
class MyView(ModelView):
column_exclude_list = ('description')
Don't show the column (by inclusion):
class MyView(ModelView):
column_list = ('rating', 'category_id', 'year', 'stock', 'image')
Reformat the column:
class MyView(ModelView):
def _description_formatter(view, context, model, name):
# Format your string here e.g show first 20 characters
# can return any valid HTML e.g. a link to another view to show the detail or a popup window
return model.description[:20]
column_formatters = {
'description': _description_formatter,
}

A way to do this could be to override the css style of the relevant column. In the Flask-admin list.html template you find the following code for creating the columns:
{% for c, name in list_columns %}
<td class="col-{{c}}">
{% if admin_view.is_editable(c) %}
{% set form = list_forms[get_pk_value(row)] %}
{% if form.csrf_token %}
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c), csrf=form.csrf_token._value()) }}
{% else %}
{{ form[c](pk=get_pk_value(row), display_value=get_value(row, c)) }}
{% endif %}
{% else %}
{{ get_value(row, c) }}
{% endif %}
</td>
{% endfor %}
So e.g. for column 2 you could add a max-width property to the css class col-2 to limit its width.

Related

Group blocks from StreamField Wagtail

What am I trying to achieve will be easier to explain on lists.
e.g
list_of_blocks=[1,2,3,4,5,6,7,8,9,10,11,12]
block_first_row = list_of_blocks[:3]
block_rest_rows = [list_of_blocks[i:i+4] for i in range(3, len(list_of_blocks), 4)]
block_rows = block_rest_rows.insert(0, list_of_blocks)
I want to group blocks from StreamField and display them in template grouped by those rows.
Is there a way to do it in my model? Or should i do it somehow in template..
I've tried to do:
operate on StreamField as on list
deconstuct StreamField.. then operate as on list
The value of a StreamField is a list-like object of type StreamValue. Since it isn't a real list, it may not support slicing - if not, you can get around that by casting it to a real list with list(self.body) (where body is your StreamField). A good place to do this is the page's get_context method:
def get_context(self, request):
context = super().get_context(request)
list_of_blocks = list(self.body)
block_first_row = list_of_blocks[:3]
block_rest_rows = [list_of_blocks[i:i+4] for i in range(3, len(list_of_blocks), 4)]
block_rows = block_rest_rows.insert(0, block_first_row)
context['block_rows'] = block_rows
return context
You can then access block_rows in your template:
{% for block_row in block_rows %}
<div class="row">
{% for block in block_row %}
render block as normal, with {% include_block block %} or otherwise
{% endfor %}
</div>
{% endfor %}

Trouble using python dictionary in a Django template

So I have a python dictionary storing the size and the amount each size has, titled final_list. Then I'm passing that to the template using "sizes": final_list. In the html template, I'm trying to create a drop-down selection with all the sizes, and only display sizes that are available, or have an amount not equal to 0. The problem is, it seems as if it isn't accepting the dict or something, since the dropdown shows up empty. Below is the code I have, any help would be much appreciated.
Views.py
I'm getting the sizing info from a model called 'Size' then checking if there are 0 objects of that size. Then I'm creating the dictionary to only have sizes that are actually available.
from django.template.defaulttags import register
#register.filter
def get_item(dictionary, key):
return dictionary.get(key)
def product(request, code):
sizes = Size.objects.get(code=code)
all_size = ['small', 'medium', 'large', 'XL']
final_list = {}
for size in all_size:
if getattr(sizes, size) == 0:
pass
else:
final_list[size] = getattr(sizes, size)
return render(request, "website/listing.html", {
"sizes": final_list
})
HTML (website/listing.html)
<form method="POST">
<select name="sizes" style="width: 90px; height: 20px;">
{% csrf_token %}
{% for size in sizes %}
{% if final_list|get_item:size != 0 %}
<option>{{size}}</option>
{% endif %}
{% endfor %}
</select>
</form>
You don't pass a context variable named final_list to the template. You should use {% if sizes|get_item ... instead.
That being said, this code could be simplified as:
{% for size, value in sizes.items %}
{% if value %}
<option>{{ size }}</option>
{% endif %}
{% endfor %}
This way you don't have to use the custom filter get_item either.

django dictionary of querysets

i made i dictionary of querysets in one of my views :
list =[]
while(x<100 and i>0):
order_qs_1 = Order.objects.filter(timestamp__range=[start_date, end_date])
x = x+1
i=i-j
list.append(order_qs_1)
context= {
'list':list,
}
but now i don't know how to access the data inside the dictionary in my template
in my template i did something like this :
{% for item in list %}
{{ item }} </br>
{% endfor %}
this is what it renders:
the random numbers and characters are the order_id in my order model
the queryet is a list of orders coming from my order model
but this not what i want , i want the access the data inside each queryset
You can iterate over the querysets. For example:
{% for qs in list %}
<p>
{% for order in qs %}
{{ order }}
{% endfor %}
</p>
{% endfor %}
Here we thus iterate over the querysets qs, and for example render the order. You can thus render individual data of that order, for example {{ order.pk }} for the primary key.

Creating a table using jinja2

I am trying to create a (latex) table using jinja2. I defined a macro to help me to create the table:
{% macro table(header, rows, columns) %}
\begin{tabular}{(formatting, later)}
{{ row(header) }}
{% for row in rows %}
{% for column in columns %}
{{ caller(row, column) }} & % *here*
{% endfor %} \\
{% endfor %}
\end{tabular}
{% endmacro %}
I can use the template like this:
{% call(row, column) table.table(header, rows, columns) %}
Content at row = {{row}}, column = {{column}}
{% endcall %}
I quite like how these macros work. The problem is however that I would like to join the results of the macro by a & sign rather than
playing a sign after each row. Essentially now I have this:
Content at row = 0, column = 0 &
Content at row = 0, column = 1 & \\
and I would like to get this instead:
Content at row = 0, column = 0 &
Content at row = 0, column = 1 \\
Is it possible to use filters on macro results? Is there some other way to generate a table where each cell is another jinja2 template depending on parameters?
I'm not familiar with a join functionality in Jinja itself. However it does have built in indexes on your loop. Using loop.last you can determine where to change the output symbol
{% macro table(header, rows, columns, ) %}
\begin{tabular}{(formatting, later)}
{{ row(header) }}
{% for row in rows %}
{% for column in columns %}
{{ caller(row, column) }} {% if loop.last %}\\{% else %}&{%endif%}
{% endfor %}
{% endfor %}
\end{tabular}
{% endmacro %}
Here's documentation on the other loop variables that are available: http://jinja.pocoo.org/docs/2.9/templates/#for

Get index of element iterating thgrough multiple choices field django for in loop

I have MultipleChoiceFieldfield
OPTIONS = (
("AUT", "Austria"),
("DEU", "Germany"),
("NLD", "Neitherlands"),
)
countries = forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(attrs={"name": "select_0","class": "fff"}),
choices=OPTIONS)
I build my own html structure for this field and this is simplified code:
{% for value, text in simple_search_form.countries.field.choices %}
{{value}}
{{text}}
{% endfor %}
How do I get and index of each element here?
I need to have
{{value}}
{text}}
{{index}}
If it's in a for loop, you can use
{{ forloop.counter0 }}

Categories