Concepts in Django
Douwe van der Meij
Goldmund, Wyldebeast & Wunderliebe
[email protected]/douwevandermeij
Project
INSTALLED_APPS = ( ... 'crm', 'webshop', ...)
Dependencies
crm
webshop
Customer
Order
● Inter-app foreign key constraint
● How to reuse webshop without crm?
Project
OrderLine
account_nr
order_nr
Define:
● Producers○ Contain data
● Consumers○ Don’t contain data○ Need a producer
Concepts
Producer
Consumer
Customer concept
The concept we’re talking about:
● A customer○ Has a number
Applications with concepts
crm
Customer
webshop
Customer Order
Producer
Consumer
account_nrProject
OrderLinenumber
Define Producers
CONCEPTS = { 'CustomerConcept': { 'crm.models.Customer': { 'number': 'account_nr', }, },}
● Map to existing models
Conceptname
Producer model
Field mapping
Consume
class Order(models.Model): customer = models.ForeignKey(CustomerConcept) order_nr = models.IntegerField()
Dependenciescrm
Customer Project
concepts
CustomerConcept
webshop
Customer
Order
● ORM level
Dependencies
webshop
Customer
Order
crm
Customer Project
● Database level
The magic (1/4)
from django.conf import settings
for concept_name, mapping in settings.CONCEPTS.items(): for klass, fields in mapping.items(): ...
● The concepts app○ Loops over settings.CONCEPTS
The magic (2/4)
from concepts.util import load_class
...concept = type( concept_name, (load_class(klass),), { '__module__': __name__, 'Meta': type('Meta', (), {'proxy': True}), },)...
● Create a dynamic class● With proxy = True in Meta
The magic (3/4)
...for _property, _field in fields.items(): if not hasattr(concept, _property): setattr( concept, _property, property( lambda self: getattr(self, _field), lambda self, value: setattr(self, _field, value), ), )...
● Create properties for all fields
The magic (4/4)
import concepts
...setattr(concepts, concept_name, concept)
● Bind the concept to the concepts module
● Concepts make apps reusable○ Without dependencies
● The only dependency○ Is a concept
● The concept producer○ You may choose yourself○ On existing apps
Conclusion
● github.com /douwevandermeij /
concepts_example
● Related work○ Django Swappable Models
■ Like swapping auth.User model in 1.5+○ Zope Component Architecture
■ Interfaces: implement/adapt
Try it yourself