Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Django Admin: Widgetry & Witchery

2,512 views

Published on

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

Django Admin: Widgetry & Witchery

  1. 1. Django AdminWidgetry & WitcheryPamela Fox@pamelafox
  2. 2. Coursera: What we do
  3. 3. Our Backend
  4. 4. Why We Need Admin
  5. 5. Why Django Admin?Creates forms for adding/editing/searching modelsRestricts fields based on admin roles
  6. 6. How Django Admin Works 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)https://docs.djangoproject.com/en/dev/ref/contrib/admin/
  7. 7. ...And a few words onhow it doesn’t work.
  8. 8. ☹: The Look & Feel !=
  9. 9. Solution: Twitter Bootstraphttps://github.com/gkuhn1/django-admin-templates-twitter-bootstrap
  10. 10. ☹: The Default WidgetsBooleanField FilePathField RegexFieldCharField FloatField SlugFieldChoiceField ImageField TimeFieldTypedChoiceField IntegerField URLFieldDateField IPAddressField ComboFieldDateTimeField GenericIPAddressField MultiValueFieldDecimalField MultipleChoiceField SplitDateTimeFieldEmailField TypedMultipleChoiceField ModelChoiceFieldFileField NullBooleanField ModelMultipleChoiceField
  11. 11. Solution: Custom WidgetsTransloaditUpload WysiHTMLEditorNumberField NumberRangeField AutoCompleteTextInput UniqueShortName
  12. 12. Custom Widgets admin/common/widgets.py: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) course/admin.py course/forms.pyfrom app import admin from django.forms import ModelFormfrom app.courses.models import Course from app.common.widgets import NumberFieldfrom app.courses.forms import CourseAdminForm class CourseAdminForm(ModelForm):class CourseAdmin(ModelAdmin): class Meta: base_model = Course widgets = { duration_string: NumberField( form = CourseAdminForm attrs={units: weeks}) }
  13. 13. ☹: Default Save Options !=
  14. 14. Solution: Horrible Hacks templates/admin/change_form.htmlvar 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="btnbtn-info">); var $saveButton = $(.form-actions input[name="_save"]) $saveButton.after(&nbsp;).after($previewButton) .after(&nbsp;).after($previewUrl);} admin/options.pyif "_saveandpreview" in request.POST: return HttpResponseRedirect(request.POST[_previewurl])
  15. 15. In conclusion...
  16. 16. Our Future Admin Stack?https://github.com/PaulUithol/backbone-tastypie https://github.com/joshbohde/django-backbone-example

×