On ne va pas se mentir, de ce que nous avons vu de la partie admin ce n'est pas l'extase visuel. Il existe des projets -sur github notamment- qui proposent d'améliorer le design de votre projet Django . Le module que j'utilise le plus souvent est xadmin puisqu'en plus d'être sympatique visuellement (basé sur bootstrap twitter ) il propose quelques plugins très utiles, comme les exports en CSV , XML et JSON mais également des filtres très bien pensés.
Démo de xadmin
Arrêtons les éloges, vous pouvez visiter le site de démonstration pour vous faire votre propre idée: Demo xadmin .
Les identifiants sont admin / admin .
Installer xadmin
Un petit pip pour installer xadmin :
pip install django-xadmin
Le projet est sur Github: xAdmin
Implémenter xadmin
Il vous faudra indiquer la présence de xadmin et crispy_form dans le partie settings:
eboutique/settigns.py
INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'backoffice', 'crispy_forms', 'xadmin', )Puis configurez le fichier urls.py
eboutique/urls.py
from django.conf.urls import patterns, include, url import xadmin xadmin.autodiscover() urlpatterns = patterns('', # Examples: # url(r'^$', 'eboutique.views.home', name='home'), # url(r'^blog/', include('blog.urls')), #url(r'^admin/', include(admin.site.urls)), url(r'^xadmin/', include(xadmin.site.urls)), )
Nous avons défini que le module xadmin est accessible via l'uri /xadmin/
Premières captures
http://localhost:8000/xadmin

Vous pouvez vos connecter à l' interface xadmin en indiquant les identifiants que vous avez renseigné lors de votre syncb .
Responsive design
Format grand écran:

Format tablette:

Format smartphone:

Afficher ses modèles
Dans nos exemples nous utiliserons les modèles suivants:
backoffice/models.py
# coding: utf-8 from django.db import models class Product(models.Model): """ Produit : prix, code, etc. """ class Meta: verbose_name = "Produit" name = models.CharField(max_length=100) code = models.CharField(max_length=10, null=True, blank=True, unique=True) price_ht = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="Prix unitaire HT") price_ttc = models.DecimalField(max_digits=8, decimal_places=2, verbose_name="Prix unitaire TTC") def __unicode__(self): return "{0} [{1}]".format(self.name, self.code) class ProductItem(models.Model): """ Déclinaison de produit déterminée par des attributs comme la couleur, etc. """ class Meta: verbose_name = "Déclinaison Produit" product = models.ForeignKey('Product') code = models.CharField(max_length=10, null=True, blank=True, unique=True) code_ean13 = models.CharField(max_length=13) attributes = models.ManyToManyField("ProductAttributeValue", related_name="product_item", null=True, blank=True) def __unicode__(self): return "{0} [{1}]".format(self.product.name, self.code) class ProductAttribute(models.Model): """ Attributs produit """ class Meta: verbose_name = "Attribut" name = models.CharField(max_length=100) def __unicode__(self): return self.name class ProductAttributeValue(models.Model): """ Valeurs des attributs """ class Meta: verbose_name = "Valeur attribut" ordering = ['position'] value = models.CharField(max_length=100) product_attribute = models.ForeignKey('ProductAttribute', verbose_name="Unité") position = models.PositiveSmallIntegerField("Position", null=True, blank=True) def __unicode__(self): return "{0} [{1}]".format(self.value, self.product_attribute)
Comme pour la partie admin de Django , il est nécessaire d'indiquer à xadmin quel modèle nous voulons afficher dans l'interface. Créons un fichier adminx.py dans notre application:
backoffice/adminx.py
# coding: utf-8 import xadmin from models import Product xadmin.site.register(Product)
Vous pouvez maintenant visualiser votre vue Product :
http://localhost:8000/xadmin

Ajoutons un produit:
http://localhost:8000/xadmin/backoffice/product/add/

Ne remplissons pas les champs obligatoires pour voir la réaction de Django:
http://localhost:8000/xadmin/backoffice/product/add/

Validons notre produit correctement
http://localhost:8000/xadmin/backoffice/product/add/

Exporter les données
xadmin vous apporte des options en plus comme la possibilité d'exporter votre liste de données en CSV, XML ou JSON:

Inlines
Comme nous l'avons vu dans le chapitre admin , nous pouvons mettre à la suite de notre formulaire principal un formulaire pour les clés étrangères à l'aide du paramètre inlines :
backoffice/adminx.py
# coding: utf-8 import xadmin from models import * class ProductItemAdminInline(object): model = ProductItem extra = 1 class ProductAdmin(object): model = Product inlines = [ProductItemAdminInline] xadmin.site.register(Product, ProductAdmin)
Résultat de notre fiche produit:

Par défaut les items se succèdent les uns à la suite des autres, ce qui en terme d'ergonomie peut dans certains cas être génant, par exemple si les données inlines sont nombreuses. Il existe des options pour changer l'affichage:
class ProductItemAdminInline(object): model = ProductItem extra = 3 style = 'tab'

class ProductItemAdminInline(object): model = ProductItem extra = 3 style = 'table'

class ProductItemAdminInline(object): model = ProductItem extra = 3 style = 'accordion'

Créer une page personnalisée
Un backoffice n'est pas composé que de pages d'édition ou de listing de modèles, vous pouvez par exemple créer une page statistiques:
backoffice/adminx.py
from xadmin import views class StatsView(views.CommAdminView): def get(self, request, *args, **kwargs): return self.template_response('xadmin/stats.html', self.get_context()) xadmin.site.register_view(r'stats/$', StatsView, name='stats')
CSS
Amusez-vous à modifier le CSS pour personnaliser votre interface
textarea:focus,input:focus{outline:none!important}
:focus{outline:none!important}
:active{outline:none!important}
.form-control:focus{border-color:#ededed;-webkit-box-shadow:none;box-shadow:none}
.form-horizontal .control-label{margin-top:8px}
.controls{padding:1px!important;margin:0}
.form-horizontal .control-label{padding-top:0!important}
.form-horizontal .controls{border-left:none}
.form-control{display:block;width:100%;padding:2px;font-size:1em;line-height:1.428571429;
color:#555;vertical-align:middle;background-color:#fff;background-image:none;
border:1px solid #ededed;border-radius:0;-webkit-box-shadow:none;box-shadow:none;
-webkit-transition:border-color ease-in-out 0.15s,box-shadow ease-in-out .15s;
transition:border-color ease-in-out 0.15s,box-shadow ease-in-out .15s;margin-top:1px}
ul.nav-sitemenu{padding:0}
#left-side{padding:1px;margin:0}
#left-side a{background-color:#fff;color:#333}
#left-side .active a{background-color:#3276b1;color:#333;font-weight:700;color:#fff}
body{background-color:#eee}
#content-block{padding:0 20px!important}
.form-group{background-color:none;border-bottom:0}
.panel-body{margin:10px 1px}
input[type="file"]{max-width:300px;border:1px solid #efefef}
input[type="number"]{max-width:100px;border:1px solid #efefef;text-align:center}
input[type="email"]{max-width:300px;border:1px solid #efefef}
input[type="text"]{width:100%;border:1px solid #efefef}
input{font-weight:700}
.text-field{max-width:none;height:30px}
.panel .btn{padding:4px}
.panel .input-group-addon{padding:2px 5px}
.input-group-addon,.input-group-btn{width:0}
.textinput{max-width:500px;width:100%}
.text-field{width:70%!important}
.selectize-input{min-height:15px;line-height:13px}
input[data-upper]{text-transform:uppercase}
input[type="text"],input[type="number"],input[type="email"],input[type="file"]
{padding:0;padding-left:5px;line-height:1em;height:30px}
.navbar .navbar-brand{max-width:none}
.select2-container{width:99%}
.select2-choices{max-width:100%}
Les templates de xadmin
Vous trouverez ci-dessous tous les templates du projet xadmin . Pour écraser un template de base , il vous suffit de le recréer dans votre dossier template de votre application avec le même nom.
tree /usr/local/lib/python2.7/dist-packages/xadmin/templates/xadmin/
├── 404.html
├── 500.html
├── auth
│ ├── password_reset
│ │ ├── complete.html
│ │ ├── confirm.html
│ │ ├── done.html
│ │ ├── email.html
│ │ └── form.html
│ └── user
│ ├── add_form.html
│ └── change_password.html
├── base.html
├── base_site.html
├── blocks
│ ├── comm.top.setlang.html
│ ├── comm.top.theme.html
│ ├── comm.top.topnav.html
│ ├── modal_list.left_navbar.quickfilter.html
│ ├── model_form.before_fieldsets.wizard.html
│ ├── model_form.submit_line.wizard.html
│ ├── model_list.nav_form.search_form.html
│ ├── model_list.nav_menu.bookmarks.html
│ ├── model_list.nav_menu.filters.html
│ ├── model_list.results_bottom.actions.html
│ ├── model_list.results_top.charts.html
│ ├── model_list.results_top.date_hierarchy.html
│ ├── model_list.top_toolbar.exports.html
│ ├── model_list.top_toolbar.layouts.html
│ └── model_list.top_toolbar.refresh.html
├── edit_inline
│ ├── accordion.html
│ ├── base.html
│ ├── blank.html
│ ├── one.html
│ ├── stacked.html
│ ├── tab.html
│ └── tabular.html
├── filters
│ ├── char.html
│ ├── checklist.html
│ ├── date.html
│ ├── fk_search.html
│ ├── list.html
│ ├── number.html
│ ├── quickfilter.html
│ └── rel.html
├── forms
│ └── transfer.html
├── grids
│ └── thumbnails.html
├── includes
│ ├── box.html
│ ├── pagination.html
│ ├── sitemenu_accordion.html
│ ├── sitemenu_default.html
│ ├── submit_line.html
│ ├── toggle_back.html
│ └── toggle_menu.html
├── layout
│ ├── fieldset.html
│ ├── field_value.html
│ ├── field_value_td.html
│ ├── input_group.html
│ └── td-field.html
├── views
│ ├── app_index.html
│ ├── batch_change_form.html
│ ├── dashboard.html
│ ├── form.html
│ ├── invalid_setup.html
│ ├── logged_out.html
│ ├── login.html
│ ├── model_dashboard.html
│ ├── model_delete_confirm.html
│ ├── model_delete_selected_confirm.html
│ ├── model_detail.html
│ ├── model_form.html
│ ├── model_history.html
│ ├── model_list.html
│ ├── quick_detail.html
│ ├── quick_form.html
│ ├── recover_form.html
│ ├── recover_list.html
│ ├── revision_diff.html
│ └── revision_form.html
└── widgets
├── addform.html
├── base.html
├── chart.html
├── list.html
└── qbutton.html
Intégrer font awesome
La version font awesome intégrée ne propose pas toutes les icones. Vous pouvez importer le projet font awesome en modifiant le fichier base.html
backoffice/template/xadmin/base.html
<link rel="stylesheet" type="text/css" href="{% static "css/font-awesome.min.css" %}" />
N'oubliez pas d'ajouter le projet font-awesome dans votre dossier static .
Ajouter une ligne dans votre menu
Les menus sont construit dans le template sitemenu_default.html
backoffice/templates/xadmin/includes/sitemenu_default.html
<li class="nav-header">Actions</li> <li class="{% if request.path == "/xadmin/stats/" %}active{% endif %}"> <a href="{% url 'xadmin:stats' %}"><i class="fa-fw fa fa-line-chart"></i> Statistique</a> </li>
À noter que request.path nécessite une action de votre part expliquée dans le chapitre context processor .
Résultat:

Associer une icone à une vue
Les icones cercle par défaut sont assez fades, vous pouvez ajouter votre propres icones font awsome en renseignant l'attribut model_icon :
backoffice/adminx.py
class ProductAdmin(object): model = Product model_icon = "fa fa-barcode" class ProductAttributeAdmin(object): model= ProductAttribute model_icon = "fa fa-list-ol"
Résultat:
![]()
Manipuler depuis les valeurs POST envoyées
Vous pouvez redéfinir la méthode post pour ajouter des contrôles ou modifier des données lors de la soumission du formulaire.
backoffice/adminx.py
class ProductAdmin(object): model = Product def post(self, request, *args, **kwargs): try: self.instance_forms() self.setup_forms() if self.valid_forms(): self.message_user("Attention ceci et cela bla bla", 'warning') return self.get_response() except: pass return super(TicketAdmin, self).post(request, *args, **kwargs)
Pour info vous pouvez récupérer les données soumis par le formulaire via l' objet request .
Voici un exemple qui récupère le nombre d'items de product
nb = int(request.POST.get("productitem_set-TOTAL_FORMS", "0"))




