Big Data, Better Decision
Michelle Leu @flywindy
PyCon Taiwan 2016 #PyConTW2016
那些年,
我⽤ Django Admin 接的案⼦
Once upon the time…
Facial bed –
The story has just begun
•  A chain of SPA (10+ branches)
•  Paper work -> Computer record
Why use Django Admin?
Django Admin - the automatic admin interface
•  Django 1.9 - big updates after 8 years
•  No requirements of design
•  It’s all about records
Agenda
•  Django Admin Overview
•  Scenario
•  User	permission	
•  Filter	Birthday	
•  Membership	
•  Customized UI
Django Admin Overview
AdminSite
ModelAdmin
 ChangeList
Scenario
Account
 Branch
m
 n
class	Account(models.Model):	
	
				name	=	models.CharField(max_length=50)	
				birthday	=	models.CharField(	
								max_length=5,	blank=True,	default='00.00',	
				)	
				mobile	=	models.CharField(max_length=20)	
				email	=	models.EmailField(blank=True)	
				…...	
				branches	=	models.ManyToManyField(	
								Branch,	
								through='Membership'	
				)	
	
class	Branch(models.Model):	
	
				name	=	models.CharField(max_length=50)	
				phone	=	models.CharField(max_length=15,	blank=True)	
				address	=	models.CharField(max_length=255,	blank=True)
User permission
Users:
•  Superuser – user management
•  Headquarters – all models
•  Brand managers – part of models about
records
Custom AdminSite
Why?
•  Root and login templates
•  Difference Admin URLs
hLp://localhost:8000/admin/
hLp://localhost:8000/
Custom AdminSite
Step:
1. Create an instance of your
AdminSite subclass
#	core/admin.py	
	
from	django.contrib	import	admin	
	
	
class	MyAdminSite(admin.AdminSite):	
				site_header	=	'My	Admin'	
				site_url	=	None	
				index_template	=	'admin/index.html'	
	
	
admin_site	=	MyAdminSite(name='myadmin')	
admin_site.disable_acSon('delete_selected')
Custom AdminSite
Step:
2. Register your models and
ModelAdmin subclasses with it
instead of using the default.
•  admin_site.register(Account,	AccountAdmin)	
	
•  @admin.register(Account,	site=admin_site)	
	class	AccountAdmin(admin.ModelAdmin):	
	…	
#	account/admin.py	
	
#	from	django.contrib	import	admin	
#	admin.site.register(Account)	
	
from	core.admin	import	admin_site	
admin_site.register(Account)
#	project/urls.py	
	
from	django.contrib	import	admin	
from	core.admin	import	admin_site	
	
urlpaLerns	=	[	
				url(r'^',	admin_site.urls),	
				url(r'^admin/',	admin.site.urls),	
]
3. Update urls.py
Filter Birthday
By months
•  SimpleListFilter
•  list_filter
#	account/admin.py	
	
class	BirthdayListFilter(admin.SimpleListFilter):	
				Stle	=	'Birthday	by	month'	
				parameter_name	=	'birthday'	
	
				def	lookups(self,	request,	model_admin):	
								return	(	
												('01',	'Jan'),	
												('02',	'Feb'),	
											…												
												('12',	'Dec'),	
								)	
	
				def	queryset(self,	request,	queryset):	
								if	self.value():	
												month	=	self.value()	+	'.'	
												return	queryset.filter(birthday__contains=month)	
	
	
class	AccountAdmin(admin.ModelAdmin):	
				list_filter	=	(BirthdayListFilter)
Membership
•  Many-to-many field #	account/models.py	
	
class	Membership(models.Model):	
				member_id	=	models.CharField(	
								max_length=20,	
								default='',	
								blank=True	
				)	
				account	=	models.ForeignKey(Account)	
				branch	=	models.ForeignKey(Branch)	
	
				def	__str__(self):	
								return	self.member_id
Account
 Branch
m
 n
Membership
Membership
•  list_display
•  list_display_links
•  A string representing an
attribute on the
ModelAdmin.
Account
 Branch
m
 n
Membership
#	account/admin.py	
	
class	AccountAdmin(admin.ModelAdmin):	
				list_display	=	('member_id',	'name',	'birthday',	'mobile')	
				list_display_links	=	('member_id',	'name')	
	
				def	member_id(self,	obj):	
								memberships	=	Membership.objects.filter(	
												account=obj,	
												branch__name=self.request.user.first_name	
								)	
								if	memberships.count()	>	0:	
												return	memberships[0].member_id	
								return	''
