 Okay, so for those who don't know me, my name is Russell Keith McGee. My day job is as the CTO and co-founder of Trades Cloud We're a cloud provider of services software services for trades people so plumbers electricians people like that But that like I said is my day job The reason that I'm here is that I've been a core developer on the Django project since January of 2006 I've been president of the Django software foundation since 2010 The DSF as I said in my introduction this morning is the the IP legal and fundraising arm of the Django project So if you are interested if you were if you represent a company that has money I'd like to talk to you because because we need your money But that's why that's not why I'm here today today. I'm here to talk about class-based views Class-based views were introduced in Django 1.3, but have not been how should I put this greeted with universal enthusiasm? so Let's the reason I'm giving this talk and this is a Redo of a talk that I gave about a month ago at Django Con Australia I Want to clear up the mess what what our class-based views? Why do they exist and why should anyone care? Now I'd like to emphasize this isn't a tutorial It's an attempt to sort of set the big picture straight In the hope that by getting the big picture straight I'll be able to set some of the broader discussions about class-based views that I keep seeing on mailing lists and Twitter and things like that and Try set those discussions going in a slightly better direction or at least stop from being quite so badly wrong That's sort of the fundamentals of those discussions sometimes get based on So if we're talking big picture To explain why it is what we've got what we've got it helps to know where we've come from You know people who ignore history are doomed to repeat it. So Cast your mind back to the Halcyon days of 2005 To Django was introduced as a mechanism for building websites Views are there for displaying content. There are lots of common patterns in views that we all like being dry We like not repeating ourselves. So Django had this concept of of generic views They were they were added because we wanted those properties they weren't in Django's very original release They were added on July 25th 2005 release 304 so about two weeks after Django went public Class-based views or sorry generic views first landed in Django's code base And they were added because we had these common problems. We wanted to solve we want to avoid Reproducing the same code over and over again. So you refactor all the code you have You identify those key patterns generic views are there to do things like Display a template display a single object on a page display a list of objects on a page display a form With you know, the create update and delete kind of consequences of displaying a form display an archive of Objects based around date remember Django is coming from a journalism or a strong journalism background So a list of articles by date is a common problem that people were trying to solve Those generic views are then wrapped up instead of a in a sort of a have a coming of key features Each view is a function and you configure that function by passing in arguments to to control how you want that function to operate So for example a common This is sort of a running through the code that you would have written for an edits view for a book the the book The view you take a request object and you pass in the ID number of the book you want to edit You do a try-catch to or try accept to get to the book the book doesn't exist return a 404 If it's a post then we're actually saving the result of the form Okay, so we need to instantiate the form with the data from the request and the instance of the book We're trying to edit check that the form is valid how we provided all the information That's required if it is then save that form and then redirect to the URL for that particular book Fantastic if it's not a post request and we're going to assume that it's a get request generate the form for just the empty instantiated show us what the form should look like and render the That form and the object against some sort of template, okay? So absolutely boring vanilla code and if you would go and reproduce that code over and over and over again for every object Type that you wanted to edit You then take that view and you deploy it Into your old patterns, okay define a URL pattern that says I want to edit a book slash book slash ID Is where we're gonna go that view is the book view We're gonna call it edit book so we can do a URL and name-based URL look up And everything's all nice and happy. We've now got our view for editing a book into our project but then Generic views are there to say okay. Well that code is so cookie cutter It's so generic that we can replace that instead of talking about your generic I think your base idea of an update object. We're gonna replace a book view We're gonna replace it with this idea of updating an object and Configure it to say this update object will specifically we're gonna be updating books So we're gonna be looking for books based upon an object ID The name of the URL is exactly the same the operation of that function is exactly the same So instead of having to rewrite the boilerplate to update an object and have that try catch if post blah blah blah You can just say well here is a pre-canned version or all I need to drop in is the model which is a book Fantastic, which means that okay. We then we have books. We also want to be able to edit authors The only thing we need to change is Where the URL fits it's slash author instead of slash book The model that we're configuring is author rather than book and the name of the URL is edit author instead of edit book Okay, so that's you know the best best practices of code reuse find the thing that you're doing over and over and over again Factor it out into something generic and then configure it on each individual use fantastic so There are some problems though. Okay, so Configuration options the configuration options for that generic function view Unlimited by the arguments you can pass in okay So it is a function at the end of the day and we are passing in different arguments to make that thing happen if you want to instantiate a different form instead of you know a generic model form that's being being created you want to have a Very specific form be instantiated Based upon some sort of property of the object that you've actually retrieved. Well, you can't do that Do you want to perform some sort of logic after the form has been validated? But before the form is saved. Well, unless you can actually put that logic onto the forms save method itself You don't have an entry point to inject that logic Do you want to pass in extra arguments to the form instantiation like for example really something really simple like the request? Well, no unless you can put into a decorator or something like that You can't you can't do it Do you have common permissions logic that you want to run now this view or parts of the you're going to access this object If you have a particular permission unless you could put that on a decorator. You can't do it So how do we address these problems? Well, okay, you can keep adding new functional entry points So you can keep saying okay Well, here's another configuration another configuration argument another configuration argument or You can say okay with that configuration argument can actually be a callable and we can say okay Well, you pass in the function that you want to operate in this particular part of the function and you know get all completely You know met her and deep like that But at some point what you basically end up doing is poorly implementing half of the features of class inheritance So as an example of what I sort of think I'm talking about here in practice Let's we go back to our edit book example view you've written this code everyone has written this code at some point And it's really really easy to say well Okay, if the form is valid before we save do something. So, you know, we want to prepare the book before we actually save the form Trivial to do if you've got access to the full view almost impossible to do if you've got or you can't do it with the generic function-based views that were in Django as of 1.3 almost impossible to do in a clean way To extend those function-based views to make that use case really really easily So again, we must refactor all the things and instead of trying to pretend that we're going to implement class-based views by hacking them into a function Let's actually go class-based. Let's actually make these things classes Subclassing gives you these entry points. You can say I've got some behavior here My base behavior is to do nothing or to do a very simple thing But you can then subclass and add additional behavior that you want You can override specific pieces of logic You can use class mix-ins to compose behavior out of other out of a collection of objects And that's essentially what we did for Django 1.3 Now it turns out that although that's you know the high level architectural goal In practice, it turns out to be not quite that simple There are lots of little details that needed to get sorted out the discussion around class-based views went on for years There were several draft attempts made at landing something that was a class-based view Jacob Kaplan Moss tried, Joseph Cochran's tried, Ben Fershmann tried I am sort of the person who stands on the shoulders of giants there I'm responsible. I'm the person who did the final push and got building on top of the efforts of all those those gentlemen And finally ended up committing something for 1.3 So the architecture that I committed is most like the work that Ben did Ben built on top of what Joseph did Joseph built on top of what Jacob did Unfortunately, that's where the wheels fell off the whole process Why why did that happen? Well, there's a couple of reasons firstly There's a lot of confusion or there were a lot there has been a lot of confusion about what class-based views actually are and what they Should be or can be used for there's a lot of thought of that confusion is because there's two very distinct purposes in The code base around this sort of this one commit that was the feature that got landed in 1.3 And those two very distinct Purposes or two very distinct pieces of work were wrapped into a single commit and as a result sort of look like one feature The second problem is that the implementation isn't necessarily obvious It's the it's implemented with class-based views are implemented the way they are for a very specific reason But that reason leads to non-obvious complexity that if you come to the idea for the first time I think well, why is it being done this way? Isn't this other way wouldn't have made a lot more sense and been a lot more obvious There's a reason why it's not like that The third criticism that sort of has been levelled is something that's labeled ravioli code I'll come back to exactly what this means. It's a legitimate criticism that legitimate architectural criticism and I'll come sort of an explanation about what that means in a minute and Sort of the worst problem of all was that the documentation at the time it landed in 1.3 was to use the technical term bad I take full blame for that one I wrote the documentation that such that it was in 1.3 And it was not good documentation by any stretch of the imagination if anything else It's a it's a an abject lesson in the person who writes the code shouldn't be the person who documents it because it was obvious To me so wasn't it obvious to you guys Since since I landed my original documentation Mark Tamlin Danny Greenfield and a number of others have made some really big contributions and really big improvements in that area So that that situation at least has got a little bit better But the rest of them still exists. So let's let's go through them and try to clean up this wonderful mess what I made First off purpose there are two very distinct pieces of work Inside what is the feature of class-based views in Django 1.3? There are class-based views and there are class-based generic views When people talk about the commit it usually gets spoken about in terms of these class-based views But it is very two very distinct pieces of work Class-based views are a class-based analog of a view function They it has in embedded in it as part of the implementation method-based HTTP verb dispatch and that's it Okay, that is all a class-based view is it's a way of saying I've got a get request implement this piece of functionality or perform this piece of logic So for example, we go back to our this is this is essentially a class-based view Okay, it is a class my class is my view and it extends a base class called view You have a get method. Guess what if someone makes a get request That's the method that gets invoked if someone makes invokes a post request The post request is what gets invoked that is all class-based views are But because it is wrapped around a base class you get a whole bunch of interesting features for free You could get automated options handling So okay for those of you sort of aren't that familiar with HTTP or the internals of HTTP The HTTP verb is sort of the request you're the name of the thing you're asking the web server to do The ones that everyone knows about a get and post because it's kind of the read and the write Versions of what you're doing on the internet, but there's actually a whole bunch of other useful words Options is the way you ask what verbs can I use if I go to this URL? What can I do can I do a get can I do a post can I do a put can I do a delete can I do a trace? What options are available to me and you get that you get options handling for free when you use a class-based view because We know if you've defined a get method therefore you support gets You also get automatic naive head request handling now a head request is essentially a way of asking the server Hypothetically if I was to request this URL How big would it be give me the headers not the content just the headers for how big this request would be Which is then useful if you're doing so don't know performance optimization stuff for a large file delivery or something like that You can say how big is this content and then prepare yourself for how big that content is actually going to be You can implement that in a function-based view, but in a class-based view you can do a naive implementation I just do that you can just do the get request and then don't return the body content Okay, and you can get that for free You also automatically get HTTP 405 on any verb that isn't supported. So HTTP 405 is method not allowed So if you have got a view that you specifically do not want to allow get requests Just don't implement get and anyone who does a get request on that URL will get HTTP 405 Okay, that is particularly useful when you look at a function-based view Most people write a function-based view if you don't have any other logic in there Essentially, it doesn't matter whether you ask for a get put post options head The function-based view will return the same content which by strictly by the HTTP standard is not what it's supposed to do okay, so By doing it by having this class by structure you can deal with the verbs properly so that you can say no You can't do that when someone does something that you're not supposed to be doing Okay, so that's class-based views Layered on top of class-based views are class-based generic views these use the class-based view as as a base and Then create analogs of all of the old function-based generic views in Class in a class-based form Along the way addressing the limitations of the functional based approach So you can have the injection points you can have the extension points available to you using basic subclassing and mix-ins and all the nice things that you can do with object orientation Without having to go into this You know trying to invent a class-based views by passing in callable or passing in more more keyword arguments to the configuration of the function The catch is that by addressing those limitations of that of the approach of the functional approach Is that you introduce a whole new body of knowledge? It's now you need to understand the class structure for how generic class base or generic use work in order to be able to Do anything with them? That's the ravioli criticism essentially and I'll come again I'll come back to exactly why it's what that means and why the term ravioli gets used The second criticism that gets leveled against class-based views is the implementation choice The approach that we took is not the obvious one There are a couple of deployment things you have to do the way you put a class-based view into your URL patterns Looks a little odd It looks a little odd because it can't be done the obvious way that would be the obvious Approach just dropped the class in the view has some side effects and would require Either an overhead on a part of developers or an overhead on part on the part of the framework that we weren't willing to live with I won't go through the details of why we've done it the way we've done it The good news is that Django's wiki actually has a complete teardown of the history of the development of class-based views If you go to that URL what you will find is these are the 10 options We looked at here are the pros and cons of every one of them and this is why we chose this one Okay, so it's here is the design decision behind why we've got what we've got So if you if you're interested it's certainly worth a read and you can sort of find the find the backstory for why you Have to do as view Okay problem three ravioli This phrase came into being because one of actually one of Django's core developers guy named Luke Plant It's describing the fact of the end product that we've got or ravioli is sort of as a product is delicious and tasty And looks lovely unless it'll square packet or triangular packet that's sitting in your plate The internals however don't ask too many questions. They're kind of minced and unclear and may contain products You don't want to know about It also means that there's a price to becoming an expert unless you know what the internals were made off You can't just reproduce it Okay, you end up yes with a very attractive outside package But the inside you need expert knowledge to know how to make the inside of the ravioli Now this is an entirely legitimate criticism, you know the The the generic class-based views have a very very complex internal structure. There are lots of entry points There are there's there's all sorts of subclasses and mixings that come together to give you the final end product that is an update for you and Unfortunately in order to use them at all for anything other than the most trivial case you need to understand all of it and That means that the learning curve is hideously steep That then gets compounded when you have really bad documentation That doesn't explain how to get to the expert position really really quickly So yeah, the minimum quantum of knowledge to actually operate is much larger than it should be So Here's my ravioli cooking class 101 Let's have a look at our sort of pseudo code version of our original view here Here's an edit view we need to get an object if it's a post get the form if the form is valid Handle the form and redirect otherwise. We need to handle the failure in some way If we go back and it was a get request then we need to get the form and then we need to return a response So how does this manifest in our generic class-based view? That's the collection of mix-ins that go together to make that view happen. So let's step through them one by one And the internals right on the entire inside. We've got a single object mix in We are dealing with a view that will be returning a single object or it's dealing with a single object We need to put that single object into a context so that we can actually deal with that single object So we have a context mix-in which is subclassed into a single object mix-in Which essentially all it does is say I can make sure that I can render a single object on a page Yes, and that's basically doing the get object part of this picture. I'm dealing with a single object I need to be able to get an object Process form view is the bit that says okay. Well, this is a view that's dealing with forms That means I need to be able to deal with get posts and puts So let's make sure that I've got a get post and put entry point and that that then defers to whatever it is The rest of this form of this page is doing if it's dealing with a single object lots of objects I don't know but I need to be able to do get post and put and we'll defer everything else to subclasses What exactly are we going to do? Well, okay in this case We're dealing with a form the form needs to be handled and the way we deal with forms We need to instantiate a form and then we need to check the form is valid We need to handle the failure and we need to be able to instantiate the form when we have data When we don't have data but in particular this is a form that's been driven by a model So we need to be able to generate a model based form So we have a form mix in which contributes to the model form mix in the model form mix in knows that it's dealing with a single object So it is also bringing in the single object mix in to give you a model form dealing with a single object And then at the end of the day having handled the forgot the object handled the form dealt with it appropriately We need to give a response back to someone. We have a single object template response mix in which says given that I know I've got a single object in my context and it's been handled in an appropriate way Render it render that single object into a template Okay, and again the single object template response mix in is an extension of Template response mix in which is the generic I need to return a template the single object template response mix in is I need to return a template that deals with a single object So there we go simple nine classes to go and get your nine nine mix-ins to get you a simple view That allows you to do updating a single object with a form What's the problem? Okay, so but there's this is why it's so complicated Let's say we want to move from being an edit view to being a create view. What's the difference in the processing? Well fundamentally, it's exactly the same Except and instead of creating or getting an existing object We need to be able to instantiate a dummy object and then make sure that dummy object gets stable Here is the new object we want to create So all we really want to modify is the bit right at the beginning the get objects needs to turn into instantiate an object So all we need to do is change the base update view to a base create view that knows how to create objects rather than getting an existing one Okay, so the most of the code is exactly the same We just have to use one slightly different base class which knows how to instantiate rather than than retrieving from a database Okay, what about instead of creating we've got this create view instead of responding as a template We want to respond with jason content. We want to build an API. Well, okay The creation process still going to be dealing with a form We're still going to be dealing with instantiating an object all that stuff is the same The only thing that's different is down the bottom instead of rendering to a template We want to render to a jason response. So you can switch out The single template a single object template response mix in with a single object jason response mix in And all of a sudden starts generating jason content And everything else can get reused What does it look like when it actually gets deployed? Okay. Well, this is your generic function based view You're asking for update object you pass in the class We want to configure to the book and we give it a URL Effectively, this is all you're doing you're saying instead of Passing in the function update view You get the class update view and you say I want to use this as a view for the book model Okay, and this is the bit I was talking about the the that is not necessarily the obvious way to use a class There's a reason it needs to be done this way though So dig into the that wiki page I gave you if you want to if you want to see the reason why That is doing it in one line if you do whoever want to you know Bring it out as a class in your own that's essentially just shorthand for saying I've got this class called a book update view It extends generic update view and it's configured to use a particular model as a book And then you just say book update view dot as view and there you go You can deploy that, you know multiple times in your URL structure if you wanted to Okay, so but other than using up more lines of code Why would you want to pull this out as a separate class? Well the reason Is it then you can extend it yourself? So subclassing lets you dig into the internals and overwrite your own pieces of behavior if you want to So remember back when we said you couldn't inject logic into the process to say you know if this form is successful But before we save it we want to do some extra processing Well, okay, all you've got to do is say here's form valid by default form valid will save the form But we want to do Some processing first self dot object dot process and then just do whatever the base class wanted us to do Go off and save the form Okay, so you can easily inject logic in and all you need to do is override a single method You need to know that's the method you need to need to override But you override one method inject the logic into the flow where you want and off you go Okay, well, what about something more complex? Let's have a look at something like permissions Okay, you can use mixins to define behavior and then inject that behavior into any class you want So let's say we've got a really really complex permission scheme here based upon random number generation You want any attempts to access a single object to be checked against the dice roll And if you pass the dice roll then you're allowed to see the object Fantastic, all you've got to do is override the way that you get that single object By default the implementation of get object will go and get an object based upon the arguments that have been passed into the view Overwrite it put some extra logic in there to say if the random number exceeds whatever threshold Then you're allowed to see it otherwise return a 404. No, you're not or any other 404 if you want to do Any other htp response if you want and then all you've got to do is say, okay Well, there's my mixin it defines get object you can drop that into any view update view create you whatever You've got a reusable block of random based permissions logic To to inject into any view that you want to do it you want to handle that with Now as a side note the form valid method that I had on the previous slide you could have done that as a mixin as well It's just a question of how reusable a piece of logic is in practice a specific post-save behavior Probably doesn't have a lot of reuse potential. So an override in a subclass Makes a little bit of sense permission checking is something that's likely to you likely to have the same permission scheme In existence for all objects. So pull that into a mixin reuse that mixin over and over again so At the end of the day, you remember ravioli tastes good. There's a there's a reason the italians keep making it Ravioli allows ravioli code in this context Allows us to reuse core logic over and over again You only need to define once how do I get a single object and then you can reuse that logic everywhere You've got a view that deals with a single object. It's extremely flexible for inserting new logic. It's easy to add your own mixins but Unfortunately, you need to grok all the pieces to be able to know where you've got to go So like I said the technical term for the documentation state at time of delivery was bad It got all the details 100 correct, but completely missed the big picture It's kind of like the the joke about the the person sailing by In a in a hot air balloon goes past the the tall building yells out say, excuse me So can you tell me where am I and the guy says you're in a hot air balloon 100 meters off the ground Technically 100 correct utterly useless information So Yeah, the documentation mixed the big missed the big picture You still also need to make some framework decisions We have kind of not made at a project level a decision about whether we should be using class decorators So it takes something like a login required decor a login required mechanism easy to do on a class On a function base view you just wrap it with a decorator. It says login required Do you use a mix in do you use a class decorator? Do you use a method decorator on the class? There are there are multiple ways to skin that cat And as a result there's now kind of multiple ways to do it and no officially blessed Right way for as far as Django the project and our documentation is concerned So at one level as a core team we kind of need to Bite the bullet pick one and then encourage everyone to kind of run with it Okay, so where do we go from here? Documentation can always improve There are some high-level decisions that we probably need to make and then integrate that into documentation We can extend what is currently there. Like I said when we when we landed When we landed one point in 1.3 the generic class based views We very deliberately drew the line at replace what is there? We had a create view. We had an update view. We had We had that sort of basic set Let's just replace what's there. We know there are an infinite panoply of things we could build Let's sit to this deliver that and then we'll move on from there Now that leaves lots of new territory There are lots of additional class based generic views that could be built You know there there wasn't a function based generic view for handling form sets So there isn't a class based generic view for handling four sets either It's an obvious addition or object plus inline form set This that sort of thing it isn't an obvious It's an obvious construct to have because we do it in admin So there is room to expand and add those generic class based views into into Django and officially bless them So why haven't we added them in the intervening years? Well, first off, I need to ask the question. Have we solved the wrong problem here? We go back 30 odd slides I put up this list of Features of generic views and we need to be able to display a template We need to be able to do display a list a single object a list of objects a form We need to be able to create update delete objects. We need to be able to display a date archive These were all very very common problems in 2005, you know We were coming from a world where we had great big java-based websites that we all wanted to kill ourselves We had to deal with them and we've replaced it with this lightweight fresh framework Let's just build these functions really really easily because we were solving the problems we had in 2005 Modern websites have different problems or at least much more involved answers to the same problems A you know a genuine. Hey look, this is a this is a schmick modern website Has multiple forms and form sets per page It has continuous scrolling rather than pagination based Views of the world It will almost inevitably be dealing with Ajax at some level including things like in-place editing and in On-page live form validation of content You've go have things like pjax for navigation So like the github thing where you the page header is always there and you navigate and the URL changes But you're only really reloading part of the pages content You'll have the concept of having multiple actions per page You don't go to the create page to create You'll go to a page and you'll have a whole bunch of different actions You can do that you want to be able to interact with each one of them And then you've got you know rich javascript driven driven user interfaces where you've got You know the there yes, there is back-end data that's being provided to you But what you've got on the front end is is a rich api driven user interface The mood and to the emergence of things like react and angular and ember are kind of a This is what the tools we're using to build these front-end front-end tools and jango is kind of Historically said no, we're just a server side We don't deal with the front end But as a result we kind of haven't adapted well to these problems that exist and interacting with these with the front-end problems so In particular the api driven user interface is something that I I kind of want to harp on as an audience I think we can take it as a given that good websites, you know Good good software products that we're delivering these days have apis they're documented their version full first class Citizens of the ecosystem. We're trying to try to develop and like I said by delivering this as sort of part of the website experience You actually genuinely build an ecosystem it enables other people to remix and reuse the functionality of this website in ways that you as the person Who just delivered a user interface Possibly haven't envisaged or or conceived of And if you think about it, is there any reason that an appropriately authenticated automated process shouldn't be able to do everything That an appropriately authenticated actual human can do The easiest way to make this happen is to make the user interface and the api have functional parity And at the end point really a user interface is just a way to allow meat to invoke an api And then visualize the response of that in a way that meat can understand So why not make the api that the center what we're working on here completely aside from the sort of force multiplier benefits There's a simple engineering benefit because apis are easily tested And if the user interface is just invoking an api, then you've got a good conceptual separation between what it is We're actually trying to achieve that we can then test test seriously And we've got a user interface that needs to invoke that a user that api which we can test against You've got good separation there between the presentation of between the the actual Yeah, the the functionality you're trying to drive it gives you a testing boundary API driven user interfaces are you know really easy to generate in in jango. We've got apis are easy to generate We've got jango rest framework. We've got tasty pie and others that are out there But what we're missing are the views the the building the user interfaces We still need to be able to describe navigation and composition of various pieces of functionality on a page And all this I would argue requires that we have a strong base framework to work with And my argument is that class-based views provide that framework Not class-based generic views. I'm very strong at putting that out The class-based generic views are a great solution to the problem we had in 2005 I don't think the generic views we've got today are a great solution for today's problems But that doesn't mean that class-based views can't be the basis for what we do Why do I say that with confidence? Well to a certain level it's already being done Django contrib.admin is a class-based view. It doesn't eat Django's own dog food But it is class-based in that sense. You've got this object an admin object that you deploy into a url structure That then knows how to do other more interesting things Interestingly it's implemented using a single call method, which is one of the approaches that the Class-based views that we've delivered as part of 1.3 Rejected because there is actually some security implement implications in there Again dig into the documentation if you want to find about that or come and ask me and I can I can sort of delve a little bit into the details for that So we got a proof that we can build a class-based complex user interface Use class-based mechanisms to allow people to have extension points to add functionality to a complex user interface And I think this is something that's worth exploring a little bit more Django this however doesn't need necessarily to be part of Django's core Django's admin Was distributed as part of core, but that's kind of a conceit of the packaging infrastructure that existed in 2005 Which is to say that there wasn't packaging infrastructure in 2005 These days pip install Django foo works and everyone knows it works And everyone just has their requirements file and deploys websites to rely on it We could conceptually pull Django admin out into a completely separate package and then just have it automatically be installed when you install Django It's it's easy to do that kind of thing now with the state of setup tools being where it is So if we're going to genuinely replace admin or use admin as a testing ground for what we can do long-term instead of class-based structures We can do this completely outside of core Maybe with a long-term image of bringing in as a core managed project or something But exploring this idea of can we build rich user interfaces At a code level class-based with easy extension points and what have you to Support all of this api over here user interface control over here connected over the api layer This is something we can test bit outside of Django outside of core And then possibly bring in interesting parts of it into core as a long-term thing So Okay, there's sort of a call to action here If you are out in the field and you are discussing class-based views and class-based generic views Please be clear about which of those you are actually referring to if you're criticizing class-based views Are you criticizing class-based views or are you criticizing class-based generic views? I will heartily endorse anyone criticizing class-based generic views. They have they have a multitude of problems Criticizing class-based views, however You'll have a lot more struggle getting that argument across with me because I think there are much much stronger framework that people give a credit for Documentation can still be improved. So if you are interested in those class-based generic views or in just in class-based views for that matter There is a lot of work we could do to improve that documentation and we've got sprints coming up this weekend So if you feel like contributing that would certainly be a helpful way to contribute If you are interested in extending what is there, there are tickets things like 188 30 is a ticket that I've logged a while back But an idea called form collection ways of getting richer functionality Into class-based generic views without necessarily adding a whole new farm of of class-based generic view Mix-ins and what have you But also experiment experiment with apis this sort of broad idea of building Rich user interfaces at a functional level to say at Django's admin is really just a Deeply introspective, but it's really just a user interface to say here's a list of things we can get at and here Is a way of displaying an object and having multiple pieces of functionality with filtering and You know in place editing and in in place form submission This is an idea we can play around with I'm not saying I have any solutions I'm certainly interested in talking about it if anybody wants to talk about it I'm interested to talk about many things great length um, so Play around we know we don't have to to live with just because of the tools we've got are the tools we've got Django needs to continue to evolve or we run the risk of being Taken over by projects like meteor and node.js. And please I don't want to write javascript for the rest of my life But the only way we're going to be able to compete with meteor's demo of hey Look a live chat server in in in 10 minutes is to have a compelling counter example that we can build things much More complex than that in 10 minutes so from that If you've got questions, I'm happy to answer questions And hopefully I've ceded some ideas into the community and and said a few things straight about the state of class based views