2008-06-30 14:24:21 +08:00
import copy
2008-08-18 04:07:59 +08:00
from django . contrib . auth . models import User
2008-06-30 14:24:21 +08:00
from django . db import models
from django . db . models . query import Q
2008-08-18 04:07:59 +08:00
from django . utils . datastructures import SortedDict
2008-06-30 14:24:21 +08:00
class RevisionableModel ( models . Model ) :
base = models . ForeignKey ( ' self ' , null = True )
title = models . CharField ( blank = True , max_length = 255 )
def __unicode__ ( self ) :
return u " %s ( %s , %s ) " % ( self . title , self . id , self . base . id )
def save ( self ) :
super ( RevisionableModel , self ) . save ( )
if not self . base :
self . base = self
super ( RevisionableModel , self ) . save ( )
def new_revision ( self ) :
new_revision = copy . copy ( self )
new_revision . pk = None
return new_revision
__test__ = { " API_TESTS " : """
2008-08-18 04:07:59 +08:00
# Regression tests for #7314 and #7372
2008-06-30 14:24:21 +08:00
>> > rm = RevisionableModel . objects . create ( title = ' First Revision ' )
>> > rm . pk , rm . base . pk
( 1 , 1 )
>> > rm2 = rm . new_revision ( )
>> > rm2 . title = " Second Revision "
>> > rm2 . save ( )
>> > print u " %s of %s " % ( rm2 . title , rm2 . base . title )
Second Revision of First Revision
>> > rm2 . pk , rm2 . base . pk
( 2 , 1 )
Queryset to match most recent revision :
2008-07-04 03:02:43 +08:00
>> > qs = RevisionableModel . objects . extra ( where = [ " %(table)s .id IN (SELECT MAX(rev.id) FROM %(table)s rev GROUP BY rev.base_id) " % { ' table ' : RevisionableModel . _meta . db_table , } ] , )
2008-06-30 14:24:21 +08:00
>> > qs
[ < RevisionableModel : Second Revision ( 2 , 1 ) > ]
Queryset to search for string in title :
>> > qs2 = RevisionableModel . objects . filter ( title__contains = " Revision " )
>> > qs2
[ < RevisionableModel : First Revision ( 1 , 1 ) > , < RevisionableModel : Second Revision ( 2 , 1 ) > ]
Following queryset should return the most recent revision :
>> > qs & qs2
[ < RevisionableModel : Second Revision ( 2 , 1 ) > ]
2008-08-18 04:07:59 +08:00
>> > u = User . objects . create_user ( username = " fred " , password = " secret " , email = " fred@example.com " )
# General regression tests: extra select parameters should stay tied to their
# corresponding select portions. Applies when portions are updated or otherwise
# moved around.
>> > qs = User . objects . extra ( select = SortedDict ( ( ( " alpha " , " %s " ) , ( " beta " , " 2 " ) , ( " gamma " , " %s " ) ) ) , select_params = ( 1 , 3 ) )
>> > qs = qs . extra ( select = { " beta " : 4 } )
>> > qs = qs . extra ( select = { " alpha " : " %s " } , select_params = [ 5 ] )
>> > result = { ' alpha ' : 5 , ' beta ' : 4 , ' gamma ' : 3 }
>> > list ( qs . filter ( id = u . id ) . values ( ' alpha ' , ' beta ' , ' gamma ' ) ) == [ result ]
True
# Regression test for #7957: Combining extra() calls should leave the
# corresponding parameters associated with the right extra() bit. I.e. internal
# dictionary must remain sorted.
>> > User . objects . extra ( select = { " alpha " : " %s " } , select_params = ( 1 , ) ) . extra ( select = { " beta " : " %s " } , select_params = ( 2 , ) ) [ 0 ] . alpha
1
>> > User . objects . extra ( select = { " beta " : " %s " } , select_params = ( 1 , ) ) . extra ( select = { " alpha " : " %s " } , select_params = ( 2 , ) ) [ 0 ] . alpha
2
# Regression test for #7961: When not using a portion of an extra(...) in a
# query, remove any corresponding parameters from the query as well.
>> > list ( User . objects . extra ( select = { " alpha " : " %s " } , select_params = ( - 6 , ) ) . filter ( id = u . id ) . values_list ( ' id ' , flat = True ) ) == [ u . id ]
True
2008-08-18 04:18:52 +08:00
# Regression test for #8063: limiting a query shouldn't discard any extra()
# bits.
>> > qs = User . objects . all ( ) . extra ( where = [ ' id= %s ' ] , params = [ u . id ] )
>> > qs
[ < User : fred > ]
>> > qs [ : 1 ]
[ < User : fred > ]
2008-06-30 14:24:21 +08:00
""" }