def get_model_replacement(self, view): subclass_filter = get_subclass_filter(view) if subclass_filter: model_str = '|'.join([get_model_name(model) for model in subclass_filter.subclasses]) else: model_str = get_model_name(view.model) return model_str
def add_validation(self, model): rules = {} for field in model._meta.fields: if is_excluded(model, field.name) or is_readonly(model, field.name) or is_included(model, field.name): continue key = field.name if self.camelcase: key = underscore_to_camel_case(key) rules[key] = ApiFieldRule(field).rule if rules: self.models[get_model_name(model)]['rules'] = rules if not self.cord: self.models[get_model_name(model)]['validate'] = 'validate'
def get_include_related(self, model): related_models = {} name = get_model_name(model) if hasattr(model, 'API') and hasattr(model.API, 'include_related'): include_related = model.API.include_related for field in model._meta.fields: if field.name in include_related: if self.camelcase: field_name = underscore_to_camel_case(field.name) else: field_name = field.name related_models[field_name] = get_model_name(get_related_model(field)) if related_models: self.include_related[name] = related_models
def add_model(self, model, extra): # Add the model for any resource type name = get_model_name(model) if not self.models.has_key(name): self.models[name] = {} if self.renameid: self.models[name]['idAttribute'] = camel_case_to_underscore(name) + '_id' if self.camelcase: self.models[name]['idAttribute'] = underscore_to_camel_case(self.models[name]['idAttribute']) self.add_parse(model) if self.choices: self.add_choices(model) if self.defaults: self.add_defaults(model) if self.descriptions: self.add_descriptions(model) if self.formats: self.add_instructions(model) if self.titles: self.add_titles(model) if self.validation: self.add_validation(model) self.translate_properties(model) self.get_include_related(model) self.get_readonly_fields(model) self.models[name].update(extra)
def add_titles(self, model): titles = {} for field in model._meta.fields: if is_excluded(model, field.name): continue key = field.name if self.camelcase: key = underscore_to_camel_case(key) titles[key] = field.verbose_name.title() if titles: self.models[get_model_name(model)]['titles'] = titles
def add_descriptions(self, model): subtitles = {} for field in model._meta.fields: if is_excluded(model, field.name): continue if hasattr(field, 'help_text') and field.help_text: key = field.name if self.camelcase: key = underscore_to_camel_case(key) subtitles[key] = force_unicode(field.help_text) if subtitles: self.models[get_model_name(model)]['subtitles'] = subtitles
def enum_patterns(self, patterns): for pattern in patterns: if pattern.callback: if isinstance(pattern.callback, (api_view, BasicApiView)): self.regex_stack.append(pattern._regex) view = pattern.callback url = format_regex_stack(self.regex_stack) resource_type = get_resource_type(self.regex_stack, pattern) model_extra = {} if resource_type == 'Collection': collection_name = get_collection_name(view) if url.find('<object_id>') == -1 and url.find('<slug>') == -1: # Unrelated self.collections[collection_name] = {'url': url, 'model': 'model###' + self.get_model_replacement(view)} else: # Related parent_name = get_model_name(view.parent_model) if url.find('<object_id>') != -1: if not self.related_collections.has_key(parent_name): self.related_collections[parent_name] = [] self.related_collections[parent_name].append({'collection': collection_name, 'url': url.replace('<object_id>', '" + this.id + "')}) # Generate a blank collection class for related items if needed if not self.collections.has_key(collection_name): self.collections[collection_name] = {'model': 'model###' + get_model_name(view.model)} elif resource_type == 'Object': if url.find('<object_id>') != -1: # Remove the last piece of the url path, should be <object_id>, don't look for <slug> because the idAttribute above only allows the object id model_extra['urlRoot'] = '/' + '/'.join(url.strip('/').split('/')[:-1]) elif resource_type == 'Single Object': self.singletons[get_model_name(view.model)] = '/' + url.strip('/') # Add the model for any view without a subclass filter if not get_subclass_filter(view): self.add_model(view.model, model_extra) self.regex_stack.pop() else: self.regex_stack.append(pattern._regex) self.enum_patterns(pattern.url_patterns) if self.regex_stack: self.regex_stack.pop()
def add_parse(self, model): fields = [] for field in model._meta.fields: if is_excluded(model, field.name): continue # Parse DateField and DateTimeFields, but not TimeFields if isinstance(field, DateField): if self.camelcase: fields.append("'%s'" % underscore_to_camel_case(field.name)) else: fields.append("'%s'" % field.name) if fields: self.models[get_model_name(model)]['parse'] = ', '.join(fields)
def add_defaults(self, model): name = get_model_name(model) for field in model._meta.fields: if is_excluded(model, field.name) or is_readonly(model, field.name): continue default = field.default if isinstance(default, type): default = default() if default is not NOT_PROVIDED and not callable(default): if not self.models[name].has_key('defaults'): self.models[name]['defaults'] = {} key = field.name if self.camelcase: key = underscore_to_camel_case(key) self.models[name]['defaults'][key] = default
def add_choices(self, model): choices = {} for field in model._meta.fields: if is_excluded(model, field.name): continue if hasattr(field, 'choices') and field.choices: field_choices = {} for choice in field.choices: field_choices[choice[0]] = choice[1] key = field.name if self.camelcase: key = underscore_to_camel_case(key) choices[key] = field_choices if choices: self.models[get_model_name(model)]['choices'] = choices
def get_readonly_fields(self, model): fields = [] included_fields = [] name = get_model_name(model) for field in model._meta.fields: if is_excluded(model, field.name): continue if is_readonly(model, field.name): key = field.name if self.camelcase: key = underscore_to_camel_case(key) if is_included(model, field.name): included_fields.append(key) fields.append(key) if field: self.readonly_fields[name] = fields if included_fields: self.readonly_included_fields[name] = included_fields
def add_instructions(self, model): instructions = {} for field in model._meta.fields: if is_excluded(model, field.name): continue key = field.name if self.camelcase: key = underscore_to_camel_case(key) message = force_unicode(field.error_messages.get('invalid', field.error_messages.get('invalid_choice', ''))) default_invalid = default_invalid_choice = None for cls in reversed([field.__class__] + get_base_classes(field.__class__)): if not hasattr(cls, 'default_error_messages'): continue default_invalid = cls.default_error_messages.get('invalid', default_invalid) default_invalid_choice = cls.default_error_messages.get('invalid_choice', default_invalid_choice) if message and message != default_invalid and message != default_invalid_choice: instructions[key] = message if instructions: self.models[get_model_name(model)]['instructions'] = instructions
def translate_properties(self, model): lang = 'es6' if self.es6 else 'js' model_properties = {} model_properties_args = {} for cls in [model] + get_base_classes(model): for name in cls.__dict__: attr = cls.__dict__[name] if type(attr) is property and attr.fget and hasattr(attr.fget, 'api_code'): if self.camelcase: name = underscore_to_camel_case(name) if getattr(attr.fget, 'api_translations', None) and attr.fget.api_translations.has_key(lang): model_properties[name] = attr.fget.api_translations[lang] else: model_properties[name] = translate_code(attr.fget.api_code, lang, BackboneAttributeTransformer(model)) # If using Cord, then convert all references to other api properties to a get model call then to just arguments passed into the getter instead if self.cord: def replace_properties(m): prop = m.group(1) if prop in model_properties: return 'this.get("%s")' % prop return m.group(0) def replace_attributes(args, m): attr = m.group(1) args.add(attr) return attr for name, code in model_properties.items(): model_properties_args[name] = set() if code.find('this.id'): model_properties_args[name].add('id') code = re.sub(r'this.([0-9a-zA-Z_]*)', replace_properties, code) model_properties[name] = re.sub(r'this.get\("([0-9a-zA-Z_]*)"\)', partial(replace_attributes, model_properties_args[name]), code) model_name = get_model_name(model) if model_properties: self.model_properties[model_name] = model_properties if model_properties_args: self.model_properties_args[model_name] = model_properties_args
def get_context(self, app_label): context = { 'name': app_label, 'name_lower': app_label[0].lower() + app_label[1:] } if hasattr(self, 'extra_context'): context.update(self.extra_context()) # Loop over the view mappings for mapping_name in self.mappings: mapping = self.mappings[mapping_name] lines = [] for url_format, view in self.views.iteritems(): for action in self.get_view_actions(self.urls[url_format], view): line = None if mapping.has_key(action): format_context = { 'url': self.urls[url_format], 'url_format': url_format, 'view': view, 'app_name': app_label, 'app_name_lower': app_label[0].lower() + app_label[1:], 'model_name': view.model.__name__, 'name': view.model.__name__, 'name_lower': view.model.__name__[0].lower() + view.model.__name__[1:], 'name_plural': view.model._meta.verbose_name_plural.title( ).replace(' ', ''), 'name_plural_lower': view.model._meta.verbose_name_plural[0].lower() + view.model._meta.verbose_name_plural.title( ).replace(' ', '')[1:], 'login': ((view.requirements & ApiRequirement.LOGIN) and not (action.startswith('READ') and (view.requirements & ApiRequirement.ANONYMOUS_READ))), 'https': (view.requirements & ApiRequirement.HTTPS), 'hmac': (view.requirements & ApiRequirement.HMAC) } subclass_filter = get_subclass_filter(view) if subclass_filter: format_context['subclasses'] = [ (_ApiModel(model).id_field[1], get_model_name(model)) for model in subclass_filter.subclasses ] format_context.update( self.get_param_context(self.urls[url_format], action)) if hasattr(view, 'parent_model') and view.parent_model: # Related and basic api views format_context[ 'parent_name'] = view.parent_model.__name__ format_context[ 'parent_name_lower'] = view.parent_model.__name__[ 0].lower() + view.parent_model.__name__[1:] format_context[ 'parent_name_plural'] = view.parent_model._meta.verbose_name_plural.title( ).replace(' ', '') format_context[ 'parent_name_plural_lower'] = view.parent_model._meta.verbose_name_plural[ 0].lower( ) + view.parent_model._meta.verbose_name_plural.title( ).replace(' ', '')[1:] line = self.perform_mapping(mapping[action], format_context) if line is None: raise CommandError("No such mapping for %s in %s." % (action, mapping_name)) elif line: line = line.split('\n') if not mapping.get('RemoveDuplicates', False) or not is_sublist( lines, line): lines.extend(line) context[mapping_name] = lines if mapping.get('Sort', False): context[mapping_name].sort() return context