Package: classify
Generate concrete class API documentation for python Classes.Installation$pipinstallclassifyUsage$classify<python.path.to.Class>This outputs by default to your shell’s pager. However you can also generate an
HTML document to getCCBVstyle pages and even serve that document.By default HTML documents are saved to/path/to/current/dir/output.
To change this specify a relative location with the--outputoption.$classify<python.path.to.Class>--html[--output[--serve[--port]]]Why?CCBVhas long been part of my everyday toolkit for
working with Django’s class-based views, it’s a fantastic resource for quick
reference. But it only covers Django’s CBVs.Classify aims to be CCBV for all your Python classes.An Example$classifydjango.views.generic.CreateViewclassCreateView(SingleObjectTemplateResponseMixin,BaseCreateView):"""
    View for creating a new object instance,
    with a response rendered by template.
    """content_type=Nonecontext_object_name=Noneform_class=Nonehttp_method_names=[u'get',u'post',u'put',u'delete',u'head',u'options',u'trace']initial={}model=Nonepk_url_kwarg=pkqueryset=Noneresponse_class=<class'django.template.response.TemplateResponse'>slug_field=slugslug_url_kwarg=slugsuccess_url=Nonetemplate_name=Nonetemplate_name_field=Nonetemplate_name_suffix=_formdef__init__(self,**kwargs):"""
        Constructor. Called in the URLconf; can contain helpful extra
        keyword arguments, and other things.
        """# Go through keyword arguments, and either save their values to our# instance, or raise an error.forkey,valueinsix.iteritems(kwargs):setattr(self,key,value)@classonlymethoddefas_view(cls,**initkwargs):"""
        Main entry point for a request-response process.
        """# sanitize keyword argumentsforkeyininitkwargs:ifkeyincls.http_method_names:raiseTypeError("You tried to pass in the %s method name as a ""keyword argument to %s(). Don't do that."%(key,cls.__name__))ifnothasattr(cls,key):raiseTypeError("%s() received an invalid keyword %r. as_view ""only accepts arguments that are already ""attributes of the class."%(cls.__name__,key))defview(request,*args,**kwargs):self=cls(**initkwargs)ifhasattr(self,'get')andnothasattr(self,'head'):self.head=self.getself.request=requestself.args=argsself.kwargs=kwargsreturnself.dispatch(request,*args,**kwargs)# take name and docstring from classupdate_wrapper(view,cls,updated=())# and possible attributes set by decorators# like csrf_exempt from dispatchupdate_wrapper(view,cls.dispatch,assigned=())returnviewdefdispatch(self,request,*args,**kwargs):# Try to dispatch to the right method; if a method doesn't exist,# defer to the error handler. Also defer to the error handler if the# request method isn't on the approved list.ifrequest.method.lower()inself.http_method_names:handler=getattr(self,request.method.lower(),self.http_method_not_allowed)else:handler=self.http_method_not_allowedreturnhandler(request,*args,**kwargs)defform_invalid(self,form):"""
        If the form is invalid, re-render the context data with the
        data-filled form and errors.
        """returnself.render_to_response(self.get_context_data(form=form))defform_valid(self,form):"""
        If the form is valid, redirect to the supplied URL.
        """returnHttpResponseRedirect(self.get_success_url())defform_valid(self,form):"""
        If the form is valid, save the associated model.
        """self.object=form.save()returnsuper(ModelFormMixin,self).form_valid(form)defget(self,request,*args,**kwargs):"""
        Handles GET requests and instantiates a blank version of the form.
        """form_class=self.get_form_class()form=self.get_form(form_class)returnself.render_to_response(self.get_context_data(form=form))defget(self,request,*args,**kwargs):self.object=Nonereturnsuper(BaseCreateView,self).get(request,*args,**kwargs)defget_context_data(self,**kwargs):if'view'notinkwargs:kwargs['view']=selfreturnkwargsdefget_context_data(self,**kwargs):"""
        Insert the single object into the context dict.
        """context={}context_object_name=self.get_context_object_name(self.object)ifcontext_object_name:context[context_object_name]=self.objectcontext.update(kwargs)returnsuper(SingleObjectMixin,self).get_context_data(**context)defget_context_data(self,**kwargs):"""
        If an object has been supplied, inject it into the context with the
        supplied context_object_name name.
        """context={}ifself.object:context['object']=self.objectcontext_object_name=self.get_context_object_name(self.object)ifcontext_object_name:context[context_object_name]=self.objectcontext.update(kwargs)returnsuper(ModelFormMixin,self).get_context_data(**context)defget_context_object_name(self,obj):"""
        Get the name to use for the object.
        """ifself.context_object_name:returnself.context_object_nameelifisinstance(obj,models.Model):returnobj._meta.object_name.lower()else:returnNonedefget_form(self,form_class):"""
        Returns an instance of the form to be used in this view.
        """returnform_class(**self.get_form_kwargs())defget_form_class(self):"""
        Returns the form class to use in this view
        """returnself.form_classdefget_form_class(self):"""
        Returns the form class to use in this view.
        """ifself.form_class:returnself.form_classelse:ifself.modelisnotNone:# If a model has been explicitly provided, use itmodel=self.modelelifhasattr(self,'object')andself.objectisnotNone:# If this view is operating on a single object, use# the class of that objectmodel=self.object.__class__else:# Try to get a queryset and extract the model class# from thatmodel=self.get_queryset().modelreturnmodel_forms.modelform_factory(model)defget_form_kwargs(self):"""
        Returns the keyword arguments for instantiating the form.
        """kwargs={'initial':self.get_initial()}ifself.request.methodin('POST','PUT'):kwargs.update({'data':self.request.POST,'files':self.request.FILES,})returnkwargsdefget_form_kwargs(self):"""
        Returns the keyword arguments for instantiating the form.
        """kwargs=super(ModelFormMixin,self).get_form_kwargs()kwargs.update({'instance':self.object})returnkwargsdefget_initial(self):"""
        Returns the initial data to use for forms on this view.
        """returnself.initial.copy()defget_object(self,queryset=None):"""
        Returns the object the view is displaying.

        By default this requires `self.queryset` and a `pk` or `slug` argument
        in the URLconf, but subclasses can override this to return any object.
        """# Use a custom queryset if provided; this is required for subclasses# like DateDetailViewifquerysetisNone:queryset=self.get_queryset()# Next, try looking up by primary key.pk=self.kwargs.get(self.pk_url_kwarg,None)slug=self.kwargs.get(self.slug_url_kwarg,None)ifpkisnotNone:queryset=queryset.filter(pk=pk)# Next, try looking up by slug.elifslugisnotNone:slug_field=self.get_slug_field()queryset=queryset.filter(**{slug_field:slug})# If none of those are defined, it's an error.else:raiseAttributeError("Generic detail view %s must be called with ""either an object pk or a slug."%self.__class__.__name__)try:# Get the single item from the filtered querysetobj=queryset.get()exceptObjectDoesNotExist:raiseHttp404(_("No %(verbose_name)s found matching the query")%{'verbose_name':queryset.model._meta.verbose_name})returnobjdefget_queryset(self):"""
        Get the queryset to look an object up against. May not be called if
        `get_object` is overridden.
        """ifself.querysetisNone:ifself.model:returnself.model._default_manager.all()else:raiseImproperlyConfigured("%(cls)s is missing a queryset. Define ""%(cls)s.model, %(cls)s.queryset, or override ""%(cls)s.get_queryset()."%{'cls':self.__class__.__name__})returnself.queryset._clone()defget_slug_field(self):"""
        Get the name of a slug field to be used to look up by slug.
        """returnself.slug_fielddefget_success_url(self):"""
        Returns the supplied success URL.
        """ifself.success_url:# Forcing possible reverse_lazy evaluationurl=force_text(self.success_url)else:raiseImproperlyConfigured("No URL to redirect to. Provide a success_url.")returnurldefget_success_url(self):"""
        Returns the supplied URL.
        """ifself.success_url:url=self.success_url%self.object.__dict__else:try:url=self.object.get_absolute_url()exceptAttributeError:raiseImproperlyConfigured("No URL to redirect to.  Either provide a url or define"" a get_absolute_url method on the Model.")returnurldefget_template_names(self):"""
        Returns a list of template names to be used for the request. Must return
        a list. May not be called if render_to_response is overridden.
        """ifself.template_nameisNone:raiseImproperlyConfigured("TemplateResponseMixin requires either a definition of ""'template_name' or an implementation of 'get_template_names()'")else:return[self.template_name]defget_template_names(self):"""
        Return a list of template names to be used for the request. May not be
        called if render_to_response is overridden. Returns the following list:

        * the value of ``template_name`` on the view (if provided)
        * the contents of the ``template_name_field`` field on the
          object instance that the view is operating upon (if available)
        * ``<app_label>/<object_name><template_name_suffix>.html``
        """try:names=super(SingleObjectTemplateResponseMixin,self).get_template_names()exceptImproperlyConfigured:# If template_name isn't specified, it's not a problem --# we just start with an empty list.names=[]# If self.template_name_field is set, grab the value of the field# of that name from the object; this is the most specific template# name, if given.ifself.objectandself.template_name_field:name=getattr(self.object,self.template_name_field,None)ifname:names.insert(0,name)# The least-specific option is the default <app>/<model>_detail.html;# only use this if the object in question is a model.ifisinstance(self.object,models.Model):names.append("%s/%s%s.html"%(self.object._meta.app_label,self.object._meta.object_name.lower(),self.template_name_suffix))elifhasattr(self,'model')andself.modelisnotNoneandissubclass(self.model,models.Model):names.append("%s/%s%s.html"%(self.model._meta.app_label,self.model._meta.object_name.lower(),self.template_name_suffix))returnnamesdefhttp_method_not_allowed(self,request,*args,**kwargs):logger.warning('Method Not Allowed (%s): %s',request.method,request.path,extra={'status_code':405,'request':self.request})returnhttp.HttpResponseNotAllowed(self._allowed_methods())defoptions(self,request,*args,**kwargs):"""
        Handles responding to requests for the OPTIONS HTTP verb.
        """response=http.HttpResponse()response['Allow']=', '.join(self._allowed_methods())response['Content-Length']='0'returnresponsedefpost(self,request,*args,**kwargs):"""
        Handles POST requests, instantiating a form instance with the passed
        POST variables and then checked for validity.
        """form_class=self.get_form_class()form=self.get_form(form_class)ifform.is_valid():returnself.form_valid(form)else:returnself.form_invalid(form)defpost(self,request,*args,**kwargs):self.object=Nonereturnsuper(BaseCreateView,self).post(request,*args,**kwargs)defput(self,*args,**kwargs):returnself.post(*args,**kwargs)defrender_to_response(self,context,**response_kwargs):"""
        Returns a response, using the `response_class` for this
        view, with a template rendered with the given context.

        If any keyword arguments are provided, they will be
        passed to the constructor of the response class.
        """response_kwargs.setdefault('content_type',self.content_type)returnself.response_class(request=self.request,template=self.get_template_names(),context=context,**response_kwargs)