Membership
InlineModelAdmin
•  TabularInline
•  StackedInline
•  options
•  extra	
•  max_num	
•  min_num	
#	account/admin.py	
	
class	MembershipInline(admin.StackedInline):	
				model	=	Membership	
				extra	=	0	
				min_num	=	1	
	
	
class	AccountAdmin(admin.ModelAdmin):	
				inlines	=	(MembershipInline,)
Customized UI
Before overwriting
•  fieldsets
class	AccountAdmin(admin.ModelAdmin):	
				fieldsets	=	(	
								(None,	{	
												'fields':	(	
																'name',	'mobile',	'birthday',	
																('address',	'email'),	
												)	
								}),	
								('experience',	{	
												'classes':	('collapse',),	
												'fields':	('start_date',	'first_branch',	'source'),	
								}),	
				)
Before overwriting
•  date_hierarchy
•  DateField	or	DateTimeField	
#	account/admin.py	
	
class	AccountAdmin(admin.ModelAdmin):	
				date_hierarchy	=	'start_date'
Before overwriting
•  empty_value_display
•  New	in	Django	1.9	
•  The	default	value	is	-	(a	dash)	
•  format_html
•  raw_id_fields
•  Change	into	an	Input	widget	for	either	a	ForeignKey	or	
ManyToManyField	
def	colored_name(self):	
				return	format_html('<span	style="color:	#{};">{}	{}</span>',	
																							self.color_code,	
																							self.first_name,	
																							self.last_name)
Before overwriting
•  list_editable
•  Any	field	in	list_editable	must	also	be	in	list_display.	You	can’t	edit	a	field	that’s	not	displayed!	
•  The	same	field	can’t	be	listed	in	both	list_editable	and	list_display_links	–	a	field	can’t	be	both	a	form	
and	a	link.	
#	account/admin.py	
	
class	AccountAdmin(admin.ModelAdmin):	
				list_display	=	('member_id',	'name',	'birthday',	'mobile')	
				list_display_links	=	('member_id',	'name')	
				list_editable	=	('birthday',	'mobile')
Renaming
•  Model field - verbose_name
•  Models - Meta class
•  verbose_name	
•  verbose_name_plural	
•  App - AppConfig (Django 1.7+)
•  A string representing an attribute on the ModelAdmin ex: member_id
•  short_descripSon
Template Architecture
https://github.com/django/django/tree/master/
django/contrib/admin/templates/admin
base.html
base_site.html	
Index.html	
app_index.html		
login.html	
change_list.html		
change_form.html	
…
Overwrite templates
1.  Set up your projects admin template directories
•  templates/admin/	
2.  To override an admin template for a specific app
•  templates/admin/my_app/	
3.  Just overriding not replacing
•  block	
4.  Templates which may be overridden per app or model
•  app_index.html,	change_form.htm,		change_list.htm,		deleteconfirmaSon.html,	
object_history.html	
5.  Root and login templates – AdminSite
•  login_template,	logout_template,	password_change_template…
How to customize JS and CSS
a.  Overwrite base.html
b.  Define assets in ModelAdmin (the Media class)
class	ArScleAdmin(admin.ModelAdmin):	
				class	Media:	
								css	=	{	
												"all":	("my_styles.css",)	
								}	
								js	=	("my_code.js",)
django-admin-views
Easily link custom admin views and
direct URLs into the Django admin
Django admin packages
https://www.djangopackages.com
•  Django Suit - Django Girls Website
•  Django JET
Summary
When to use Django Admin
•  Design
•  write	you	view	and	tmeplate	
•  No design
•  Django	Admin	package	
•  Customize	your	django	admin		
Next
•  Python Web Meetup
PyCon Taiwan 2016 Talks
R0
Day	2		16:20	-	16:45	
	
Write	your	own	micro	data	
processing	framework	in	python	
CEO CTOGM
Django	Girls	Taipei	
hLp://djangogirls.org/taipei	
	
2016.06.04	BoF	X	PyLadies	
2016.07.09	Django	Girls	Workshop	#4		
Day	3		10:30	–	10:55	
	
Python	的 50	道陰影
Day	3		11:00	–	11:25	
	
Analyzing	Chinese	Lyrics	with	
Python
THANK YOU
info@gliacloud.com / 886 2 2752 8851
Unit.3, 11F., No.48, Fuxing N.Rd., Zhongshan Dist., Taipei City 104, Taiwan

那些年,我用 Django Admin 接的案子