Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Django Admin: Widgetry & Witchery
Search
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Pamela Fox
August 31, 2012
Technology
1.6k
4
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
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
More Decks by Pamela Fox
See All by Pamela Fox
Enterprise AI in 2025?
pamelafox
0
380
Fast-track your AI app development with GitHub and Azure
pamelafox
1
250
GitHub Universe: Evaluating RAG apps in GitHub Actions
pamelafox
0
570
Learn Live: Creating a Website using GitHub Copilot
pamelafox
1
340
O'Reilly Superstream: Building a RAG App to Chat with Your Data
pamelafox
1
480
AI Tour Mexico: Production-ready RAGwith Azure AI Search
pamelafox
1
440
AI Tour Mexico: Securing AI Apps on Azure
pamelafox
0
870
RAGHack: Kickoff and RAG 101
pamelafox
1
960
RAGHack: Building RAG apps in Python
pamelafox
1
540
Other Decks in Technology
See All in Technology
LLM Internals: 언어 모델의 계보와 알고리즘 진화 (2023~2026)
inureyes
PRO
0
550
同じWAFが、攻撃の“形”は弾く── 正当な“形”の不正は通す
kuroneko13
0
220
まちスペース®とデジタルツインと「まちづくり」
hiro_ogi
0
130
【AG-UI × A2UI × MCP Apps】Generative UIをやさしく解説する
nrinetcom
PRO
1
140
DatadogのBits Chatが開発組織にもたらしたもの / What Bits Chat Has Brought Us
sms_tech
1
280
Service Connect 上のサービスに ECS Service の外側から到達できなかった話
ota1022
1
270
研究開発部の紹介 / Sansan R&D Profile
sansan33
PRO
4
24k
2026-08-15 JAWS-UG 茨城 #16 Secrets ManagerにおけるSecret値の管理(Terraformの場合) / Secrets Manager Secrets
masasuzu
0
210
カートの信頼性を担保するWireMockを使ったe2eテスト
ykagano
0
390
AIコーディングの次。コードレビューと理解負荷を解消して組織の開発生産性を高める
moongift
PRO
2
2.6k
オートロックマンションなのに、各部屋は施錠なし!? 攻撃者が組織内ネットワークで大暴れする理由 / The Front Door Is Locked, but the Rooms Are Wide Open: Why Attackers Move Freely Inside Enterprise Networks
nttcom
1
6k
20260807_第6回_関東kaggler会LT_claw系bot xangiと始める、"寂しくない" kaggle
sugupoko
0
320
Featured
See All Featured
The untapped power of vector embeddings
frankvandijk
2
1.8k
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.7k
What's in a price? How to price your products and services
michaelherold
247
13k
The Mindset for Success: Future Career Progression
greggifford
PRO
0
450
"I'm Feeling Lucky" - Building Great Search Experiences for Today's Users (#IAC19)
danielanewman
230
23k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Lightning Talk: Beautiful Slides for Beginners
inesmontani
PRO
2
630
A Modern Web Designer's Workflow
chriscoyier
698
190k
Organizational Design Perspectives: An Ontology of Organizational Design Elements
kimpetersen
PRO
1
800
How to train your dragon (web standard)
notwaldorf
97
6.8k
Test your architecture with Archunit
thirion
1
2.3k
30 Presentation Tips
portentint
PRO
1
370
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