def q_realization_add_relationship_value(request): valid_request, msg = validate_request(request) if not valid_request: return HttpResponseForbidden(msg) target_proxy_id = request.POST.get("target_proxy_id") property_key = request.POST.get("key") session_key = get_key_from_request(request) cached_realizations_key = "{0}_realizations".format(session_key) cached_realizations = get_cached_object(request.session, cached_realizations_key) if not cached_realizations: msg = "unable to locate cached_realizations" raise QError(msg) property = get_property_realization_by_fn( lambda r: r.get_key() == property_key, cached_realizations ) if not property: raise QError("unable to find property w/ key='{0}'".format(property_key)) target_proxy = QModelProxy.objects.get(id=target_proxy_id) new_model_realization = get_new_realizations( project=cached_realizations.project, ontology=cached_realizations.ontology, model_proxy=target_proxy, key=target_proxy.name, ) # double-check that adding this model to this property makes sense... assert target_proxy in property.proxy.relationship_target_models.all() assert property.get_cardinality_max() == '*' or property.relationship_values(manager="allow_unsaved_relationship_values_manager").count() < int(property.get_cardinality_max()) # add the model... property.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(new_model_realization) with allow_unsaved_fk(QModel, ["relationship_property"]): # in theory, Django doesn't store unsaved relationship # the custom manager above gets around this for the m2m relationship (property to model) and it is what I ought to use # however, in order to work my way up the realization hierarchy I need access to the reverse of that relationship # which is a fk relationship; hence this extra bit of code (which only exists so that "model_realizations.py#QRealization.get_parent_model_realization" works) new_model_realization.relationship_property = property # re-cache the changed realizations... request.session[cached_realizations_key] = cached_realizations # and return a serialized version of that model... new_model_realization_serialization = serialize_new_realizations(new_model_realization) return JsonResponse(new_model_realization_serialization)
def create_models_from_components(component_node, model_parameters, models=[], **kwargs): """ recursively look through mppt components to recreate that hierarchy in models :param component_node: :param model_parameters: :param models: :return: None """ title = model_parameters["title"] model_parameters["title"] = title[:title.index(" : ")] + " : " + component_node.name model_parameters["component_key"] = component_node.get_key() model_parameters["is_root"] = kwargs.pop("is_root", False) with allow_unsaved_fk(MetadataModel, ["parent", ]): model = MetadataModel(**model_parameters) models.append(model) for child_component in component_node.get_children(): model_parameters["parent"] = model create_models_from_components(child_component,model_parameters,models)
def get_new_customization_set(project=None, ontology=None, proxy=None, vocabularies=[]): """ """ model_customization = QModelCustomization(ontology=ontology, proxy=proxy, project=project) model_customization.reset(proxy) vocabulary_customizations = [] for i, vocabulary in enumerate(vocabularies): with allow_unsaved_fk(QModelCustomizationVocabulary, ["model_customization"]): vocabulary_customization = QModelCustomizationVocabulary( model_customization=model_customization, vocabulary=vocabulary, order=i + 1, active=True ) vocabulary_customizations.append(vocabulary_customization) standard_category_customizations = [] for standard_category_proxy in ontology.categorization.category_proxies.all(): with allow_unsaved_fk(QStandardCategoryCustomization, ["model_customization"]): standard_category_customization = QStandardCategoryCustomization( model_customization=model_customization, proxy=standard_category_proxy ) standard_category_customization.reset(standard_category_proxy) standard_category_customizations.append(standard_category_customization) standard_property_customizations = [] for standard_property_proxy in proxy.standard_properties.all(): with allow_unsaved_fk( QStandardPropertyCustomization, ["model_customization", "category", "relationship_subform_customization"] ): standard_property_customization = QStandardPropertyCustomization( model_customization=model_customization, proxy=standard_property_proxy, category=find_in_sequence( lambda category: category.proxy.has_property(standard_property_proxy), standard_category_customizations, ), ) standard_property_customization.reset(standard_property_proxy) # HERE BEGINS THE SUBFORM BIT if standard_property_customization.use_subform(): subform_customization_set = get_new_customization_set( project=project, ontology=ontology, proxy=standard_property_proxy.relationship_target_model, vocabularies=[], # NO VOCABULARIES USED IN SUBFORMS ? ) standard_property_customization.relationship_subform_customization = subform_customization_set[ "model_customization" ] # this is important; I do not have access to unsaved m2m fields, but I can set an attribute on the instance standard_property_customization.relationship_subform_customization_set = subform_customization_set # HERE ENDS THE SUBFORM BIT standard_property_customizations.append(standard_property_customization) scientific_category_customizations = [] scientific_property_customizations = [] for vocabulary in vocabularies: vocabulary_key = vocabulary.get_key() for component in vocabulary.component_proxies.all(): component_key = component.get_key() n_categories = len(scientific_category_customizations) for scientific_category_proxy in component.category_proxies.all(): with allow_unsaved_fk(QScientificCategoryCustomization, ["model_customization"]): scientific_category_customization = QScientificCategoryCustomization( model_customization=model_customization, proxy=scientific_category_proxy, vocabulary_key=vocabulary_key, component_key=component_key, ) scientific_category_customization.reset(scientific_category_proxy, reset_keys=False) scientific_category_customizations.append(scientific_category_customization) n_properties = len(scientific_property_customizations) for scientific_property_proxy in component.scientific_property_proxies.all(): with allow_unsaved_fk(QScientificPropertyCustomization, ["category", "model_customization"]): scientific_property_customization = QScientificPropertyCustomization( model_customization=model_customization, proxy=scientific_property_proxy, vocabulary_key=vocabulary_key, component_key=component_key, category=find_in_sequence( lambda category: category.proxy.has_property(scientific_property_proxy), scientific_category_customizations[n_categories - 1 :], ), # ignore the previous categories ) scientific_property_customization.reset(scientific_property_proxy, reset_keys=False) scientific_property_customizations.append(scientific_property_customization) customization_set = { "model_customization": model_customization, "vocabulary_customizations": vocabulary_customizations, "standard_category_customizations": standard_category_customizations, "standard_property_customizations": standard_property_customizations, "scientific_category_customizations": scientific_category_customizations, "scientific_property_customizations": scientific_property_customizations, } return customization_set
def q_realization_add_relationship_value(request): # check the request was valid... valid_request, msg = validate_request(request) if not valid_request: return HttpResponseForbidden(msg) target_proxy_id = request.POST.get("target_proxy_id") property_key = request.POST.get("key") session_key = get_key_from_request(request) cached_realizations_key = "{0}_realizations".format(session_key) cached_realizations = get_cached_object(request.session, cached_realizations_key) if not cached_realizations: msg = "unable to locate cached_realizations" return HttpResponseBadRequest(msg) # do some sanity checks... # check the realization to add to exists... property_realization = get_property_realization_by_key(property_key, cached_realizations) if not property_realization: msg = "unable to find a QPropertyRealization with a key of '{0}'".format(property_key) return HttpResponseBadRequest(msg) # check that the target to add exists... try: target_proxy = QModelProxy.objects.get(id=target_proxy_id) except QModelProxy.DoesNotExist: msg = "unable to find a QModelProxy with an id of '{0}'".format(target_proxy_id) return HttpResponseBadRequest(msg) # check that it makes sense to add this target... if target_proxy not in property_realization.proxy.relationship_target_models.all(): msg = "you are trying to add the wrong type of QModelRealization to this QPropertyRealization" return HttpResponseBadRequest(msg) if (not property_realization.is_infinite) and (property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").count() >= property_realization.cardinality_max): msg = "you have already added the maximum amount of QModelRealizations to this QPropertyRealization" return HttpResponseBadRequest(msg) # check the user has permission to modify the realization... current_user = request.user project = cached_realizations.project if project.authenticated: if not current_user.is_authenticated() or not is_member_of(current_user, project): msg = "{0} does not have permission to modify a realization".format(current_user) return HttpResponseForbidden(msg) # ...okay, sanity checks are over # now create the model... new_model_realization = get_new_realizations( project=project, ontology=target_proxy.ontology, model_proxy=target_proxy, key=target_proxy.name, ) # now add the model... property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(new_model_realization) with allow_unsaved_fk(QModelRealization, ["relationship_property"]): # the custom manager above ("allow_unsaved_relationship_values_manager") lets me cope w/ an unsaved m2m relationship - it is what I ought to use # however, some fns ("QRealization.get_root_realization") needs access to the reverse of that relationship; hence this extra bit of code new_model_realization.relationship_property = property_realization request.session[cached_realizations_key] = cached_realizations # finally return a serialized version of that model... new_model_realization_serialization = serialize_realizations(new_model_realization) return JsonResponse(new_model_realization_serialization)
def get_new_realizations(project=None, ontology=None, model_proxy=None, **kwargs): # unlike w/ customizations, I do not create the entire possible set all at once # instead I just deal w/ the minimum number of properties (based on cardinality) # infinite recursion is therefore avoided; not by re-using previously created models # as with customizations, but by only creating a finite amount of models # hooray! parent_property = kwargs.pop("parent_property", None) if parent_property is not None: is_active = parent_property.is_required else: is_active = True model_realization = QModelRealization( project=project, proxy=model_proxy, version="0.0.0", is_active=is_active ) model_realization.reset() category_realizations = [] # TODO: IS THERE A MORE EFFICIENT WAY TO DO THIS? # gets _all_ of the categories that are relevant to this model... used_category_proxies = [p.category_proxy for p in model_proxy.property_proxies.all()] category_proxies = set(model_proxy.category_proxies.all()) category_proxies.update(used_category_proxies) # for category_proxy in model_proxy.category_proxies.all(): for category_proxy_order, category_proxy in enumerate(category_proxies): with allow_unsaved_fk(QCategoryRealization, ["model"]): category_realization = QCategoryRealization( proxy=category_proxy, model=model_realization, order=category_proxy_order, ) category_realization.reset() category_realizations.append(category_realization) model_realization.categories(manager="allow_unsaved_categories_manager").add_potentially_unsaved(*category_realizations) property_realizations = [] for property_proxy_order, property_proxy in enumerate(model_proxy.property_proxies.all()): property_category_realization = find_in_sequence( lambda c: c.proxy == property_proxy.category_proxy, category_realizations ) with allow_unsaved_fk(QPropertyRealization, ["model", "category"]): property_realization = QPropertyRealization( proxy=property_proxy, field_type=property_proxy.field_type, # TODO: I AM HAVING TO PASS "field_type" SO THAT IT'S SET IN "__init__" IN ORDER TO SETUP ANY ENUMERATIONS; model=model_realization, # TODO: AN ALTERNATIVE WOULD BE TO CALL "reset" FROM "__init__" WHENEVER "is_new" IS True. category=property_category_realization, order=property_proxy_order, ) property_realization.reset() property_category_realization.properties(manager="allow_unsaved_category_properties_manager").add_potentially_unsaved(property_realization) # here begins the icky bit if property_realization.field_type == QPropertyTypes.RELATIONSHIP and property_realization.is_hierarchical: # property_realization.is_required: target_relationship_values = [] # TODO: IF I WERE TO PRE-CREATE ALL RELATIONSHIPS THEN HERE IS WHERE I WOULD DO IT # TODO: BUT THAT WOULD BE MIND-BOGGLINGLY COMPLEX... # TODO: ...B/C I WOULD NEED TO KNOW IN ADVANCE WHAT TYPES OF RELATIONSHIPS TO CREATE IN THE CASE OF MULTIPLE TYPES OF TARGETS; # TODO: AS IT IS, I GET AROUND THIS BY ONLY PRE-CREATING SPECIALIZATIONS WHICH ARE EXPLICIT IN THEIR TARGET PROXIES # TODO: BUT I STILL CANNOT HANDLE THIS FOR NON-SPECIALIZED PROXIES if property_realization.has_specialized_values: # assert property_realization.cardinality_min == len(property_proxy.values) for target_model_proxy_id in property_proxy.values: target_model_proxy = property_proxy.relationship_target_models.get(cim_id=target_model_proxy_id) kwargs.update({"parent_property": property_realization}) with allow_unsaved_fk(QModelRealization, ["relationship_property"]): # this lets me access the parent property of a model new_model_realization = get_new_realizations( project=project, ontology=target_model_proxy.ontology, model_proxy=target_model_proxy, **kwargs ) new_model_realization.relationship_property = property_realization target_relationship_values.append(new_model_realization) property_realization.relationship_values(manager="allow_unsaved_relationship_values_manager").add_potentially_unsaved(*target_relationship_values) # here ends the icky bit property_realizations.append(property_realization) model_realization.properties(manager="allow_unsaved_properties_manager").add_potentially_unsaved(*property_realizations) return model_realization
def get_new_customizations(project=None, ontology=None, model_proxy=None, **kwargs): key = kwargs.pop("key") customizations = kwargs.pop("customizations", {}) # TODO: CHANGE THIS TO USE GUIDS INSTEAD OF NAMES FOR KEYS # TODO: TRY TO REWRITE THIS TO USE "prefix" AGAIN (INSTEAD OF EXPLICIT "key") model_proxy_key = key if model_proxy_key not in customizations: model_customization = QModelCustomization( project=project, ontology=ontology, proxy=model_proxy, ) model_customization.reset() customizations[model_proxy_key] = model_customization else: model_customization = customizations[model_proxy_key] category_customizations = [] for catgegory_proxy in ontology.categorization.category_proxies.all(): category_proxy_key = "{0}.{1}".format(model_proxy_key, catgegory_proxy.name) with allow_unsaved_fk(QCategoryCustomization, ["model_customization"]): if category_proxy_key not in customizations: category_customization = QCategoryCustomization( proxy=catgegory_proxy, model_customization=model_customization, ) category_customization.reset() customizations[category_proxy_key] = category_customization else: category_customization = customizations[category_proxy_key] category_customizations.append(category_customization) # assert category_customizations[-1].proxy == ontology.categorization.get_uncategorized_category_proxy() model_customization.category_customizations(manager="allow_unsaved_category_customizations_manager").add_potentially_unsaved(*category_customizations) property_customizations = [] for property_proxy in model_proxy.property_proxies.all(): property_proxy_key = "{0}.{1}".format(model_proxy_key, property_proxy.name) with allow_unsaved_fk(QPropertyCustomization, ["model_customization", "category"]): # close this context manager before using the custom related manager # (too much hackery at once) if property_proxy_key not in customizations: category_customization = find_in_sequence( lambda c: c.proxy.has_property(property_proxy), category_customizations ) property_customization = QPropertyCustomization( proxy=property_proxy, model_customization=model_customization, category=category_customization, ) property_customization.reset() category_customization.property_customizations(manager="allow_unsaved_categories_manager").add_potentially_unsaved(property_customization) customizations[property_proxy_key] = property_customization else: property_customization = customizations[property_proxy_key] property_customizations.append(property_customization) ############################ # here begins the icky bit # ############################ if property_customization.use_subforms(): subform_key = "{0}.{1}".format(model_proxy.name, property_proxy.name) # this property in this model (only 1 level deep) target_model_customizations = [] for target_model_proxy in property_proxy.relationship_target_models.all(): target_model_proxy_key = "{0}.{1}".format(subform_key, target_model_proxy.name) if target_model_proxy_key not in customizations: target_model_customization = get_new_customizations( project=project, ontology=ontology, model_proxy=target_model_proxy, key=target_model_proxy_key, customizations=customizations, ) else: target_model_customization = customizations[target_model_proxy_key] target_model_customizations.append(target_model_customization) property_customization.relationship_target_model_customizations(manager="allow_unsaved_relationship_target_model_customizations_manager").add_potentially_unsaved(*target_model_customizations) ########################## # here ends the icky bit # ########################## model_customization.property_customizations(manager="allow_unsaved_property_customizations_manager").add_potentially_unsaved(*property_customizations) return customizations[model_proxy_key]
def get_new_realization_set(project=None, ontology=None, model_proxy=None, standard_property_proxies=[], scientific_property_proxies=[], model_customizer=None, vocabularies=[]): models = [] model_parameters = { "project" : project, 'version' : ontology, "proxy" : model_proxy, } if model_customizer.model_show_hierarchy or len(vocabularies) == 0: # setup the root model... model = MetadataModel(**model_parameters) model.vocabulary_key = DEFAULT_VOCABULARY_KEY model.component_key = DEFAULT_COMPONENT_KEY model.title = model_customizer.model_root_component model.is_root = True models.append(model) for vocabulary in vocabularies: if model_customizer.model_show_hierarchy: model_parameters["parent"] = model else: model_parameters.pop("parent", None) model_parameters["vocabulary_key"] = vocabulary.get_key() components = vocabulary.component_proxies.all() if components: # recursively go through the components of each vocabulary, # adding corresponding models to the list root_component = components[0].get_root() model_parameters["title"] = u"%s : %s" % (vocabulary.name, root_component.name) create_models_from_components( root_component, model_parameters, models, # is_root will be False in all instances except the 1st time this is called # for a component w/ no hierarchy is_root=not model_customizer.model_show_hierarchy, ) standard_properties = {} scientific_properties = {} for i, model in enumerate(models): model.reset() property_key = model.get_model_key() # since this is _not_ being created in the context of a subform, # each model in models corresponds to a separate component and will therefore have a unique key standard_properties[property_key] = [] for standard_property_proxy in standard_property_proxies: with allow_unsaved_fk(MetadataStandardProperty, ["model", ]): standard_property = MetadataStandardProperty(proxy=standard_property_proxy,model=model) standard_property.reset() standard_properties[property_key].append(standard_property) scientific_properties[property_key] = [] try: for scientific_property_proxy in scientific_property_proxies[property_key]: with allow_unsaved_fk(MetadataScientificProperty, ["model", ]): scientific_property = MetadataScientificProperty(proxy=scientific_property_proxy,model=model) scientific_property.reset() scientific_properties[property_key].append(scientific_property) except KeyError: # there were no scientific properties associated w/ this component (or, rather, no components associated w/ this vocabulary) # that's okay, scientific_properties[property_key] = [] realization_set = { "models": models, "standard_properties": standard_properties, "scientific_properties": scientific_properties, } return realization_set
def get_new_subrealization_set(project, version, model_proxy, standard_property_proxies, scientific_property_proxies, model_customizer, vocabularies, parent_vocabulary_key, parent_component_key): """creates the full set of realizations required for a particular project/version/proxy combination w/ a specified list of vocabs""" model_parameters = { "project": project, "version": version, "proxy": model_proxy, } # setup the root model... model = MetadataModel(**model_parameters) model.vocabulary_key = parent_vocabulary_key model.component_key = parent_component_key model.is_root = True if model_customizer.model_show_hierarchy: # TODO: DON'T LIKE DOING THIS HERE model.title = model_customizer.model_root_component # it has to go in a list in-case # is part of a hierarchy # (the formsets assume a hierarchy; if not, it will just be a formset w/ 1 form) models = [] models.append(model) for vocabulary in vocabularies: model_parameters["vocabulary_key"] = vocabulary.get_key() components = vocabulary.component_proxies.all() if components: # recursively go through the components of each vocabulary # adding corresponding models to the list root_component = components[0].get_root() model_parameters["parent"] = model model_parameters["title"] = u"%s : %s" % (vocabulary.name, root_component.name) create_models_from_components(root_component, model_parameters, models) standard_properties = {} scientific_properties = {} for i, model in enumerate(models): model.reset() property_key = model.get_model_key() # since this _is_ being created in the context of a subform, # then all models will correspond to the same component (ie: the component of the "parent" model of the property w/ subforms) # so I add a counter to make it unique (and using the format "-i" keeps it consistent w/ how forms & formsets work in Django) property_key += "-%s" % (i) standard_properties[property_key] = [] for standard_property_proxy in standard_property_proxies: with allow_unsaved_fk(MetadataStandardProperty, ["model", ]): standard_property = MetadataStandardProperty(proxy=standard_property_proxy,model=model) standard_property.reset() standard_properties[property_key].append(standard_property) scientific_properties[property_key] = [] try: for scientific_property_proxy in scientific_property_proxies[property_key]: with allow_unsaved_fk(MetadataScientificProperty, ["model", ]): scientific_property = MetadataScientificProperty(proxy=scientific_property_proxy,model=model) scientific_property.reset() scientific_properties[property_key].append(scientific_property) except KeyError: # there were no scientific properties associated w/ this component (or, rather, no components associated w/ this vocabulary) # that's okay, scientific_properties[property_key] = [] realization_set = { "models": models, "standard_properties": standard_properties, "scientific_properties": scientific_properties, } return realization_set