Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Django Admin: Widgetry & Witchery
Search
Pamela Fox
August 31, 2012
Technology
4
1.6k
Django Admin: Widgetry & Witchery
Why we chose to use Django admin, and how it worked, and, well, how it didn't work.
Pamela Fox
August 31, 2012
Tweet
Share
More Decks by Pamela Fox
See All by Pamela Fox
Enterprise AI in 2025?
pamelafox
0
280
Fast-track your AI app development with GitHub and Azure
pamelafox
1
180
GitHub Universe: Evaluating RAG apps in GitHub Actions
pamelafox
0
470
Learn Live: Creating a Website using GitHub Copilot
pamelafox
1
260
O'Reilly Superstream: Building a RAG App to Chat with Your Data
pamelafox
1
410
AI Tour Mexico: Production-ready RAGwith Azure AI Search
pamelafox
1
360
AI Tour Mexico: Securing AI Apps on Azure
pamelafox
0
790
RAGHack: Kickoff and RAG 101
pamelafox
1
780
RAGHack: Building RAG apps in Python
pamelafox
1
450
Other Decks in Technology
See All in Technology
【U/day Tokyo 2025】Cygames流 最新スマートフォンゲームの技術設計 〜『Shadowverse: Worlds Beyond』におけるアーキテクチャ再設計の挑戦~
cygames
PRO
2
680
Kiro を用いたペアプロのススメ
taikis
1
190
Database イノベーショントークを振り返る/reinvent-2025-database-innovation-talk-recap
emiki
0
230
SREには開発組織全体で向き合う
koh_naga
0
370
AI駆動開発における設計思想 認知負荷を下げるフロントエンドアーキテクチャ/ 20251211 Teppei Hanai
shift_evolve
PRO
2
420
AWS運用を効率化する!AWS Organizationsを軸にした一元管理の実践/nikkei-tech-talk-202512
nikkei_engineer_recruiting
0
100
CARTAのAI CoE が挑む「事業を進化させる AI エンジニアリング」 / carta ai coe evolution business ai engineering
carta_engineering
0
1.9k
NIKKEI Tech Talk #41: セキュア・バイ・デザインからクラウド管理を考える
sekido
PRO
0
150
Lessons from Migrating to OpenSearch: Shard Design, Log Ingestion, and UI Decisions
sansantech
PRO
1
150
寫了幾年 Code,然後呢?軟體工程師必須重新認識的 DevOps
cheng_wei_chen
1
1.5k
AWS re:Invent 2025で見たGrafana最新機能の紹介
hamadakoji
0
420
30分であなたをOmniのファンにしてみせます~分析画面のクリック操作をそのままコード化できるAI-ReadyなBIツール~
sagara
0
180
Featured
See All Featured
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
7.9k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
Become a Pro
speakerdeck
PRO
31
5.7k
Measuring & Analyzing Core Web Vitals
bluesmoon
9
710
Building Adaptive Systems
keathley
44
2.9k
A designer walks into a library…
pauljervisheath
210
24k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
3.3k
The Hidden Cost of Media on the Web [PixelPalooza 2025]
tammyeverts
1
110
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.6k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
9
1.1k
Improving Core Web Vitals using Speculation Rules API
sergeychernyshev
21
1.3k
Transcript
Django Admin Widgetry & Witchery Pamela Fox @pamelafox Thursday, August
30, 12
Coursera: What we do Thursday, August 30, 12
Our Backend Thursday, August 30, 12
Why We Need Admin Thursday, August 30, 12
Why Django Admin? Creates forms for adding/editing/searching models Restricts fields
based on admin roles Thursday, August 30, 12
How Django Admin Works https://docs.djangoproject.com/en/dev/ref/contrib/admin/ from django.contrib import admin from
app import admin from app.courses.models import Course from app.courses.forms import CourseAdminForm class CourseAdmin(ModelAdmin): base_model = Course restrict_fields = ['instructors', 'teaching_assistants', ] form = CourseAdminForm fieldsets = [ (None, { 'fields': [ 'name', 'topic', 'active', ] }), ('Dates', { 'fields': [ 'start_date', 'end_date', 'start_date_string', 'duration_string', ] }) ] admin.site.register(Course, CourseAdmin) Thursday, August 30, 12
...And a few words on how it doesn’t work. Thursday,
August 30, 12
☹: The Look & Feel != Thursday, August 30, 12
Solution: Twitter Bootstrap https://github.com/gkuhn1/django-admin-templates-twitter-bootstrap Thursday, August 30, 12
☹: The Default Widgets BooleanField CharField ChoiceField TypedChoiceField DateField DateTimeField
DecimalField EmailField FileField FilePathField FloatField ImageField IntegerField IPAddressField GenericIPAddressField MultipleChoiceField TypedMultipleChoiceField NullBooleanField RegexField SlugField TimeField URLField ComboField MultiValueField SplitDateTimeField ModelChoiceField ModelMultipleChoiceField Thursday, August 30, 12
Solution: Custom Widgets WysiHTMLEditor TransloaditUpload UniqueShortName NumberField NumberRangeField AutoCompleteTextInput Thursday,
August 30, 12
Custom Widgets class NumberField(HiddenInput): class Media: js = ( settings.ADMIN_MEDIA_PREFIX
+ 'js/numberfields.js', ) def render(self, name, value, attrs=None): input = super(NumberField, self).render(name, value, attrs=attrs) final_attrs = self.build_attrs(attrs) units = final_attrs.get('units', '') html = u""" <div class="number-field"> %(input)s <input type="number" min="1" class="number-range-field-num input-mini"> <span class="number-range-field-units">%(units)s<span> </div> """ % {'input': input, 'units': units} return mark_safe(html) admin/common/widgets.py: from django.forms import ModelForm from app.common.widgets import NumberField class CourseAdminForm(ModelForm): class Meta: widgets = { 'duration_string': NumberField( attrs={'units': 'weeks'}) } course/forms.py from app import admin from app.courses.models import Course from app.courses.forms import CourseAdminForm class CourseAdmin(ModelAdmin): base_model = Course form = CourseAdminForm course/admin.py Thursday, August 30, 12
☹: Default Save Options != Thursday, August 30, 12
Solution: Horrible Hacks var topicPageRegEx = /\/topics\/topic\//i; var isTopicPage =
topicPageRegEx.exec(window.location.href); if (isTopicPage) { var previewHosts = {'admin': 'site', 'admin.coursera.org': 'www.coursera.org'}; var previewUrl = 'http://' + previewHosts[window.location.host] + '/course/' + $ ('input[name="short_name"]').val(); var $previewUrl = $('<input type="hidden" name="_previewurl">').val(previewUrl); var $previewButton = $('<input type="submit" name="_saveandpreview" value="Save and Preview" class="btn btn-info">'); var $saveButton = $('.form-actions input[name="_save"]') $saveButton.after(' ').after($previewButton) .after(' ').after($previewUrl); } templates/admin/change_form.html if "_saveandpreview" in request.POST: return HttpResponseRedirect(request.POST['_previewurl']) admin/options.py Thursday, August 30, 12
In conclusion... Thursday, August 30, 12
Our Future Admin Stack? https://github.com/PaulUithol/backbone-tastypie https://github.com/joshbohde/django-backbone-example Thursday, August 30, 12