def rest_cards(request): #todo:refactor into facts (no???) ''' Returns the cards for a given fact. Accepts `fact` in the GET params. ''' if request.GET['fact']: fact = get_object_or_404(Fact, pk=request.GET['fact']) return to_dojo_data(fact.card_set.get_query_set())
def rest_card_templates_for_fact(request, fact_id): ''' Returns a list of card templates for which the given fact has corresponding cards activated. ''' fact = get_object_or_404(Fact, pk=fact_id) activated_card_templates = list(e.template for e in fact.card_set.filter(active=True)) card_templates = [] for card_template in fact.fact_type.cardtemplate_set.all(): #TODO-OLD only send the id(uri)/name/status card_templates.append({ 'card_template': card_template, 'activated_for_fact': (card_template in activated_card_templates), }) return to_dojo_data(card_templates, identifier=None)
def rest_card_templates_for_fact(request, fact_id): ''' Returns a list of card templates for which the given fact has corresponding cards activated. ''' fact = get_object_or_404(Fact, pk=fact_id) activated_card_templates = list( e.template for e in fact.card_set.filter(active=True)) card_templates = [] for card_template in fact.fact_type.cardtemplate_set.all(): #TODO only send the id(uri)/name/status card_templates.append({ 'card_template': card_template, 'activated_for_fact': (card_template in activated_card_templates), }) return to_dojo_data(card_templates, identifier=None)
def user_list_datagrid(request): ### need to hand pick fields from TegakiUser, if some are None, need to pass back empty strings for dojo dojo_obs = [] users, num = datagrid_helper(TegakiUser, request) for u in users: djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = u.user.id djob['user__username'] = u.user.username if u.country: djob['country'] = u.country if u.lang: djob['lang__description'] = u.lang.description if u.description: djob['description'] = u.description if u.show_handwriting_samples: #only if they publicly display their samples djob['n_handwriting_samples'] = u.n_handwriting_samples dojo_obs += [djob] return to_dojo_data(dojo_obs, identifier='user__username', num_rows=num)
def samples_datagrid(request): ### need to hand pick fields from TegakiUser, if some are None, need to pass back empty strings for dojo dojo_obs = [] samples, num = datagrid_helper(HandWritingSample, request) for s in samples: djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = s.id djob['character__utf8'] = s.character.utf8() djob['character__lang__description'] = s.character.lang.description djob['date'] = s.date djob['user__username'] = s.user.username if s.user.get_profile().show_handwriting_samples or request.user == s.user: #only if they publicly display this charset #or it's their charset dojo_obs += [djob] else: num = num -1 return to_dojo_data(dojo_obs, identifier='id', num_rows=num)
def samples_datagrid(request): ### need to hand pick fields from TegakiUser, if some are None, need to pass back empty strings for dojo dojo_obs = [] samples, num = datagrid_helper(HandWritingSample, request) for s in samples: djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = s.id djob['character__utf8'] = s.character.utf8() djob['character__lang__description'] = s.character.lang.description djob['date'] = s.date djob['character_set__name'] = s.character_set.name djob['user__username'] = s.user.username if s.user.get_profile().show_handwriting_samples or request.user == s.user: #only if they publicly display this charset #or it's their charset dojo_obs += [djob] else: num = num -1 return to_dojo_data(dojo_obs, identifier='id', num_rows=num)
def assignments_datagrid(request): ### need to hand pick fields from Assignments, if some are None, need to pass back empty strings for dojo dojo_obs = [] assignments, num = datagrid_helper(Assigment, request) for a in assignments: djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = a.id #djob['character__utf8'] = s.character.utf8() #djob['character__lang__description'] = s.character.lang.description #djob['date'] = s.date #djob['character_set__name'] = s.character_set.name #djob['user__username'] = s.user.username #if s.user.get_profile().show_handwriting_samples or request.user == s.user: #only if they publicly display this charset #or it's their charset # dojo_obs += [djob] #else: # num = num -1 return to_dojo_data(dojo_obs, identifier='id', num_rows=num)
def charset_datagrid(request): ### need to hand pick fields from TegakiUser, if some are None, need to pass back empty strings for dojo dojo_obs = [] charsets, num = datagrid_helper(CharacterSet, request) for c in charsets: djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = c.id djob['name'] = c.name djob['lang__description'] = c.lang.description djob['description'] = c.description djob['random_char'] = unichr(c.get_random()) djob['characters'] = c.characters #might want to do something else for display if c.user: djob['user__username'] = c.user.username if c.public or request.user == c.user: #only if they publicly display this charset #or it's their charset dojo_obs += [djob] else: num = num -1 return to_dojo_data(dojo_obs, identifier='id', num_rows=num)
def disks_datagrid_json(request): disks = models.Disk.objects.filter(disk_enabled=True, disk_multipath_name='') complete = [] for data in disks: ret = {} ret['edit'] = { 'edit_url': reverse('freeadmin_model_edit', kwargs={ 'app': 'storage', 'model': 'Disk', 'oid': data.id, }) + '?deletable=false', 'wipe_url': reverse('storage_disk_wipe', kwargs={ 'devname': data.disk_name, }), } ret['edit'] = simplejson.dumps(ret['edit']) for f in data._meta.fields: # filefields can't be json serialized if isinstance(f, dmodels.ImageField) or \ isinstance(f, dmodels.FileField): ret[f.attname] = unicode(getattr(data, f.attname)) else: #json_encode() this? ret[f.attname] = getattr(data, f.attname) ret['devname'] = data.devname complete.append(ret) return HttpResponse( simplejson.dumps( to_dojo_data(complete, identifier=models.Disk._meta.pk.name, num_rows=len(disks))))
def disks_datagrid_json(request): disks = models.Disk.objects.filter( disk_enabled=True, disk_multipath_name='' ) complete = [] for data in disks: ret = {} ret['edit'] = { 'edit_url': reverse('freeadmin_model_edit', kwargs={ 'app': 'storage', 'model': 'Disk', 'oid': data.id, }) + '?deletable=false', 'wipe_url': reverse('storage_disk_wipe', kwargs={ 'devname': data.disk_name, }), } ret['edit'] = simplejson.dumps(ret['edit']) for f in data._meta.fields: # filefields can't be json serialized if isinstance(f, dmodels.ImageField) or \ isinstance(f, dmodels.FileField): ret[f.attname] = unicode(getattr(data, f.attname)) else: #json_encode() this? ret[f.attname] = getattr(data, f.attname) ret['devname'] = data.devname complete.append(ret) return HttpResponse(simplejson.dumps( to_dojo_data(complete, identifier=models.Disk._meta.pk.name, num_rows=len(disks)) ))
def charset_datagrid(request): ### need to hand pick fields from TegakiUser, if some are None, need to pass back empty strings for dojo dojo_obs = [] charsets, num = datagrid_helper(CharacterSet, request) for c in charsets: print c djob = {} #'id', 'user__username', 'country', 'lang', 'description', 'n_handwriting_samples' djob['id'] = c.id djob['name'] = c.name djob['lang__description'] = c.lang.description djob['description'] = c.description #print c.get_random() djob['random_char'] = unichr(c.get_random()) #djob['characters'] = c.characters #might want to do something else for display djob['number_of_characters'] = len(c) if c.user: djob['user__username'] = c.user.username if c.public or request.user == c.user: #only if they publicly display this charset #or it's their charset dojo_obs += [djob] else: num = num -1 return to_dojo_data(dojo_obs, identifier='id', num_rows=num)
def rest_fact_types(request): return to_dojo_data(FactType.objects.all())
def rest_fields(request, fact_type_id): '''Returns list of Field objects given a FactType id''' fact_type = get_object_or_404(FactType, pk=fact_type_id) return to_dojo_data(fact_type.fieldtype_set.all().order_by('ordinal'))
def rest_card_templates(request, fact_type_id): '''Returns list of CardTemplate objects given a parent FactType id''' fact_type = get_object_or_404(FactType, pk=fact_type_id) return to_dojo_data(fact_type.cardtemplate_set.all())
def serialize(self, querySet, totalRows): return to_dojo_data( list(QuerySetSerializer.serialize(self, querySet)), identifier=self.identifier, num_rows=totalRows)
def rest_facts(request, deck=None, tags=None): #TODO refactor into facts (no???) if request.method == 'GET': ret = [] if request.GET['fact_type']: fact_type_id = request.GET['fact_type'] fact_type = get_object_or_404(FactType, pk=fact_type_id) user = deck.owner if deck else request.user facts = Fact.objects.with_upstream( user, deck=deck, tags=tags).filter(active=True) #is the user searching his facts? if ('search' in request.GET and request.GET['search'].strip()): search_query = request.GET['search'] facts = Fact.objects.search( fact_type, search_query, query_set=facts) #FIXME add search for synchronized facts too! for fact in facts.iterator(): row = { 'fact-id': fact.id, 'suspended': fact.suspended(), } ident, name = '', '' for field_content in fact.field_contents: #TODO rename to be clearer, like field_id, or ??? key = 'id{0}'.format(field_content.field_type_id) if not ident: ident = key elif not name: name = key row[key] = field_content.human_readable_content() row['{0}_field-content-id'.format(key)] = field_content.id if not name: name = ident ret.append(row) ret = to_dojo_data(ret) ret['identifier'] = 'fact-id' #ret['name'] = name #todo:for <2 cols/fields...? return ret elif request.method == 'POST': # Create fact in deck, including its fields and cards. POST method. #TODO refactor into other module probably ret = {} #TODO just get this from the form object. deck = get_deck_or_404(request.user, request.POST['fact-deck'], must_own=True) # Override the submitted deck ID with the ID from the URL, # since this is a RESTful interface. post_data = request.POST.copy() #post_data['fact-deck'] = deck_id #todo: refactor this into model code #CardFormset = modelformset_factory(Card, exclude=('fact', 'ease_factor', )) #TODO make from CardForm #card_formset = CardFormset(post_data, prefix='card') card_templates = CardTemplate.objects.filter( id__in=[e[1] for e in post_data.items() if e[0].find('card_template') == 0]) #FieldContentFormset = modelformset_factory(FieldContent, exclude=('fact', )) FieldContentFormset = modelformset_factory( FieldContent, form=FieldContentForm) field_content_formset = FieldContentFormset( post_data, prefix='field_content') fact_form = FactForm(post_data, prefix='fact') if field_content_formset.is_valid() and fact_form.is_valid(): #TODO automate the tag saving in forms.py new_fact = fact_form.save() new_fact.active = True new_fact.save() # maps subfact group numbers to the subfact object group_to_subfact = {} for field_content_form in field_content_formset.forms: #TODO don't create fieldcontent objects for # optional fields which were left blank. new_field_content = field_content_form.save(commit=False) # is this a field of the parent fact, or a subfact? if (new_field_content.field_type.fact_type == new_fact.fact_type): # parent fact new_field_content.fact = new_fact else: # subfact group = field_content_form\ .cleaned_data['subfact_group'] if group not in group_to_subfact.keys(): # create the new subfact new_subfact = Fact( fact_type=new_field_content\ .field_type.fact_type, active=True, #deck=new_fact.deck, parent_fact=new_fact, ) new_subfact.save() group_to_subfact[group] = new_subfact new_field_content.fact = group_to_subfact[group] new_field_content.save() for card_template in card_templates: #card_form in card_formset.forms: new_card = Card( template=card_template, fact=new_fact, active=True, priority = 0) new_card.randomize_new_order() new_card.save() else: raise ApiException({ #'card': card_formset.errors, 'field_content': field_content_formset.errors, 'fact': [fact_form.errors] }) return ret
def datagrid_list(request, app_name, model_name, access_model_callback=access_model, access_field_callback=access_model_field): """ Renders a json representation of a model within an app. Set to handle GET params passed by dojos ReadQueryStore for the dojango datagrid. The following GET params are handled with specially: 'search_fields','inclusions','sort','search','count','order','start' search_fields: list of fields for model to equal the search, each OR'd together. search: see search_fields sort: sets order_by count: sets limit start: sets offset inclusions: list of functions in the model that will be called and result added to JSON any other GET param will be added to the filter on the model to determine what gets returned. ie a GET param of id__gt=5 will result in the equivalent of model.objects.all().filter( id__gt=5 ) The access_model_callback is a function that gets passed the request, app_name, model_name, and an instance of the model which will only be added to the json response if returned True The access_field_callback gets passed the request, app_name, model_name, field_name, and the instance. Return true to allow access of a given field_name to model app_name.model_name given instance model. The default callbacks will allow access to any model in added to the DOJANGO_DATAGRID_ACCESS in settings.py and any function/field that is not "delete" """ # get the model model = get_model(app_name,model_name) # start with a very broad query set target = model.objects.all() # modify query set based on the GET params, dont do the start/count splice # custom options passed from "query" param in datagrid for key in [ d for d in request.GET.keys() if not d in AVAILABLE_OPTS]: target = target.filter(**{str(key):request.GET[key]}) num = target.count() # until after all clauses added if request.GET.has_key('search') and request.GET.has_key('search_fields'): ored = [models.Q(**{str(k).strip(): unicode(request.GET['search'])} ) for k in request.GET['search_fields'].split(",")] target = target.filter(reduce(operator.or_, ored)) if request.GET.has_key('sort') and request.GET["sort"] not in request.GET["inclusions"] and request.GET["sort"][1:] not in request.GET["inclusions"]: # if the sort field is in inclusions, it must be a function call.. target = target.order_by(request.GET['sort']) else: if request.GET.has_key('sort') and request.GET["sort"].startswith('-'): target = sorted(target, lambda x,y: cmp(getattr(x,request.GET["sort"][1:])(),getattr(y,request.GET["sort"][1:])())); target.reverse(); elif request.GET.has_key('sort'): target = sorted(target, lambda x,y: cmp(getattr(x,request.GET["sort"])(),getattr(y,request.GET["sort"])())); # get only the limit number of models with a given offset target=target[int(request.GET['start']):int(request.GET['start'])+int(request.GET['count'])] # create a list of dict objects out of models for json conversion complete = [] for data in target: # TODO: complete rewrite to use dojangos already existing serializer (or the dojango ModelStore) if access_model_callback(app_name, model_name, request, data): ret = {} for f in data._meta.fields: if access_field_callback(app_name, model_name, f.attname, request, data): if isinstance(f, models.ImageField) or isinstance(f, models.FileField): # filefields can't be json serialized ret[f.attname] = unicode(getattr(data, f.attname)) else: ret[f.attname] = getattr(data, f.attname) #json_encode() this? fields = dir(data.__class__) + ret.keys() add_ons = [k for k in dir(data) if k not in fields and access_field_callback(app_name, model_name, k, request, data)] for k in add_ons: ret[k] = getattr(data, k) if request.GET.has_key('inclusions'): for k in request.GET['inclusions'].split(','): if k == "": continue if access_field_callback(app_name, model_name, k, request, data): try: ret[k] = getattr(data,k)() except: try: ret[k] = eval("data.%s"%".".join(k.split("__"))) except: ret[k] = getattr(data,k) complete.append(ret) else: raise Exception, "You're not allowed to query the model '%s.%s' (add it to the array of the DOJANGO_DATAGRID_ACCESS setting)" % (model_name, app_name) return to_dojo_data(complete, identifier=model._meta.pk.name, num_rows=num)
def test_states(request): states = [ {'name':"Alabama", 'label':"<img width='97px' height='127px' src='images/Alabama.jpg'/>Alabama",'abbreviation':"AL"}, {'name':"Alaska", 'label':"Alaska",'abbreviation':"AK"}, {'name':"American Samoa", 'label':"American Samoa",'abbreviation':"AS"}, {'name':"Arizona", 'label':"Arizona",'abbreviation':"AZ"}, {'name':"Arkansas", 'label':"Arkansas",'abbreviation':"AR"}, {'name':"Armed Forces Europe", 'label':"Armed Forces Europe",'abbreviation':"AE"}, {'name':"Armed Forces Pacific", 'label':"Armed Forces Pacific",'abbreviation':"AP"}, {'name':"Armed Forces the Americas", 'label':"Armed Forces the Americas",'abbreviation':"AA"}, {'name':"California", 'label':"California",'abbreviation':"CA"}, {'name':"Colorado", 'label':"Colorado",'abbreviation':"CO"}, {'name':"Connecticut", 'label':"Connecticut",'abbreviation':"CT"}, {'name':"Delaware", 'label':"Delaware",'abbreviation':"DE"}, {'name':"District of Columbia", 'label':"District of Columbia",'abbreviation':"DC"}, {'name':"Federated States of Micronesia", 'label':"Federated States of Micronesia",'abbreviation':"FM"}, {'name':"Florida", 'label':"Florida",'abbreviation':"FL"}, {'name':"Georgia", 'label':"Georgia",'abbreviation':"GA"}, {'name':"Guam", 'label':"Guam",'abbreviation':"GU"}, {'name':"Hawaii", 'label':"Hawaii",'abbreviation':"HI"}, {'name':"Idaho", 'label':"Idaho",'abbreviation':"ID"}, {'name':"Illinois", 'label':"Illinois",'abbreviation':"IL"}, {'name':"Indiana", 'label':"Indiana",'abbreviation':"IN"}, {'name':"Iowa", 'label':"Iowa",'abbreviation':"IA"}, {'name':"Kansas", 'label':"Kansas",'abbreviation':"KS"}, {'name':"Kentucky", 'label':"Kentucky",'abbreviation':"KY"}, {'name':"Louisiana", 'label':"Louisiana",'abbreviation':"LA"}, {'name':"Maine", 'label':"Maine",'abbreviation':"ME"}, {'name':"Marshall Islands", 'label':"Marshall Islands",'abbreviation':"MH"}, {'name':"Maryland", 'label':"Maryland",'abbreviation':"MD"}, {'name':"Massachusetts", 'label':"Massachusetts",'abbreviation':"MA"}, {'name':"Michigan", 'label':"Michigan",'abbreviation':"MI"}, {'name':"Minnesota", 'label':"Minnesota",'abbreviation':"MN"}, {'name':"Mississippi", 'label':"Mississippi",'abbreviation':"MS"}, {'name':"Missouri", 'label':"Missouri",'abbreviation':"MO"}, {'name':"Montana", 'label':"Montana",'abbreviation':"MT"}, {'name':"Nebraska", 'label':"Nebraska",'abbreviation':"NE"}, {'name':"Nevada", 'label':"Nevada",'abbreviation':"NV"}, {'name':"New Hampshire", 'label':"New Hampshire",'abbreviation':"NH"}, {'name':"New Jersey", 'label':"New Jersey",'abbreviation':"NJ"}, {'name':"New Mexico", 'label':"New Mexico",'abbreviation':"NM"}, {'name':"New York", 'label':"New York",'abbreviation':"NY"}, {'name':"North Carolina", 'label':"North Carolina",'abbreviation':"NC"}, {'name':"North Dakota", 'label':"North Dakota",'abbreviation':"ND"}, {'name':"Northern Mariana Islands", 'label':"Northern Mariana Islands",'abbreviation':"MP"}, {'name':"Ohio", 'label':"Ohio",'abbreviation':"OH"}, {'name':"Oklahoma", 'label':"Oklahoma",'abbreviation':"OK"}, {'name':"Oregon", 'label':"Oregon",'abbreviation':"OR"}, {'name':"Pennsylvania", 'label':"Pennsylvania",'abbreviation':"PA"}, {'name':"Puerto Rico", 'label':"Puerto Rico",'abbreviation':"PR"}, {'name':"Rhode Island", 'label':"Rhode Island",'abbreviation':"RI"}, {'name':"South Carolina", 'label':"South Carolina",'abbreviation':"SC"}, {'name':"South Dakota", 'label':"South Dakota",'abbreviation':"SD"}, {'name':"Tennessee", 'label':"Tennessee",'abbreviation':"TN"}, {'name':"Texas", 'label':"Texas",'abbreviation':"TX"}, {'name':"Utah", 'label':"Utah",'abbreviation':"UT"}, {'name':"Vermont", 'label':"Vermont",'abbreviation':"VT"}, {'name': "Virgin Islands, U.S.",'label':"Virgin Islands, U.S.",'abbreviation':"VI"}, {'name':"Virginia", 'label':"Virginia",'abbreviation':"VA"}, {'name':"Washington", 'label':"Washington",'abbreviation':"WA"}, {'name':"West Virginia", 'label':"West Virginia",'abbreviation':"WV"}, {'name':"Wisconsin", 'label':"Wisconsin",'abbreviation':"WI"}, {'name':"Wyoming", 'label':"Wyoming",'abbreviation':"WY"} ] # Implement a very simple search! search_string, start, end = get_combobox_data(request) ret = [] for state in states: if state['name'].lower().startswith(search_string.lower()): ret.append(state) ret = ret[start:end] # Convert the data into dojo.date-store compatible format. return to_dojo_data(ret, identifier='abbreviation')
def rest_facts(request, deck=None, tags=None): #TODO-OLD refactor into facts (no???) if request.method == 'GET': ret = [] if request.GET['fact_type']: fact_type_id = request.GET['fact_type'] fact_type = get_object_or_404(FactType, pk=fact_type_id) user = deck.owner if deck else request.user facts = Fact.objects.with_upstream(user, deck=deck, tags=tags).filter(active=True) #is the user searching his facts? if ('search' in request.GET and request.GET['search'].strip()): search_query = request.GET['search'] facts = Fact.objects.search(fact_type, search_query, query_set=facts) #FIXME add search for synchronized facts too! for fact in facts.iterator(): row = { 'fact-id': fact.id, 'suspended': fact.suspended(), } ident, name = '', '' for field_content in fact.field_contents: #TODO-OLD rename to be clearer, like field_id, or ??? key = 'id{0}'.format(field_content.field_type_id) if not ident: ident = key elif not name: name = key row[key] = field_content.human_readable_content() row['{0}_field-content-id'.format(key)] = field_content.id if not name: name = ident ret.append(row) ret = to_dojo_data(ret) ret['identifier'] = 'fact-id' #ret['name'] = name #todo:for <2 cols/fields...? return ret elif request.method == 'POST': # Create fact in deck, including its fields and cards. POST method. #TODO-OLD refactor into other module probably ret = {} #TODO-OLD just get this from the form object. deck = get_deck_or_404(request.user, request.POST['fact-deck'], must_own=True) # Override the submitted deck ID with the ID from the URL, # since this is a RESTful interface. post_data = request.POST.copy() #post_data['fact-deck'] = deck_id #todo: refactor this into model code #CardFormset = modelformset_factory(Card, exclude=('fact', 'ease_factor', )) #TODO-OLD make from CardForm #card_formset = CardFormset(post_data, prefix='card') card_templates = CardTemplate.objects.filter(id__in=[ e[1] for e in post_data.items() if e[0].find('card_template') == 0 ]) #FieldContentFormset = modelformset_factory(FieldContent, exclude=('fact', )) FieldContentFormset = modelformset_factory(FieldContent, form=FieldContentForm) field_content_formset = FieldContentFormset(post_data, prefix='field_content') fact_form = FactForm(post_data, prefix='fact') if field_content_formset.is_valid() and fact_form.is_valid(): #TODO-OLD automate the tag saving in forms.py new_fact = fact_form.save() new_fact.active = True new_fact.save() # maps subfact group numbers to the subfact object group_to_subfact = {} for field_content_form in field_content_formset.forms: #TODO-OLD don't create fieldcontent objects for # optional fields which were left blank. new_field_content = field_content_form.save(commit=False) # is this a field of the parent fact, or a subfact? if (new_field_content.field_type.fact_type == new_fact.fact_type): # parent fact new_field_content.fact = new_fact else: # subfact group = field_content_form\ .cleaned_data['subfact_group'] if group not in group_to_subfact.keys(): # create the new subfact new_subfact = Fact( fact_type=new_field_content\ .field_type.fact_type, active=True, #deck=new_fact.deck, parent_fact=new_fact, ) new_subfact.save() group_to_subfact[group] = new_subfact new_field_content.fact = group_to_subfact[group] new_field_content.save() for card_template in card_templates: #card_form in card_formset.forms: new_card = Card(template=card_template, fact=new_fact, active=True, priority=0) new_card.randomize_new_order() new_card.save() else: raise ApiException({ #'card': card_formset.errors, 'field_content': field_content_formset.errors, 'fact': [fact_form.errors] }) return ret
def datagrid_list(request, app_name, model_name, access_model_callback=access_model, access_field_callback=access_model_field): """ Renders a json representation of a model within an app. Set to handle GET params passed by dojos ReadQueryStore for the dojango datagrid. The following GET params are handled with specially: 'search_fields','inclusions','sort','search','count','order','start' search_fields: list of fields for model to equal the search, each OR'd together. search: see search_fields sort: sets order_by count: sets limit start: sets offset inclusions: list of functions in the model that will be called and result added to JSON any other GET param will be added to the filter on the model to determine what gets returned. ie a GET param of id__gt=5 will result in the equivalent of model.objects.all().filter( id__gt=5 ) The access_model_callback is a function that gets passed the request, app_name, model_name, and an instance of the model which will only be added to the json response if returned True The access_field_callback gets passed the request, app_name, model_name, field_name, and the instance. Return true to allow access of a given field_name to model app_name.model_name given instance model. The default callbacks will allow access to any model in added to the DOJANGO_DATAGRID_ACCESS in settings.py and any function/field that is not "delete" """ # get the model model = get_model(app_name,model_name) # start with a very broad query set target = model.objects.all() # modify query set based on the GET params, dont do the start/count splice # custom options passed from "query" param in datagrid for key in [ d for d in list(request.GET.keys()) if not d in AVAILABLE_OPTS]: target = target.filter(**{str(key):request.GET[key]}) num = target.count() # until after all clauses added if 'search' in request.GET and 'search_fields' in request.GET: ored = [models.Q(**{str(k).strip(): str(request.GET['search'])} ) for k in request.GET['search_fields'].split(",")] target = target.filter(reduce(operator.or_, ored)) if 'sort' in request.GET and request.GET["sort"] not in request.GET["inclusions"] and request.GET["sort"][1:] not in request.GET["inclusions"]: # if the sort field is in inclusions, it must be a function call.. target = target.order_by(request.GET['sort']) else: if 'sort' in request.GET and request.GET["sort"].startswith('-'): target = sorted(target, lambda x,y: cmp(getattr(x,request.GET["sort"][1:])(),getattr(y,request.GET["sort"][1:])())); target.reverse(); elif 'sort' in request.GET: target = sorted(target, lambda x,y: cmp(getattr(x,request.GET["sort"])(),getattr(y,request.GET["sort"])())); # get only the limit number of models with a given offset target=target[int(request.GET['start']):int(request.GET['start'])+int(request.GET['count'])] # create a list of dict objects out of models for json conversion complete = [] for data in target: # TODO: complete rewrite to use dojangos already existing serializer (or the dojango ModelStore) if access_model_callback(app_name, model_name, request, data): ret = {} for f in data._meta.fields: if access_field_callback(app_name, model_name, f.attname, request, data): if isinstance(f, models.ImageField) or isinstance(f, models.FileField): # filefields can't be json serialized ret[f.attname] = str(getattr(data, f.attname)) else: ret[f.attname] = getattr(data, f.attname) #json_encode() this? fields = dir(data.__class__) + list(ret.keys()) add_ons = [k for k in dir(data) if k not in fields and access_field_callback(app_name, model_name, k, request, data)] for k in add_ons: ret[k] = getattr(data, k) if 'inclusions' in request.GET: for k in request.GET['inclusions'].split(','): if k == "": continue if access_field_callback(app_name, model_name, k, request, data): try: ret[k] = getattr(data,k)() except: try: ret[k] = eval("data.%s"%".".join(k.split("__"))) except: ret[k] = getattr(data,k) complete.append(ret) else: raise Exception("You're not allowed to query the model '%s.%s' (add it to the array of the DOJANGO_DATAGRID_ACCESS setting)" % (model_name, app_name)) return to_dojo_data(complete, identifier=model._meta.pk.name, num_rows=num)