Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Django Admin: Pushing the Pony's boundries (DjangoCon Europe 2015)

Django Admin: Pushing the Pony's boundries (DjangoCon Europe 2015)

Ce99ccbfed462de9b46953827df21fa5?s=128

Ola Sitarska

June 01, 2015
Tweet

Transcript

  1. PUSHING THE PONY’S BOUNDRIES

  2. BFF Ola + Admin ==

  3. None
  4. 6 years of building admin interfaces

  5. Ola Sitarska

  6. None
  7. DjangoCon Europe 2013 Django Girls Django Core Team DSF Board

  8. DjangoCon Europe 2013 Django Girls Django Core Team DSF Board

  9. DjangoCon Europe 2013 Django Girls Django Core Team DSF Board

  10. DjangoCon Europe 2013 Django Girls Django Core Team DSF Board

  11. ADMIN

  12. Insides of the admin Magic tricks Future of the admin

  13. before after

  14. HOW ADMIN WORKS

  15. AdminSite ModelAdmin ChangeList

  16. AdminSite ModelAdmin ChangeList

  17. AdminSite ModelAdmin ChangeList

  18. AdminSite encapsulates an instance of the Django admin application, ready

    to be hooked in to your URLconf.
  19. site = AdminSite() AdminSite: URLs

  20. url(r'^admin/', include(admin.site.urls)), AdminSite: URLs

  21. super_awesome_site = AdminSite() 
 url(r’^super-awesome-admin/', 
 include(super_awesome_site.urls)), AdminSite: URLs

  22. class AdminSite(object): … @property def urls(self): return self.get_urls(), ‘admin’, self.name

    AdminSite: URLs
  23. class AdminSite(object): … @property def get_urls(self): # Admin-site-wide urls urlpatterns

    = [ url(r'^$', wrap(self.index), name='index'), url(r'^login/$', self.login, name='login'), url(r'^logout/$', wrap(self.logout), 
 name='logout'), … AdminSite: URLs
  24. # Add in each model's views, and create a list

    of 
 # valid URLS for the app_index for model, model_admin in self._registry.items(): urlpatterns += [ url(r'^%s/%s/' % (model._meta.app_label, 
 model._meta.model_name), 
 include(model_admin.urls) ), ] AdminSite: URLs
  25. AdminSite: model registry from django.contrib import admin admin.site.register(Author, AuthorAdmin)

  26. AdminSite: model registry from django.contrib import admin admin.site.register(Author, AuthorAdmin) @admin.register(Author)

    class AuthorAdmin(admin.ModelAdmin):
  27. AdminSite: model registry from django.contrib import admin admin.site.register(Author, AuthorAdmin) @admin.register(Author)

    class AuthorAdmin(admin.ModelAdmin): admin.site.register(Author)
  28. AdminSite: model registry from django.contrib import admin admin.site.register(Author, AuthorAdmin) @admin.register(Author)

    class AuthorAdmin(admin.ModelAdmin): admin.site.register(Author) register(Author, list_display=(‘name’, ‘age’))
  29. AdminSite: basic config class AdminSite(object): # Text to put at

    the end of each page's <title>. site_title = ugettext_lazy('Django site admin') # Text to put in each page's <h1>. site_header = ugettext_lazy('Django administration') # Text to put at the top of the admin index page. index_title = ugettext_lazy('Site administration')
  30. ModelAdmin encapsulates all admin options and functionality for any given

    model.
  31. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  32. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  33. None
  34. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  35. None
  36. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  37. None
  38. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  39. None
  40. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  41. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  42. None
  43. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  44. None
  45. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  46. AdminSite ModelAdmin ChangeList

  47. Insides of the admin Magic tricks Future of the admin

  48. None
  49. None
  50. None
  51. None
  52. None
  53. Advanced permissions • organizers can edit only their own events

  54. None
  55. django-suit

  56. Advanced permissions class EventAdmin(admin.ModelAdmin): list_display = ('name', 'organizers', ‘date') search_fields

    = ('city', 'country', 'name') def get_queryset(self, request): qs = super(EventAdmin, self).queryset(request) if request.user.is_superuser: return qs return qs.filter(team=request.user)
  57. None
  58. None
  59. Advanced permissions def get_form(self, request, obj=None, **kwargs): form = super(EventPageContentAdmin,

    self).get_form(request, obj, **kwargs) if not request.user.is_superuser: if 'page' in form.base_fields: form.base_fields['page'].queryset = \ EventPage.objects.filter( event__team=request.user ) return form
  60. None
  61. Advanced permissions • organizers can edit only their own events

    • organizers can edit only future
 events
  62. ModelAdmin actions actions_on_top actions_on_bottom actions_selection_counter date_hierarchy exclude fields fieldsets filter_horizontal

    form formfield_overrides inlines list_display list_display_links list_editable list_filter list_max_show_all list_per_page list_select_related ordering paginator prepopulated_fields preserve_filters radio_fields raw_id_fields readonly_fields save_as save_on_top search_fields show_full_result_count view_on_site
  63. Advanced permissions def get_readonly_fields(self, request, obj=None): if obj and not

    request.user.is_superuser: if not obj.page.event.is_upcoming(): return set( [x.name for x in self.model._meta.fields] ) return self.readonly_fields
  64. None
  65. Custom method fields • display all organizers as list on

    ChangeList view
  66. Custom method fields class EventAdmin(admin.ModelAdmin): list_display = ('name', ‘get_organizers’, ‘date')

    … def get_organizers(self, obj): members = [] for member in self.team.all(): members.append( u’{name} <{email}>’.format( member.get_full_name(), member.email ) ) return ', '.join(members) get_organizers.short_description = “Organizers”
  67. None
  68. Custom method fields • display all organizers as list on

    ChangeList view • display status of the event
  69. Custom method fields class EventAdmin(admin.ModelAdmin): list_display = ('name', ‘is_event_over’, ‘date')

    … def is_event_over(self, obj): return not obj.is_upcoming() is_event_over.boolean = True
  70. None
  71. Custom method fields • display all organizers as list on

    ChangeList view • display status of the event • display images on a list in the ChangeList view
  72. Custom method fields class EventAdmin(admin.ModelAdmin): list_display = ('name', ‘get_logo_display’, ‘date')

    … def get_logo_display(self, obj): if obj.logo: return '<a href="{url}" target="_blank"><img src="{url}" width="100" /></a>'.format(self.logo.url) else: return 'No logo!' get_logo_display.allow_tags = True
  73. None
  74. Custom actions • a way to publish multiple events on

    the homepage with one click
  75. None
  76. Custom method fields class EventAdmin(admin.ModelAdmin): list_display = ('name', ‘get_logo_display’, ‘date’)

    actions = [‘show_on_homepage’] … def show_on_homepage(self, request, queryset): queryset.update(is_on_homepage=True) show_on_homepage.short_description = "Publish selected”
  77. DON’T FALL INTO the TRAP!

  78. DON’T: Use Django Admin as your user facing interface

  79. DON’T: Waste too much time trying to customize something

  80. DO: Make your managers and admins lifes easier with small

    tricks +
  81. DO: Make sure your admins can’t break the website with

    too much power ,
  82. Insides of the admin Magic tricks Future of the admin

  83. None
  84. I have to agree that the Django admin interface is

    dated and has some UI issues that could use work. — Jeff, May 2010
  85. None
  86. pip install django-flat-theme

  87. Diolch!

  88. @olasitarska ola@sitarska.com Diolch!