ݺߣ

ݺߣShare a Scribd company logo
Introduction    Forms   Authentication          Generic Views   Caching   Others   Admin




               Web Development Paradigms and djangoic
                    approach to deal with them.

                                  Lakshman Prasad

                                         Agiliq Solutions




                                September 25, 2010
Concepts and abstractions used to represent elements of a program
Web Development Paradigms: Modeling common web patterns
Why?
Web Development Paradigms and djangoic approach to deal with them
Batteries Included
docs.djangoproject.com
Webapp: Simple web application framework (with custom APIs)
Lets examine the batteries
Introduction      Forms    Authentication   Generic Views   Caching   Others   Admin



          How do I know about web development or django
           ? Active Djangonaut
           ? Part of a few popular open source django applications
               github.com/becomingGuru, github.com/agiliq

           ? Consulting and Development via
           ? Developed several custom proprietory django applications




           ? @becomingGuru
Introduction     Forms   Authentication   Generic Views   Caching   Others   Admin




       Introduction

       Forms

       Authentication

       Generic Views

       Caching

       Others

       Admin
Forms
Save form data to a table
Introduction    Forms       Authentication   Generic Views   Caching     Others   Admin



                                 Use a Model Form


      >>> from d j a n g o . f o r m s import ModelForm

      # C r e a t e t h e form c l a s s .
      >>> c l a s s A r t i c l e F o r m ( ModelForm ) :
       ...         c l a s s Meta :
       ...                 model = A r t i c l e

      # C r e a t i n g a form t o add an a r t i c l e .
      >>> form = A r t i c l e F o r m ( )

      # C r e a t i n g a form t o c h an ge an e x i s t i n g a r t i c l e .
      >>> a r t i c l e = A r t i c l e . o b j e c t s . g e t ( pk=1)
      >>> form = A r t i c l e F o r m ( i n s t a n c e= a r t i c l e )
Models
Introduction       Forms        Authentication      Generic Views    Caching           Others   Admin



                                          Model Syntax

       from d j a n g o . db import m o d e l s

       c l a s s P o s t ( m o d e l s . Model ) :
               t i t l e = m o d e l s . C h a r F i e l d ( m a x l e n g t h =100)
               t e x t = models . T e x t F i e l d ( )
               datetime = models . DateTimeField ( )

               c l a s s Meta :
                       o r d e r i n g = ( ?d a t e t i m e  , )

               def      unicode ( self ):
                      return s e l f . t i t l e

       c l a s s Comment ( m o d e l s . Model ) :
               post = models . ForeignKey ( Post )
               t e x t = models . T e x t F i e l d ( )
Introduction     Forms       Authentication    Generic Views     Caching    Others   Admin



                                          Model API




      >>>from b l o g . m o d e l s import Post , Comment
      >>>p o s t = P o s t . o b j e c t s . a l l ( ) [ 0 ]
      >>>p o s t c o m m e n t s = p o s t . c om m en t s et . a l l ( )
Introduction   Forms   Authentication   Generic Views   Caching   Others   Admin



                            Save Foreign Keys
Introduction     Forms       Authentication     Generic Views     Caching       Others      Admin



                                 Use Model Formset

      from d j a n g o . f o r m s . m o d e l s import m o d e l f o r m s e t f a c t o r y
      AuthorFormSet = m o d e l f o r m s e t f a c t o r y ( Au t ho r )
      f o r m s e t = AuthorFormSet ( )
      >>> p r i n t f o r m s e t
      <i n p u t t y p e= h i d d e n  name= form?TOTAL FORMS
      v a l u e= 1  i d= i d f o r m ?TOTAL FORMS />
      <i n p u t t y p e= h i d d e n  name= form?INITIAL FORMS
      v a l u e= 0  i d= i d f o r m ?INITIAL FORMS />
      <i n p u t t y p e= h i d d e n  name= form?MAX NUM FORMS
      i d= i d f o r m ?MAX NUM FORMS />
      <t r ><th>
      < l a b e l f o r= i d f o r m ?0?name>Name:</ l a b e l >
      </th><td>
      <i n p u t i d= i d f o r m ?0?name t y p e= t e x t 
      name= form ?0?name m a x l e n g t h= 100  />
      </td ></t r >
