If someone actually wants to use it I can set aside some time within the next week or two to actually open source the whole thing (docs + source on github/pypi).
Here is an example of some of the basic functionality though: *What the following code does:* Creates a page for taking attendance of something that has 2 components, a listing component that lists existing attendees and a entry component that adds new people to the list. We have javascript that disables the default form action and on form submit submits via ajax. If there are errors, the form is displayed again with any errors showing (over ajax), if there aren't errors, it resets the form and also updates the listing component over ajax in a format like this (note, though we haven't extended ourselves, it was made so that you could send payloads other than "new_html" and make a custom handler for "framework_example_attendance_entry" that could do something other than simply dump new_html into the given div): { "actions": { "framework_example_attendance_entry": { "component_key": "framework_example_attendance_entry", "new_html": "<form method=\"POST\" action=\"/framework_example/\"> <div style=\"display:none\"> <input type=\"hidden\" name=\"csrfmiddlewaretoken\" value=\"....\"> </div> <p><label for=\"id_name\">Name:</label> <input id=\"id_name\" type=\"text\" name=\"name\" maxlength="75" /> <input type=\"hidden\" name=\"page_key\" value=\"framework_example_attendance_entry\" id=\"id_page_key\" /> <input type=\"hidden\" name=\"param_key\" id=\"id_param_key\" /> <input type=\"hidden\" name=\"version\" value=\"1\" id=\"id_version\" /></p> <input type=\"submit\"> </form>", "version": 1, "js_failure_mode": "no_warn_no_update" }, "framework_example_listing": { "component_key": "framework_example_listing", "new_html": "<ul> <li>George - Aug. 12, 2014, 1:46 p.m.</li> <li>Smith - Aug. 12, 2014, 1:46 p.m.</li> <li>Joseph - Aug. 12, 2014, 1:23 p.m. </li> <li>Steve - Aug. 12, 2014, 1:22 p.m.</li> <li>John - Aug. 12, 2014, 1:22 p.m.</li> <li>Andy - Aug. 12, 2014, 12:09 p.m.</li> <li>Sam - Aug. 12, 2014, 11:13 a.m.</li> </ul>", "version": 1, "js_failure_mode": "no_warn_no_update" } } } *views.py:* class AttendanceMixin(object): # We encourage using Mixins that contain @obj_cache decorated methods # that will (or in some cases may) be used by multiple components. @obj_cache def attendance_list(self): return list(AttendanceRecord.objects.order_by('-id')) @obj_cache def num_attendees(self): # This is free IFF we already need a list of attendees in the # request, otherwise we should be using # `AttendanceRecord.objects.count()` # Also note that it is fine to chain @obj_cache decorated methods. return len(self.attendance_list) class AttendanceEntryComponent(AttendanceMixin, Component): template_name = "framework_example/entry_component.html" def init(self): self.ctx.this_form_url = self.this_url() if not self.is_post(): self.ctx.attendance_form = AttendanceRecordForm( **self.form_init()) def handler(self, request): self.ctx.attendance_form = AttendanceRecordForm(request.POST, **self.form_init()) if self.ctx.attendance_form.is_valid(): self.ctx.attendance_form.save() self.ctx.attendance_form = AttendanceRecordForm( **self.form_init()) self.add_dependent_component(AttendanceListingComponent) return True def final(self): # The @obj_cache decorator turns methods into properties so note # that this isn't `self.num_attendees()` self.ctx.num_attendees = self.num_attendees class AttendanceListingComponent(AttendanceMixin, Component): template_name = "framework_example/listing_component.html" def init(self): self.ctx.attendance_list = self.attendance_list class AttendancePage(Page): template_name = "framework_example/attendance_page.html" def set_components(self): self.add_component(AttendanceListingComponent) *urls.py:* component_url(r'^attendance_listing/$', ComponentClass=AttendanceListingComponent, name="framework_example_listing"), component_url(r'^$', ComponentClass=AttendanceEntryComponent, name="framework_example_attendance_entry", PageClass=AttendancePage), *templates/framework_example/entry_component.html:* Add a new attendee (Currently {{ num_attendees }} attending) <form method="POST" action="{{ this_form_url }}"> {% csrf_token %} {{ attendance_form.as_p }} <input type="submit"> </form> *templates/framework_example/listing_component.html:* <ul> {% for attendance_record in attendance_list %} <li> {{ attendance_record.name }} - {{ attendance_record.arrival_time }} </li> {% endfor %} </ul> *templates/framework_example/attendance_page.html* {% extends "base.html" %} {% block content %} {% comment %} The surrounding div id follows a specific formula so it can be automatically updated on ajax requests: `cmp_<component_name>_id` {% endcomment %} <div id="cmp_framework_example_listing_id"> {% comment %} Similarly, you can grab the rendered html from the component by asking for `component_name` from the dictionary of rendered html `components`: {% endcomment %} {{ components.framework_example_listing }} </div> <div id="cmp_framework_example_attendance_entry_id"> {{ components.framework_example_attendance_entry }} </div> {% endblock content %} On Mon, Jun 1, 2015 at 11:54 PM, Emil Stenström <e...@kth.se> wrote: > On Monday, 1 June 2015 19:12:36 UTC+2, Sam Solomon wrote: >> >> So a former co-worker with some help/guidance from me developed a >> component system on top of Django that sounds sorta like what you are all >> talking about. It's very complicated and I'm still not sure whether it was >> ultimately a good idea to use or not, but it does make some things very >> simple (and we have no plans to move away from it at this point after ~2 >> years of use). I'll post some snippets from our internal docs on it now and >> if people are interested, I can explain more and possibly open source it >> <snip> >> > > Interesting! I would definitely want to see some code examples here. Could > you show me how me more about how it works? > > -- > You received this message because you are subscribed to a topic in the > Google Groups "Django developers (Contributions to Django itself)" group. > To unsubscribe from this topic, visit > https://groups.google.com/d/topic/django-developers/FmBM8VdxJ08/unsubscribe > . > To unsubscribe from this group and all its topics, send an email to > django-developers+unsubscr...@googlegroups.com. > To post to this group, send email to django-developers@googlegroups.com. > Visit this group at http://groups.google.com/group/django-developers. > To view this discussion on the web visit > https://groups.google.com/d/msgid/django-developers/5e562720-9484-4e4f-9507-129d55a4cfce%40googlegroups.com > <https://groups.google.com/d/msgid/django-developers/5e562720-9484-4e4f-9507-129d55a4cfce%40googlegroups.com?utm_medium=email&utm_source=footer> > . > > For more options, visit https://groups.google.com/d/optout. > -- You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group. To unsubscribe from this group and stop receiving emails from it, send an email to django-developers+unsubscr...@googlegroups.com. To post to this group, send email to django-developers@googlegroups.com. Visit this group at http://groups.google.com/group/django-developers. To view this discussion on the web visit https://groups.google.com/d/msgid/django-developers/CADGELX_0G%2BeyQLqzxa-enpVG_m10NeOcjyjiY_7b0c%2BbwHhqMQ%40mail.gmail.com. For more options, visit https://groups.google.com/d/optout.