Is there an easy way of displaying method output in Djangos admin detail view? For the list view we have the list_display field, however i cannot find anything similar for the detail view. Of course, editing the template would be a way but isnt there something easier?
Creating a new template isn't that hard. I typically put info in a right column like this:
{% extends "admin/change_form.html" %}
{% block coltype %}colMS{% endblock %}
{% block content %}{{block.super}}
<div id="content-related">
{{original.method}}
</div>
{% endblock %}
Related
I am pretty new to Flask/Flask-Admin.
I have followed the tutorial on flask admin and managed to get the admin panel working but slightly lost on how to get the below things implemented.
https://github.com/flask-admin/flask-admin/tree/master/examples/auth
When logged in as a normal user I can only see "home" page.
How can I expose other views to "normal user" and restrict actions such as read only etc.
I have created a "baseview" which is not associated with any other models as below:
class SitesView(MyBaseView):
#expose('/')
def index(self):
return self.render('views/testviews.html')
admin.add_view(SitesView(name='Test views', endpoint='test views'))
and html as below:
{% extends 'admin/master.html' %}
{% block body %}
{{ super() }}
{% if current_user.has_role('view1') %}
Site1
{% endif %}
{% if current_user.has_role('view2') %}
<a>Site2</a>
{% endif %}
{% if current_user.has_role('view3') %}
<a>Site3</a>
{% endif %}
{% if current_user.has_role('view4') %}
<a>Site4</a>
{% endif %}
{% endblock %}
This gives me a new tab with different views with works as expected.
What I am trying to achieve here is when user click the Site1 link they go to Site1 page within flask-admin interface but I am not sure how to do that. I could create a new route for this but the problem is I can't(don't know how to) extend flask admin template.
For example this works but it redirect the page outside flask-admin template:
#app.route('/views/')
def views():
return render_template('views/views1.html')
and modified the templates>admin>index.html page with below:
<ul class="lead text-center list-group">
{% if current_user.has_role('view1') %}
<li class="list-group-item">View1</li>
{% endif %}
{% if current_user.has_role('view2') %}
<li class="list-group-item">View2</li>
{% endif %}
{% if current_user.has_role('view3') %}
<li class="list-group-item">View3</li>
{% endif %}
{% if current_user.has_role('view4') %}
<li class="list-group-item">View4</li>
{% endif %}
</ul
I want to build the whole web site using flask admin so that I can keep user experience consistence. Am I doing this the wrong way?
Thanks for your time.
Please do let me know if you want me to provide more information on this issue.
Kind Regards.
So after going through documentations and tutorials I have found the solution to my issue.
For my first question:
When logged in as a normal user I can only see "home" page. How can I
expose other views to "normal user" and restrict actions such as read
only etc.
We can do this by overwriting our view functions is_accessible method as below:
def is_accessible(self):
if not current_user.is_active or not current_user.is_authenticated:
return False
if current_user.has_role('superuser') or current_user.has_role('user') or current_user.has_role('view1'):
return True
return False
For my second question we just need to give the endpoint as for our BaseView as below:
class MyView(BaseView):
#expose('/')
def index(self):
return self.render('views.html')
admin.add_view(MyView(name='Custom Views', endpoint='customviews'))
And then in your jinja template you need to call it:
href="{{ url_for('customviews.index') }}
Just one thing to note, doing this:
current_user.has_role('superuser') or current_user.has_role('user') or current_user.has_role('view1')
could get quite messy if we have so many roles, not sure how we would approach this but hoping this will help someone.
Thanks all.
I know this is an old question, but for the following code
current_user.has_role('superuser') or current_user.has_role('user') or current_user.has_role('view1')
What I like to do is having a hybrid_property (available on both Peewee and SQLAlchemy) inside my User class that consolidates these properties. So it'd look something like this:
#hybrid_property
def user_has_administrative_rights(self):
return self.has_role('superuser') or self.has_role('user')
Hi guys I am fairly new to the Django framework and was hoping someone could assist me in my current dilemma :)
I have my base template set up for my project. I have a main-content area and a side-bar
I created a include for my side bar:
{% include "modules/include/sidebar.html" %}
The issue is that I have two different side bars that I would like to render depending on the page the user is on e.g. if the user is on the home page then use
{% include "modules/include/sidebar.html" %}
but if the user is on an article page then use
{% include "modules/include/article-sidebar.html" %}
I looked through the docs but couldn't find anything to help me solve this issue.
All and any help will be appreciate.
Create a block in your base template, something like {% block sidebar %}{% endblock %}
Then in your home page template do
{% extends 'your-base-template-name-here' %}
{% block sidebar %}
{% include "modules/include/sidebar.html" %}
{% endblock %}
And in your article template use
{% extends 'your-base-template-name-here' %}
{% block sidebar %}
{% include "modules/include/article-sidebar.html" %}
{% endblock %}
More about template inheritance here https://docs.djangoproject.com/en/1.9/ref/templates/language/#id1
I'm building a website using django with a header on top of every page, which basically is a menu with a few links, constant throughout the pages.
However, depending on the page you're on I'd like to highlight the corresponding link on the menu by adding the class "active". To do so, I am currently doing as follow: each page has a full menu block that integrates within a general layout, which does NOT contain the menu. For exemple, page2 would look like this:
{% extends "layout.html" %}
{% block menu %}
<li>Home</li>
<li>page1</li>
<li class="active">page2</li>
<li>page3</li>
{% endblock %}
The problem is that, beside from that solution being not so pretty, every time I want to add a link to the header menu I have to modify each and every page I have. Since this is far from optimal, I was wondering if any of you would know about a better way of doing so.
Thanks in advance!
You can create a custom templatetag:
from django import template
from django.core.urlresolvers import reverse, NoReverseMatch, resolve
register = template.Library()
#register.simple_tag
def active(request, view_name):
url = resolve(request.path)
if url.view_name == view_name:
return 'active'
try:
uri = reverse(view_name)
except NoReverseMatch:
uri = view_name
if request.path.startswith(uri):
return 'active'
return ''
And use it in the template to recognize which page is loaded by URL
<li class="{% active request 'car_edit' %}">Edit</li>
If you have a "page" object at every view, you could compare a navigation item's slug to the object's slug
navigation.html
<ul>
{% for page in navigation %}
<li{% ifequal object.slug page.slug %} class="active"{% endifequal %}>
{{ page.title }}
</li>
{% endfor %}
</ul>
base.html
<html>
<head />
<body>
{% include "navigation.html" %}
{% block content %}
Welcome Earthling.
{% endblock %}
</body>
</html>
page.html
{% extends "base.html" %}
{% block content %}
{{ object }}
{% endblock %}
Where navigation is perhaps a context_processor variable holding all the pages, and object is the current PageDetailView object variable
Disclaimer
There are many solutions for your problem as noted by Paulo. Of course this solution assumes that every view holds a page object, a concept usually implemented by a CMS. If you have views that do not derive from the Page app you would have to inject page pretenders within the navigation (atleast holding a get_absolute_url and title attribute).
This might be a very nice learning experience, but you'll probably save loads time installing feinCMS or django-cms which both define an ApplicationContent principle also.
You may use the include tag and pass it a value which is the current page.
For example, this may be a separate file for declaring the menu template only:
menu.html
{% if active = "a" %}
<li>Home</li>
{% if active = "b" %}
<li>page1</li>
{% if active = "c" %}
<li class="active">page2</li>
{% if active = "d" %}
<li>page3</li>
And call this from within your template like this:
{% include 'path/to/menu.html' with active="b"%} # or a or c or d.
Hope it helps!
Is it possible to have the pagination links that appear at the bottom of a list of objects in Django's admin interface at the top as well?
Can this be done without changing the admin templates? I suspect not, given the lack of a ModelAdmin option, but thought I'd see if anyone had done this before I dug into the template code.
I really, really don't want to have to copy and paste change_list.html into a new file, just so I can add a pagination line - that'll make changing Django versions painful, since I'll have to check if anything's changed in that file, and re-apply my change.
Do not copy change_list.html, instead create a new template that extends it:
{% extends "admin/change_list.html" %}
{% block result_list %}
{% block pagination %} {{ block.super }} {% endblock %} <!-- pagination -->
{{ block.super }} <!-- rest of results list -->
{% endblock %}
Then pass the new template's name to ModelAdmin in change_list_template attribute - doc here.
The source code implementing the django admin template for change_list.html has a content block so if you create a file change_list.html under 'admin' folder in your templates directory and add this:
{% extends "admin/change_list.html" %}
{# added pagination to top as well as bottom #}
{% block content %}{% pagination cl %}{{ block.super }}{% endblock %}
it should do the trick!
I'm looking to add an extra set of pages to my auto-generated admin site. I want to generate reports off my models and some logs surrounding it. The actual generating isn't the issue.
How do I:
Make the report output look like it's an admin page, with breadcrumbs, similarly formatted table, etc?
Register the view so it shows up on the front page?
The above answer didn't address question 2, at least directly... the "hack" way to get your custom view to show up as the front page of the admin is probably to just override it in the urlconf:
(r'^admin/$', my.custom.admin.homepage),
before the normal admin line:
(r'^admin/', admin.site.root),
the "right" way to do it, though, is to make your admin a custom instance of AdminSite and override the index_template setting. http://docs.djangoproject.com/en/dev/ref/contrib/admin/#root-and-login-templates
In terms of generating the look and feel of admin, it should be trivial to inherit the parent pages of the admin and insert your own template content into the appropriate blocks.
Take a look at the markup (including id and class attributes) in the default admin pages and try to get an understanding of how things are styled consistently. If you are including the admin CSS on the page you should get an awful lot of it for free.
For further information, take a look at the admin docs: http://docs.djangoproject.com/en/dev/ref/contrib/admin/
Here's a base template to get you started:
{% extends "admin/base_site.html" %}
{% load adminmedia %}
{% block extrahead %}
{% endblock %}
{% block coltype %}flex{% endblock %}
{% block bodyclass %}change-list{% endblock %}
{% block stylesheet %}{% admin_media_prefix %}css/changelists.css{% endblock %}
{% block extrastyle %}
<link rel="stylesheet" type="text/css" href="{{settings.MEDIA_URL}}/stylesheets/extra_admin.css" />
{% endblock %}
{% block breadcrumbs %}<div class="breadcrumbs">Home › {{page_title}}</div>{% endblock %}
{% block content %}
<div id="content-main">
<h1>{{page_title}}</h1>
{{page_content}}
</div>
{% endblock %}