Why we chose to use Django admin, and how it worked, and, well, how it didn't work.
Django AdminWidgetry & WitcheryPamela Fox@pamelafoxThursday, August 30, 12
View Slide
Coursera: What we doThursday, August 30, 12
Our BackendThursday, August 30, 12
Why We Need AdminThursday, August 30, 12
Why Django Admin?Creates forms for adding/editing/searching modelsRestricts fields based on admin rolesThursday, August 30, 12
How Django Admin Workshttps://docs.djangoproject.com/en/dev/ref/contrib/admin/from django.contrib import adminfrom app import adminfrom app.courses.models import Coursefrom app.courses.forms import CourseAdminFormclass CourseAdmin(ModelAdmin):base_model = Courserestrict_fields = ['instructors', 'teaching_assistants', ]form = CourseAdminFormfieldsets = [(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 onhow it doesn’t work.Thursday, August 30, 12
☹: The Look & Feel!=Thursday, August 30, 12
Solution:Twitter Bootstraphttps://github.com/gkuhn1/django-admin-templates-twitter-bootstrapThursday, August 30, 12
☹: The Default WidgetsBooleanFieldCharFieldChoiceFieldTypedChoiceFieldDateFieldDateTimeFieldDecimalFieldEmailFieldFileFieldFilePathFieldFloatFieldImageFieldIntegerFieldIPAddressFieldGenericIPAddressFieldMultipleChoiceFieldTypedMultipleChoiceFieldNullBooleanFieldRegexFieldSlugFieldTimeFieldURLFieldComboFieldMultiValueFieldSplitDateTimeFieldModelChoiceFieldModelMultipleChoiceFieldThursday, August 30, 12
Solution:Custom WidgetsWysiHTMLEditorTransloaditUploadUniqueShortNameNumberField NumberRangeFieldAutoCompleteTextInputThursday, August 30, 12
Custom Widgetsclass 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"""%(input)s%(units)s""" % {'input': input, 'units': units}return mark_safe(html)admin/common/widgets.py:from django.forms import ModelFormfrom app.common.widgets import NumberFieldclass CourseAdminForm(ModelForm):class Meta:widgets = {'duration_string': NumberField(attrs={'units': 'weeks'})}course/forms.pyfrom app import adminfrom app.courses.models import Coursefrom app.courses.forms import CourseAdminFormclass CourseAdmin(ModelAdmin):base_model = Courseform = CourseAdminFormcourse/admin.pyThursday, August 30, 12
☹: Default Save Options!=Thursday, August 30, 12
Solution:Horrible Hacksvar 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 = $('').val(previewUrl);var $previewButton = $('');var $saveButton = $('.form-actions input[name="_save"]')$saveButton.after(' ').after($previewButton).after(' ').after($previewUrl);}templates/admin/change_form.htmlif "_saveandpreview" in request.POST:return HttpResponseRedirect(request.POST['_previewurl'])admin/options.pyThursday, 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-exampleThursday, August 30, 12