Introduction      Forms       Authentication    Generic Views   Caching     Others   Admin



                               Model Formset options


       f o r m s e t = AuthorFormSet ( q s=Au th o r . o b j e c t s . a l l ( ) ,
                                       e x t r a =5)

       formset . i s v a l i d ()

       formset . e r r o r s
       {  name  :  T h i s f i e l d    is required }

       formset . changed forms

       formset . save ()
Introduction   Forms   Authentication   Generic Views   Caching   Others   Admin



                           Form pre populated
Introduction       Forms        Authentication      Generic Views       Caching        Others        Admin



                     Forms dont have to save to a Model


       from d j a n g o import f o r m s

       c l a s s ContactForm ( f o r m s . Form ) :
               s u b j e c t = f o r m s . C h a r F i e l d ( m a x l e n g t h =100)
               message = f o r m s . C h a r F i e l d ( )
               sender = forms . E m a i l F i e l d ()
               c c m y s e l f = f o r m s . B o o l e a n F i e l d ( r e q u i r e d=F a l s e )

               def s a v e ( s e l f ) :
               #Do a n y t h i n g
                ...
Form Preview
Introduction       Forms        Authentication      Generic Views       Caching        Others       Admin



                                          Form Preview

       from d j a n g o . c o n t r i b . f o r m t o o l s . p r e v i e w import FormPreview
       from myapp . m o d e l s import SomeModel

      #Add a u r l
      ( r  ? p o s t / $  , SomeModelFormPreview ( SomeModelForm ) ) ,

      #D e f i n e form p r e v i e w

       c l a s s SomeModelFormPreview ( FormPreview ) :

               def done ( s e l f , r e q u e s t , c l e a n e d d a t a ) :
                   # Do s o m e t h i n g w i t h t h e c l e a n e d d a t a , t h e n
                   # r e d i r e c t t o a  s u c c e s s  page .
                   r e t u r n H t t p R e s p o n s e R e d i r e c t (  / form / s u c c e s s  )
Form Wizard
Introduction   Forms     Authentication   Generic Views   Caching   Others    Admin



                                    Form Wizard




       c l a s s C o n t a c t W i z a r d ( FormWizard ) :
               def done ( s e l f , r e q u e s t , f o r m l i s t ) :
                    do something with the form data ( fo r m l is t )
                    return HttpResponseRedirect (  / r e d i r e c t /  )
Authentication
Introduction       Forms         Authentication       Generic Views       Caching         Others        Admin



                                     Point to url pattern


       u r l p a t t e r n s += p a t t e r n s (  d j a n g o . c o n t r i b . a u t h . v i e w s  ,
               u r l ( r  ? l o g i n /$  ,  l o g i n  ) ,
               u r l ( r  ? l o g o u t /$  ,  l o g o u t  ) ,
               u r l ( r  ? r e g i s t e r /$  ,  r e g i s t e r  ) ,
               u r l ( r  ? p a s s r e s e t /$  ,  p a s s w o r d r e s e t  ) ,
               u r l ( r  ? p a s s r e s e t 2 /$  ,  p a s s w o r d r e s e t d o n e  ) ,
               u r l ( r  ? p a s s r e s e t c o n f i r m / ( ?P<u i d b 3 6 >[?w]+)/  ,
                         password reset confirm  ) ,
               u r l ( r  ? p a s s r e s e t c o m p l e t e /$  ,
                         password reset complete  ) ,
               )
Introduction      Forms         Authentication      Generic Views      Caching        Others        Admin



                                         Login Required




       from d j a n g o . c o n t r i b . a u t h . d e c o r a t o r s import 
       login required

       @ l o g i n r e q u i r e d ( r e d i r e c t f i e l d n a m e=  r e d i r e c t t o  )
       def my view ( r e q u e s t ) :
              ...
Introduction       Forms       Authentication     Generic Views     Caching       Others   Admin



                              Authentication backends

       class SettingsBackend :
           
           A u t h e n t i c a t e a g a i n s t t h e s e t t i n g s ADMIN LOGIN
           and ADMIN PASSWORD .
           
           def a u t h e n t i c a t e ( s e l f , username=None , p a s s w o r d=None )
                  i f l o g i n v a l i d and p w d v a l i d :
                           return user
                  r e t u r n None

               def g e t u s e r ( s e l f , u s e r i d ) :
                   try :
                         r e t u r n U s e r . o b j e c t s . g e t ( pk=u s e r i d )
                   except U s e r . D o e s N o t E x i s t :
                         r e t u r n None
