2010-12-06 22:33:00 +00:00
from django . db import models
2011-01-04 06:27:10 +00:00
import operator
from django . db . models import Q
from ox . text import smartSplit
2011-03-06 12:35:55 +00:00
from ox . django . fields import DictField
2011-01-04 06:27:10 +00:00
from django . core . paginator import Paginator , InvalidPage , EmptyPage
2011-08-22 21:56:30 +00:00
from django . template . loader import render_to_string
from django . contrib . contenttypes . models import ContentType
2011-08-27 10:54:45 +00:00
from insidepages . models import ModuleTab , ModelExtra
2011-09-10 02:45:52 +00:00
from os . path import exists
2011-10-05 15:27:02 +00:00
from sorl . thumbnail import get_thumbnail
2012-01-12 18:25:59 +00:00
from django . template import RequestContext
2012-02-02 10:19:45 +00:00
import datetime
2011-01-04 06:27:10 +00:00
def splitSearch ( string ) :
ret = [ ]
for s in smartSplit ( string ) :
word = s . replace ( " ' " , " " ) . replace ( ' " ' , ' ' )
ret . append ( word )
return ret
2011-09-09 23:13:27 +00:00
#i see the point of this function, but please clean it up: refer to 'except MultipleObjectsReturned' to see why this is here.
def get_real_ctype ( module_name ) :
for c in ContentType . objects . filter ( model = module_name ) :
2011-10-24 02:10:54 +00:00
try :
if c . model_class ( ) . is_itf_model == True :
return c
except :
pass
2011-09-09 23:13:27 +00:00
return None
2011-01-04 06:27:10 +00:00
class ItfModel ( models . Model ) :
fts_fields = [ ]
fk_filters = [ ]
2011-04-04 01:35:25 +00:00
# related_models = []
2011-01-04 06:27:10 +00:00
sort_fields = [ ]
2011-02-01 15:13:30 +00:00
hasComments = True
2011-08-22 21:56:30 +00:00
title_field = " title "
2011-09-09 23:13:27 +00:00
is_itf_model = True
2012-02-02 10:19:45 +00:00
changed = models . DateTimeField ( null = True , editable = False )
created = models . DateTimeField ( null = True , editable = False )
def save ( self , * args , * * kwargs ) :
''' On save, update timestamps '''
if not self . id :
self . created = datetime . datetime . today ( )
self . changed = datetime . datetime . today ( )
if self . created == None :
self . created = self . changed
super ( ItfModel , self ) . save ( * args , * * kwargs )
2011-01-04 06:27:10 +00:00
class Meta :
abstract = True
def list_dict ( self ) :
return { }
def info_dict ( self ) :
2011-03-18 04:49:27 +00:00
return self . get_dict ( )
2011-08-22 21:56:30 +00:00
def get_title ( self ) :
return self . get ( self . title_field )
def get_tab ( self ) :
2011-10-05 15:27:02 +00:00
modelextra = self . get_modelextra ( )
tab = ModuleTab . objects . filter ( model = modelextra ) [ 0 ]
return tab
2011-10-13 14:40:45 +00:00
@classmethod
def get_add_form ( cls ) :
try :
formStr = cls . add_form
# cls = default_tab.model_class()
app_label = cls . _meta . app_label
module = __import__ ( app_label + " .forms " )
add_form = module . forms . __getattribute__ ( formStr )
return add_form
except :
return None
2011-10-05 15:27:02 +00:00
def get_modelextra ( self ) :
2011-09-09 23:13:27 +00:00
try :
ctype = ContentType . objects . get ( model = self . __class__ . _meta . module_name )
2011-09-09 23:16:06 +00:00
except : #FIXME: ideally catch only MultipleObjectsReturned (figure out where to import that from :/ ) #FUCKING way ugly hack to get clashing model ctype names with django internal models working (get_real_ctypes simply checks, if there are multiple content objects with the same 'module_name', which one is_itf_model, and returns that).
2011-09-09 23:19:01 +00:00
ctype = get_real_ctype ( self . __class__ . _meta . module_name )
2011-09-09 23:25:10 +00:00
# modelextra = ModelExtra.objects.filter(model=ctype)[0]
modelextra = ctype . modelextra_set . all ( ) [ 0 ]
2011-10-05 15:27:02 +00:00
return modelextra
2011-08-22 21:56:30 +00:00
def get_absolute_url ( self ) :
2011-10-03 02:43:28 +00:00
return " %s /?tab= %s &object_id= %d " % ( self . get_module ( ) . get_absolute_url ( ) , self . get_tab ( ) . slug , self . id )
2011-08-22 21:56:30 +00:00
def get_module ( self ) :
tab = self . get_tab ( )
if tab :
return tab . module
else :
return None
2011-09-09 23:13:27 +00:00
2012-01-02 18:29:30 +00:00
def get_main_image ( self , size = " 142x150 " ) :
2011-12-15 16:21:37 +00:00
if hasattr ( self , ' main_image ' ) :
main_image_getter = self . main_image
2011-12-15 16:30:12 +00:00
if type ( main_image_getter ) . __name__ == ' instancemethod ' :
2011-12-15 16:21:37 +00:00
imgfield = main_image_getter ( )
else :
imgfield = main_image_getter
2012-01-02 18:32:00 +00:00
else :
imgfield = self . get_modelextra ( ) . default_image #FIXME!!
2012-01-04 13:42:12 +00:00
if imgfield is None or imgfield . name == ' ' :
2011-10-05 15:27:02 +00:00
imgfield = self . get_modelextra ( ) . default_image
2012-01-02 18:29:30 +00:00
if imgfield :
2011-10-05 15:27:02 +00:00
try :
2012-01-02 18:29:30 +00:00
thumb = get_thumbnail ( imgfield , size , crop = " center " ) . url
2011-10-05 15:27:02 +00:00
except :
thumb = ' '
else :
2011-10-10 10:30:18 +00:00
thumb = ' ' # Add default image for site
2011-08-22 21:56:30 +00:00
return {
2011-10-10 10:30:18 +00:00
' thumb ' : thumb
2011-08-22 21:56:30 +00:00
}
2011-11-24 19:15:25 +00:00
'''
2011-10-05 15:27:02 +00:00
def main_image ( self ) :
return None
2011-11-24 19:15:25 +00:00
'''
2011-10-05 15:27:02 +00:00
2011-08-22 21:56:30 +00:00
def get_template_path ( self ) :
kls = self . __class__
return " modules/ %s / %s .html " % ( kls . _meta . app_label , kls . _meta . module_name )
2011-03-18 04:49:27 +00:00
def get_dict ( self ) :
2011-04-04 01:35:25 +00:00
return self . get ( self . _get_fields ( ) . keys ( ) )
2011-03-18 04:49:27 +00:00
2012-01-12 18:25:59 +00:00
def insidepage_dict ( self , request ) :
context = RequestContext ( request , self . info_dict ( ) )
2012-03-09 14:09:12 +00:00
html = render_to_string ( self . get_template_path ( ) , context )
2011-08-22 21:56:30 +00:00
return {
' url ' : self . get_absolute_url ( ) ,
' title ' : self . get_title ( ) ,
' main_image ' : self . get_main_image ( ) ,
' html ' : html
}
2011-03-18 04:49:27 +00:00
def get ( self , props ) :
typ = type ( props )
if typ == list :
ret = { }
for p in props :
ret [ p ] = self . _get_property ( p )
return ret
elif typ == str :
2011-08-25 09:39:15 +00:00
return self . _get_property ( props )
2011-03-18 04:49:27 +00:00
else :
return False
def _get_property ( self , prop ) :
fields = self . _get_fields ( )
if prop in fields . keys ( ) :
field_type = fields [ prop ]
if field_type in [ " TextField " , " CharField " , " IntegerField " ] :
return self . __getattribute__ ( prop )
elif field_type == " ImageField " :
imagefield = self . __getattribute__ ( prop )
return imagefield . url if imagefield . name != ' ' else ' '
elif field_type == " ForeignKey " :
return self . _get_fk ( prop )
elif field_type == " ManyToMany " :
return self . _get_m2m ( prop )
elif prop . lower ( ) in self . related_models :
return self . _get_related ( prop )
else :
try :
val = self . __getattribute__ ( prop )
if type ( val ) . __name__ == ' instancemethod ' and prop in self . getters :
return val ( )
else :
return val
except :
return False #FIXME
def _get_fk ( self , prop ) :
prop = prop . replace ( " _id " , " " )
return self . __getattribute__ ( prop ) . get_dict ( )
# def _get_related_objects(self, fk_field):
def _get_m2m ( self , prop ) :
ret = [ ]
for o in self . __getattribute__ ( prop ) . all ( ) :
ret . append ( o . get_dict ( ) )
return ret
def _get_related ( self , prop ) :
attr = prop . lower ( ) + " _set "
ret = [ ]
for o in self . __getattribute__ ( attr ) . all ( ) :
ret . append ( o . get_dict ( ) )
return ret
2011-01-04 06:27:10 +00:00
2011-03-18 04:49:27 +00:00
@classmethod
def _get_fields ( kls ) :
ret = { }
for f in kls . _meta . fields :
ret [ f . get_attname ( ) ] = type ( f ) . __name__
return ret
2011-01-04 06:27:10 +00:00
@classmethod
def fts ( kls , qset , search ) :
terms = splitSearch ( search )
qobjects = [ ]
for t in terms :
for f in kls . fts_fields :
qstring = f + ' __icontains '
qobject = Q ( * * { qstring : t } )
qobjects . append ( qobject )
return qset . filter ( reduce ( operator . or_ , qobjects ) )
'''
eg . fks = {
' somefield ' : [ 1 , 5 , 7 ] ,
' someotherfield ' : [ 3 ]
}
'''
@classmethod
def filter_by_fks ( kls , qset , fks ) :
qobjects = [ ]
for key in fks . keys ( ) :
field = getField ( kls . _meta . fields , key )
if field :
# rel_class = field.related.parent_model
for i in fks [ key ] :
qobject = Q ( * * { field . name : i } )
qobjects . append ( qobject )
return qset . filter ( reduce ( operator . or_ , qobjects ) )
2011-03-06 21:40:29 +00:00
2011-01-04 06:27:10 +00:00
@classmethod
def get_fk_objects ( kls ) :
ret = { }
for f in kls . fk_filters :
ret [ f ] = [ ]
field = getField ( kls . _meta . fields , f )
rel_class = field . related . parent_model
for o in rel_class . objects . all ( ) :
ret [ f ] . append ( {
' id ' : o . id ,
' title ' : unicode ( o )
} )
return ret
@classmethod
def get_list ( kls , data ) :
options = {
2011-09-10 01:40:47 +00:00
' page ' : 1 ,
2011-10-10 10:30:18 +00:00
' count ' : 20 ,
2011-01-04 06:27:10 +00:00
' search ' : ' ' ,
2011-01-06 05:59:08 +00:00
' sort ' : [ ] ,
2011-10-10 10:30:18 +00:00
' range ' : [ 0 , 50 ] ,
' object_id ' : False
2011-01-04 06:27:10 +00:00
}
options . update ( data )
ret = [ ]
2011-09-10 01:40:47 +00:00
page_no = options [ ' page ' ]
list_size = options [ ' count ' ]
2011-04-10 02:00:43 +00:00
try :
qset = kls . get_qset ( )
except :
qset = kls . objects . all ( )
2011-01-04 06:27:10 +00:00
2011-10-10 10:30:18 +00:00
2011-01-04 06:27:10 +00:00
search = options [ ' search ' ]
if search != ' ' :
qset = kls . fts ( qset , search )
2011-01-11 20:32:18 +00:00
2011-01-04 06:27:10 +00:00
sort = options [ ' sort ' ]
2011-09-10 01:40:47 +00:00
2011-01-04 06:27:10 +00:00
if sort != [ ] :
2011-01-11 20:32:18 +00:00
for s in sort :
2011-01-13 10:08:10 +00:00
if s [ ' operator ' ] == ' - ' :
operator = ' - '
else :
operator = ' '
2011-04-10 02:00:43 +00:00
sort = operator + s [ ' key ' ]
2011-01-11 20:32:18 +00:00
qset = qset . order_by ( sort )
2011-11-01 00:19:02 +00:00
#FIXME: object_id needs to do something more graceful, this breaks sort.
if options [ ' object_id ' ] != False and options [ ' object_id ' ] != ' ' :
object_id = options [ ' object_id ' ]
qset = qset . exclude ( pk = object_id )
try :
obj = kls . objects . get ( pk = object_id )
ret . append ( obj . list_dict ( ) )
except :
pass
2011-08-25 09:39:15 +00:00
'''
2011-01-06 05:59:08 +00:00
r0 = options [ ' range ' ] [ 0 ]
r1 = options [ ' range ' ] [ 1 ]
results = qset [ r0 : r1 ]
2011-08-25 09:39:15 +00:00
'''
paginator = Paginator ( qset , list_size )
try :
results = paginator . page ( page_no )
except ( EmptyPage , InvalidPage ) :
results = paginator . page ( paginator . num_pages )
for r in results . object_list :
2011-01-04 06:27:10 +00:00
ret . append ( r . list_dict ( ) )
2011-08-25 09:39:15 +00:00
2011-10-23 23:53:51 +00:00
2011-09-10 01:40:47 +00:00
return {
' page_no ' : page_no ,
' num_pages ' : paginator . num_pages ,
' items ' : ret
}
2011-01-04 06:27:10 +00:00
2011-04-10 02:00:43 +00:00
@classmethod
def get_qset ( kls ) :
'''
Override this method in your model class to define a custom queryset instead of objects . all ( ) , for instance , to always exclude unpublished items .
'''
raise NotImplementedError
2011-03-18 04:49:27 +00:00
2011-01-04 06:27:10 +00:00
def getField ( fields , name ) :
for f in fields :
if f . name == name :
return f
return False
2010-12-06 22:33:00 +00:00
2011-02-01 15:13:30 +00:00
2011-03-18 04:49:27 +00:00
2011-02-01 15:13:30 +00:00
def site_config ( ) :
with open ( settings . SITE_CONFIG ) as f :
site_config = json . load ( f )
site_config [ ' keys ' ] = { }
for key in site_config [ ' itemKeys ' ] :
site_config [ ' keys ' ] [ key [ ' id ' ] ] = key
site_config [ ' _findKeys ' ] = { }
for key in site_config [ ' findKeys ' ] :
site_config [ ' _findKeys ' ] [ key [ ' id ' ] ] = key
return site_config