Upload
alexgaynor
View
214
Download
0
Embed Size (px)
Citation preview
8/8/2019 Rethinking the Reusable Apps
1/31
Rethinking the Reusable
Application ParadigmAlex Gaynor
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
2/31
I work here.Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
3/31
I work with these guys.Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
4/31
We do a lot of this.Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
5/31
You have been sold alie!
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
6/31
By this man!Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
7/31
The dangerous lie:
defmy_view(request, pk, template_name="my_app/my_page.html", form_class=MyForm,
redirect_url="/home/place/"):
# magical view stuff here return HttpResponse()
This does not, a reusable app, make.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
8/31
That doesnt mean its useless.
But it doesnt solve all the problems.What the hell are the problems were trying to solveanyways?
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
9/31
Similar patterns across many sites (tagging, voting,commenting, etc.).
Write once, use everywhere.
No need to reinvent the wheel.
Why Reusable Apps?
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
10/31
The problems.
Differing business logic.
Everyone wants comments, but can anonymous userscomment, is there a comment preview page?
Differing data storage
Does a forum belong to a group, does it need a slug? Docategories have an icon?
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
11/31
The Solutions
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
12/31
Class based views
See Ben Firshman at 2:20: Alternate ViewsSimple view functions dont provide entry points forchanging logic, besides what you create a parameter for.
Subclass to change the logic, e.g. the admin.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
13/31
django.contrib.admin
classArticleAdmin(admin.ModelAdmin):
defsave_model(self, request, obj, form, change):
obj.user = request.userobj.save()
Theres like 30 of these.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
14/31
Do Less
aka: reusable frameworksCreate a framework, so other people can write their buisnesslogic around it.
Example: badges.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
15/31
Badges
Can badges have multiple levels?How do you know if a user has received a given badge, at agiven level?
Can a user receive a badge more than once?
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
16/31
The stuff everyone needs...
Templatetags for getting badge count or list of badges for auser.
Queueing of computations, when theyre expensive.
Persistence.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
17/31
brabeionclassPointsBadge(Badge):
slug ="points"
levels = [
"Bronze",
"Silver",
"Gold",
]events = [
"points_awarded",
]
multiple =False
defaward(self, user, **state):
points = user.profile.points
if points >10000:
return BadgeAwarded(level=3)
elif points >7500:
return BadgeAwarded(level=2)
elif points >5000:
return BadgeAwarded(level=1)
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
18/31
Be flexible
You cant predict all the ways people want to use yoursoftware.
But you know what the common way is (probably whatever
you wanted to do in the first place).So provide a default, but let people swap it out.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
19/31
django-taggit
classEvent(models.Model):
title = models.CharField(max_length=100)
date = models.DateField()
tags = TaggableManager()
Common case: I want some tags on my stuff.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
20/31
Uncommon cases
Non-integer primary keys (IntegerField for the
GenericForeignKey, by default)
Per-user tags.
Official tags.Custom caching managers, or anything else.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
21/31
classEventTaggedItems(BaseTaggedItem):
event = models.ForeignKey("Event")
classEvent(models.Model):
title = models.CharField(max_length=100, primary_key=True)
date = models.DateField()
tags = TaggableManager(through=EventTaggedItems)
Swap out the intermediary model (also the Tag model)
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
22/31
Custom backends
django-registration
django.core.cache
django.contrib.auth
django.core.files
django.contrib.sessions
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
23/31
django-registrationclassSimpleBackend(object): defregister(self, request, **kwargs):
username, email, password = kwargs['username'], kwargs['email'], kwargs['password1']
User.objects.create_user(username, email, password)
# authenticate() always has to be called before login(), and
# will return the user we just created.
new_user = authenticate(username=username, password=password)
login(request, new_user)
signals.user_registered.send(sender=self.__class__,user=new_user,
request=request)
return new_user
defactivate(self, **kwargs):
raiseNotImplementedError
defregistration_allowed(self, request):
returngetattr(settings, 'REGISTRATION_OPEN', True)
defget_form_class(self, request):
return RegistrationForm
defpost_registration_redirect(self, request, user):
return (user.get_absolute_url(), (), {})
defpost_activation_redirect(self, request, user):
raiseNotImplementedError
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
24/31
Libraries
Not everything is business logic
Tools for other people
e.g.: django.forms
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
25/31
django-filtersclassProductFilterSet(django_filters.FilterSet):
classMeta:
model = Product
fields = ['name', 'price', 'manufacturer']
Create filters like the admins list_filter.Built on top of django.forms
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
26/31
Other Tools
django-fixture-generator
Generate fixtures programatically.django-templatetag-sugar
A declarative API for creating templatetags.
django_compressor
Compress and combine static media (CSS + JS)
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
27/31
When to ignore all ofthis
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
28/31
Well defined problem spaces.
Extremely common use cases.
You just dont care about the 20% (internal apps?)
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
29/31
user_messages
Internal Eldarion app
Allows user to send messages to other users.
Almost no customizability.
Only control is to enable multi-user messaging or not.
Dead simple to use.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
30/31
0 flexibility, 0 work
Add to INSTALLED_APPSAdd to urls.py
Write templates.
Done.
Monday, September 6, 2010
8/8/2019 Rethinking the Reusable Apps
31/31
Questions?
http://alexgaynor.net
http://alexgaynor.net/http://alexgaynor.net/http://alexgaynor.net/