django-socialauth
Send to template
Introduction     Forms       Authentication    Generic Views     Caching   Others   Admin



                                       Generic Views



       from d j a n g o . c o n f . u r l s . d e f a u l t s import ?
       from d j a n g o . v i e w s . g e n e r i c . s i m p l e 
       import d i r e c t t o t e m p l a t e

       urlpatterns = patterns (   ,
           (  ? about /$  , d i r e c t t o t e m p l a t e , {
                   t e m p l a t e  :  a b o u t . html 
           })
       )
Introduction   Forms    Authentication   Generic Views   Caching   Others   Admin



                       Object based generic views
Introduction     Forms       Authentication    Generic Views     Caching      Others   Admin



                         Display objects and their lists



       from d j a n g o . v i e w s . g e n e r i c . l i s t d e t a i l import 
                 object detail , object list
       u r l ( ( r  ? o b j e c t s / page ( ? P<page >[0 ?9]+)/ $  ,
               object list ,
               dict ( info dict )) ,
               ( r  ? o b j e c t s / ( ?P<i d >[0 ?9]+)/ $  ,
               object detail ,
               dict ( info dict )) ,
       )
Introduction      Forms       Authentication     Generic Views      Caching       Others   Admin



                                 List of generic views



       django . views . g e n e r i c . simple . d i r e c t t o t e m p l a t e
       django . views . g e n e r i c . simple . r e d i r e c t t o

       django . views . g e n e r i c . l i s t d e t a i l . o b j e c t l i s t
       django . views . g e n e r i c . l i s t d e t a i l . o b j e c t d e t a i l

       django . views . g e n e r i c . create update . c r e a t e o b j e c t
       django . views . g e n e r i c . create update . update object
       django . views . g e n e r i c . create update . d e l e t e o b j e c t
Normalized data is for sissies - Cal Henderson
Introduction   Forms   Authentication   Generic Views   Caching   Others   Admin



           Di?erent blocks need di?erent caching durations
Introduction     Forms      Authentication   Generic Views   Caching     Others      Admin



                         Generally Memcache Every page




       CACHE BACKEND =  memcached : / / 1 2 7 . 0 . 0 . 1 : 1 1 2 1 1 / 
       CACHE BACKEND =  memcached : / / 1 7 2 . 1 9 . 2 6 . 2 4 0 : 1 1 2 1 1 ; 
       172.19.26.242:11212;172.19.26.244:11213/
Introduction      Forms       Authentication    Generic Views      Caching      Others       Admin



                          Implement a caching decorator


       from d j a n g o . c o r e . c a c h e import c a c h e
       def c a c h e f o r ( s e c o n d s , f e t c h =0):
           def c a c h e i t ( f u n c ) :
                  def d e c o f u n c ( s e l f ) :
                          v a l = cache . get ( s e l f . g e t c a c h e k e y ( f e t c h ))
                          i f not v a l :
                                  val = func ( s e l f )
                                  cache . s e t ( s e l f . g e t c a c h e k e y ( f e t c h ) ,
                                                     val , seconds )
                          return v a l
                  return deco func
           return c a c h e i t
Introduction       Forms        Authentication     Generic Views       Caching       Others    Admin



                                   Apply on the blocks


       class TwitterBlock ( TwitterSearchBlock ) :

               t e m p l a t e n a m e =  t w i t t e r u s e r b l o c k . html 
               a j a x t e m p l a t e =  t w e e t s u s e r . html 

               @ c a c h e f o r ( 6 0 ? 6 0 , f e t c h =1)
               def f e t c h d a t a ( s e l f ) :
                      tw = T w i t t e r ( e m a i l=  umoja com  )
                      u s e r t w e e t s = tw . s t a t u s e s . u s e r t i m e l i n e (
                              s c r e e n n a m e= s e l f . d a t a )
                      r e t u r n u s e r t w e e t s , None
Introduction    Forms      Authentication   Generic Views   Caching   Others   Admin



                           Di?erent cache Backends




           ? Database
           ? File System
           ? Local Memory
           ? Dummy- For Development
Introduction     Forms      Authentication   Generic Views   Caching   Others   Admin



                                   More Paradigms



           ? Internationalization
           ? Localization
           ? Humanization
           ? CSRF Protection
           ? Pagination
           ? Sorting
           ? Data grid
           ? Sorl Thumbnail
