Django Admin: Widgetry & Witchery

92dfeb863138a5a9c0453ed80f9c8c75?s=47 Pamela Fox
August 31, 2012

Django Admin: Widgetry & Witchery

Why we chose to use Django admin, and how it worked, and, well, how it didn't work.

92dfeb863138a5a9c0453ed80f9c8c75?s=128

Pamela Fox

August 31, 2012
Tweet

Transcript

  1. Django Admin Widgetry & Witchery Pamela Fox @pamelafox Thursday, August

    30, 12
  2. Coursera: What we do Thursday, August 30, 12

  3. Our Backend Thursday, August 30, 12

  4. Why We Need Admin Thursday, August 30, 12

  5. Why Django Admin? Creates forms for adding/editing/searching models Restricts fields

    based on admin roles Thursday, August 30, 12
  6. 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
  7. ...And a few words on how it doesn’t work. Thursday,

    August 30, 12
  8. ☹: The Look & Feel != Thursday, August 30, 12

  9. Solution: Twitter Bootstrap https://github.com/gkuhn1/django-admin-templates-twitter-bootstrap Thursday, August 30, 12

  10. ☹: 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
  11. Solution: Custom Widgets WysiHTMLEditor TransloaditUpload UniqueShortName NumberField NumberRangeField AutoCompleteTextInput Thursday,

    August 30, 12
  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
  13. ☹: Default Save Options != Thursday, August 30, 12

  14. 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('&nbsp;').after($previewButton) .after('&nbsp;').after($previewUrl); } templates/admin/change_form.html if "_saveandpreview" in request.POST: return HttpResponseRedirect(request.POST['_previewurl']) admin/options.py Thursday, August 30, 12
  15. In conclusion... Thursday, August 30, 12

  16. Our Future Admin Stack? https://github.com/PaulUithol/backbone-tastypie https://github.com/joshbohde/django-backbone-example Thursday, August 30, 12