Web Development Paradigms and djangoic approach to deal with them
Introduction   Forms   Authentication   Generic Views   Caching   Others   Admin



                       Admin by models alone
Introduction     Forms       Authentication     Generic Views     Caching   Others   Admin



                                       Admin Syntax


       from d j a n g o . c o n t r i b import admin
       from m o d e l s import Post , Comment

       c l a s s PostAdmin ( admin . ModelAdmin ) :
               l i s t d i s p l a y = (  t i t l e  ,  datetime  )

       c l a s s CommentAdmin ( admin . ModelAdmin ) :
               l i s t d i s p l a y = (  text  ,)

       admin . s i t e . r e g i s t e r ( Post , PostAdmin )
       admin . s i t e . r e g i s t e r ( Comment , CommentAdmin )
List Page
Add an Entry
Auto Validation

More Related Content

Web Development Paradigms and djangoic approach to deal with them

  • 1. Introduction Forms Authentication Generic Views Caching Others Admin Web Development Paradigms and djangoic approach to deal with them. Lakshman Prasad Agiliq Solutions September 25, 2010
  • 2. Concepts and abstractions used to represent elements of a program
  • 3. Web Development Paradigms: Modeling common web patterns
  • 8. Webapp: Simple web application framework (with custom APIs)
  • 9. Lets examine the batteries
  • 10. Introduction Forms Authentication Generic Views Caching Others Admin How do I know about web development or django ? Active Djangonaut ? Part of a few popular open source django applications github.com/becomingGuru, github.com/agiliq ? Consulting and Development via ? Developed several custom proprietory django applications ? @becomingGuru
  • 11. Introduction Forms Authentication Generic Views Caching Others Admin Introduction Forms Authentication Generic Views Caching Others Admin
  • 12. Forms
  • 13. Save form data to a table
  • 14. Introduction Forms Authentication Generic Views Caching Others Admin Use a Model Form >>> from d j a n g o . f o r m s import ModelForm # C r e a t e t h e form c l a s s . >>> c l a s s A r t i c l e F o r m ( ModelForm ) : ... c l a s s Meta : ... model = A r t i c l e # C r e a t i n g a form t o add an a r t i c l e . >>> form = A r t i c l e F o r m ( ) # C r e a t i n g a form t o c h an ge an e x i s t i n g a r t i c l e . >>> a r t i c l e = A r t i c l e . o b j e c t s . g e t ( pk=1) >>> form = A r t i c l e F o r m ( i n s t a n c e= a r t i c l e )
  • 16. Introduction Forms Authentication Generic Views Caching Others Admin Model Syntax from d j a n g o . db import m o d e l s c l a s s P o s t ( m o d e l s . Model ) : t i t l e = m o d e l s . C h a r F i e l d ( m a x l e n g t h =100) t e x t = models . T e x t F i e l d ( ) datetime = models . DateTimeField ( ) c l a s s Meta : o r d e r i n g = ( ?d a t e t i m e , ) def unicode ( self ): return s e l f . t i t l e c l a s s Comment ( m o d e l s . Model ) : post = models . ForeignKey ( Post ) t e x t = models . T e x t F i e l d ( )
  • 17. Introduction Forms Authentication Generic Views Caching Others Admin Model API >>>from b l o g . m o d e l s import Post , Comment >>>p o s t = P o s t . o b j e c t s . a l l ( ) [ 0 ] >>>p o s t c o m m e n t s = p o s t . c om m en t s et . a l l ( )
  • 18. Introduction Forms Authentication Generic Views Caching Others Admin Save Foreign Keys
  • 19. Introduction Forms Authentication Generic Views Caching Others Admin Use Model Formset from d j a n g o . f o r m s . m o d e l s import m o d e l f o r m s e t f a c t o r y AuthorFormSet = m o d e l f o r m s e t f a c t o r y ( Au t ho r ) f o r m s e t = AuthorFormSet ( ) >>> p r i n t f o r m s e t <i n p u t t y p e= h i d d e n name= form?TOTAL FORMS v a l u e= 1 i d= i d f o r m ?TOTAL FORMS /> <i n p u t t y p e= h i d d e n name= form?INITIAL FORMS v a l u e= 0 i d= i d f o r m ?INITIAL FORMS /> <i n p u t t y p e= h i d d e n name= form?MAX NUM FORMS i d= i d f o r m ?MAX NUM FORMS /> <t r ><th> < l a b e l f o r= i d f o r m ?0?name>Name:</ l a b e l > </th><td> <i n p u t i d= i d f o r m ?0?name t y p e= t e x t name= form ?0?name m a x l e n g t h= 100 /> </td ></t r >
  • 20. Introduction Forms Authentication Generic Views Caching Others Admin Model Formset options f o r m s e t = AuthorFormSet ( q s=Au th o r . o b j e c t s . a l l ( ) , e x t r a =5) formset . i s v a l i d () formset . e r r o r s { name : T h i s f i e l d is required } formset . changed forms formset . save ()
  • 21. Introduction Forms Authentication Generic Views Caching Others Admin Form pre populated
  • 22. Introduction Forms Authentication Generic Views Caching Others Admin Forms dont have to save to a Model from d j a n g o import f o r m s c l a s s ContactForm ( f o r m s . Form ) : s u b j e c t = f o r m s . C h a r F i e l d ( m a x l e n g t h =100) message = f o r m s . C h a r F i e l d ( ) sender = forms . E m a i l F i e l d () c c m y s e l f = f o r m s . B o o l e a n F i e l d ( r e q u i r e d=F a l s e ) def s a v e ( s e l f ) : #Do a n y t h i n g ...
  • 24. Introduction Forms Authentication Generic Views Caching Others Admin Form Preview from d j a n g o . c o n t r i b . f o r m t o o l s . p r e v i e w import FormPreview from myapp . m o d e l s import SomeModel #Add a u r l ( r ? p o s t / $ , SomeModelFormPreview ( SomeModelForm ) ) , #D e f i n e form p r e v i e w c l a s s SomeModelFormPreview ( FormPreview ) : def done ( s e l f , r e q u e s t , c l e a n e d d a t a ) : # Do s o m e t h i n g w i t h t h e c l e a n e d d a t a , t h e n # r e d i r e c t t o a s u c c e s s page . r e t u r n H t t p R e s p o n s e R e d i r e c t ( / form / s u c c e s s )
  • 26. Introduction Forms Authentication Generic Views Caching Others Admin Form Wizard c l a s s C o n t a c t W i z a r d ( FormWizard ) : def done ( s e l f , r e q u e s t , f o r m l i s t ) : do something with the form data ( fo r m l is t ) return HttpResponseRedirect ( / r e d i r e c t / )
  • 28. Introduction Forms Authentication Generic Views Caching Others Admin Point to url pattern u r l p a t t e r n s += p a t t e r n s ( d j a n g o . c o n t r i b . a u t h . v i e w s , u r l ( r ? l o g i n /$ , l o g i n ) , u r l ( r ? l o g o u t /$ , l o g o u t ) , u r l ( r ? r e g i s t e r /$ , r e g i s t e r ) , u r l ( r ? p a s s r e s e t /$ , p a s s w o r d r e s e t ) , u r l ( r ? p a s s r e s e t 2 /$ , p a s s w o r d r e s e t d o n e ) , u r l ( r ? p a s s r e s e t c o n f i r m / ( ?P<u i d b 3 6 >[?w]+)/ , password reset confirm ) , u r l ( r ? p a s s r e s e t c o m p l e t e /$ , password reset complete ) , )
  • 29. Introduction Forms Authentication Generic Views Caching Others Admin Login Required from d j a n g o . c o n t r i b . a u t h . d e c o r a t o r s import login required @ l o g i n r e q u i r e d ( r e d i r e c t f i e l d n a m e= r e d i r e c t t o ) def my view ( r e q u e s t ) : ...
  • 30. Introduction Forms Authentication Generic Views Caching Others Admin Authentication backends class SettingsBackend : A u t h e n t i c a t e a g a i n s t t h e s e t t i n g s ADMIN LOGIN and ADMIN PASSWORD . def a u t h e n t i c a t e ( s e l f , username=None , p a s s w o r d=None ) i f l o g i n v a l i d and p w d v a l i d : return user r e t u r n None def g e t u s e r ( s e l f , u s e r i d ) : try : r e t u r n U s e r . o b j e c t s . g e t ( pk=u s e r i d ) except U s e r . D o e s N o t E x i s t : r e t u r n None
  • 33. Introduction Forms Authentication Generic Views Caching Others Admin Generic Views from d j a n g o . c o n f . u r l s . d e f a u l t s import ? from d j a n g o . v i e w s . g e n e r i c . s i m p l e import d i r e c t t o t e m p l a t e urlpatterns = patterns ( , ( ? about /$ , d i r e c t t o t e m p l a t e , { t e m p l a t e : a b o u t . html }) )
  • 34. Introduction Forms Authentication Generic Views Caching Others Admin Object based generic views
  • 35. Introduction Forms Authentication Generic Views Caching Others Admin Display objects and their lists from d j a n g o . v i e w s . g e n e r i c . l i s t d e t a i l import object detail , object list u r l ( ( r ? o b j e c t s / page ( ? P<page >[0 ?9]+)/ $ , object list , dict ( info dict )) , ( r ? o b j e c t s / ( ?P<i d >[0 ?9]+)/ $ , object detail , dict ( info dict )) , )
  • 36. Introduction Forms Authentication Generic Views Caching Others Admin List of generic views django . views . g e n e r i c . simple . d i r e c t t o t e m p l a t e django . views . g e n e r i c . simple . r e d i r e c t t o django . views . g e n e r i c . l i s t d e t a i l . o b j e c t l i s t django . views . g e n e r i c . l i s t d e t a i l . o b j e c t d e t a i l django . views . g e n e r i c . create update . c r e a t e o b j e c t django . views . g e n e r i c . create update . update object django . views . g e n e r i c . create update . d e l e t e o b j e c t
  • 37. Normalized data is for sissies - Cal Henderson
  • 38. Introduction Forms Authentication Generic Views Caching Others Admin Di?erent blocks need di?erent caching durations
  • 39. Introduction Forms Authentication Generic Views Caching Others Admin Generally Memcache Every page CACHE BACKEND = memcached : / / 1 2 7 . 0 . 0 . 1 : 1 1 2 1 1 / CACHE BACKEND = memcached : / / 1 7 2 . 1 9 . 2 6 . 2 4 0 : 1 1 2 1 1 ; 172.19.26.242:11212;172.19.26.244:11213/
  • 40. Introduction Forms Authentication Generic Views Caching Others Admin Implement a caching decorator from d j a n g o . c o r e . c a c h e import c a c h e def c a c h e f o r ( s e c o n d s , f e t c h =0): def c a c h e i t ( f u n c ) : def d e c o f u n c ( s e l f ) : v a l = cache . get ( s e l f . g e t c a c h e k e y ( f e t c h )) i f not v a l : val = func ( s e l f ) cache . s e t ( s e l f . g e t c a c h e k e y ( f e t c h ) , val , seconds ) return v a l return deco func return c a c h e i t
  • 41. Introduction Forms Authentication Generic Views Caching Others Admin Apply on the blocks class TwitterBlock ( TwitterSearchBlock ) : t e m p l a t e n a m e = t w i t t e r u s e r b l o c k . html a j a x t e m p l a t e = t w e e t s u s e r . html @ c a c h e f o r ( 6 0 ? 6 0 , f e t c h =1) def f e t c h d a t a ( s e l f ) : tw = T w i t t e r ( e m a i l= umoja com ) u s e r t w e e t s = tw . s t a t u s e s . u s e r t i m e l i n e ( s c r e e n n a m e= s e l f . d a t a ) r e t u r n u s e r t w e e t s , None
  • 42. Introduction Forms Authentication Generic Views Caching Others Admin Di?erent cache Backends ? Database ? File System ? Local Memory ? Dummy- For Development
  • 43. Introduction Forms Authentication Generic Views Caching Others Admin More Paradigms ? Internationalization ? Localization ? Humanization ? CSRF Protection ? Pagination ? Sorting ? Data grid ? Sorl Thumbnail
  • 45. Introduction Forms Authentication Generic Views Caching Others Admin Admin by models alone
  • 46. Introduction Forms Authentication Generic Views Caching Others Admin Admin Syntax from d j a n g o . c o n t r i b import admin from m o d e l s import Post , Comment c l a s s PostAdmin ( admin . ModelAdmin ) : l i s t d i s p l a y = ( t i t l e , datetime ) c l a s s CommentAdmin ( admin . ModelAdmin ) : l i s t d i s p l a y = ( text ,) admin . s i t e . r e g i s t e r ( Post , PostAdmin ) admin . s i t e . r e g i s t e r ( Comment , CommentAdmin )