def search(self): from haystack.query import EmptySearchQuerySet from openPLM.plmapp.search import SmartSearchQuerySet if self.is_valid(): type_ = self.cleaned_data["type"] query = self.cleaned_data["q"].strip() if type_ != "all": cls = m.get_all_users_and_plmobjects()[type_] d = {} m.get_all_subclasses(cls, d) mods = d.values() if issubclass(cls, m.Document) and query not in ("", "*"): # include documentfiles if we search for a document and # if the query does not retrieve all documents mods.append(m.DocumentFile) sqs = SmartSearchQuerySet().models(*mods) else: sqs = SmartSearchQuerySet() if self.cleaned_data["search_official"]: sqs = sqs.filter(state_class="official") if not query or query == "*": return sqs.exclude(state_class="cancelled") results = sqs.highlight().auto_query(query) return results else: return EmptySearchQuerySet()
def ajax_autocomplete(request, obj_type, field): """ Simple ajax view for JQquery.UI.autocomplete. This returns the possible completions (in JSON format) for *field*. The request must contains a get parameter named *term* which should be the string used to filter the results. *obj_type* must be a valid typename. :param str obj_type: a valid typename (like ``"part"``) :param str field: a valid field (like ``"name"``) """ if not request.GET.get('term'): return HttpResponse(content_type='text/plain') term = request.GET.get('term') limit = 50 try: cls = models.get_all_users_and_plmobjects()[obj_type] except KeyError: return HttpResponseForbidden() if hasattr(cls, "attributes"): if field not in cls(__fake__=True).attributes: return HttpResponseForbidden() elif cls == models.User: if field not in ("email", "first_name", "last_name"): return HttpResponseForbidden() if getattr(settings, "HIDE_EMAILS", False) and field == "email": return HttpResponseForbidden() if field not in cls._meta.get_all_field_names(): return HttpResponseForbidden() results = cls.objects.filter(**{"%s__icontains" % field: term}) results = results.values_list(field, flat=True).order_by(field).distinct() json = JSONEncoder().encode(list(str(r) for r in results[:limit])) return HttpResponse(json, content_type='application/json')
def ajax_creation_form(request): """ Simple view which returns the html of a creation form with the data of :attr:`request.GET` as initial values. The request must contains a get parameter *type* with a valid type, otherwise, a :class:`.HttpResponseForbidden` is returned. """ tf = forms.TypeForm(request.GET) if tf.is_valid(): type_ = tf.cleaned_data["type"] request.session["type"] = type_ request.session.save() cls = models.get_all_users_and_plmobjects()[type_] view = get_creation_view(cls) if view is not None: return {"reload" : True} initial = dict(request.GET.iteritems()) if "pfiles" in request.GET: initial["pfiles"] = request.GET.getlist("pfiles") if "reference" in initial: # gets a new reference if the type switches from a part to a document # and vice versa, see ticket #99 ref = initial["reference"] if (ref.startswith("DOC_") and type_ in models.get_all_parts()) or \ (ref.startswith("PART_") and type_ in models.get_all_documents()): del initial["reference"] form = forms.get_creation_form(request.user, cls, initial=initial) return {"reload" : False, "form" : form.as_table(), "type" : type_, "form_media": form.media.render(), } else: return HttpResponseForbidden()
def ajax_autocomplete(request, obj_type, field): """ Simple ajax view for JQquery.UI.autocomplete. This returns the possible completions (in JSON format) for *field*. The request must contains a get parameter named *term* which should be the string used to filter the results. *obj_type* must be a valid typename. :param str obj_type: a valid typename (like ``"part"``) :param str field: a valid field (like ``"name"``) """ if not request.GET.get('term'): return HttpResponse(mimetype='text/plain') term = request.GET.get('term') limit = 50 try: cls = models.get_all_users_and_plmobjects()[obj_type] except KeyError: return HttpResponseForbidden() if hasattr(cls, "attributes"): if field not in cls(__fake__=True).attributes: return HttpResponseForbidden() elif cls == models.User: if field not in ("email", "first_name", "last_name"): return HttpResponseForbidden() if field not in cls._meta.get_all_field_names(): return HttpResponseForbidden() results = cls.objects.filter(**{"%s__icontains" % field : term}) results = results.values_list(field, flat=True).order_by(field).distinct() json = JSONEncoder().encode(list(str(r) for r in results[:limit])) return HttpResponse(json, mimetype='application/json')
def ajax_search_form(request): """ Simple view which returns the html of a search form with the data of :attr:`request.GET` as initial values. The request must contains a get parameter *type* with a valid type, otherwise, a :class:`.HttpResponseForbidden` is returned. """ tf = forms.TypeForm(request.GET) if tf.is_valid(): cls = models.get_all_users_and_plmobjects()[tf.cleaned_data["type"]] form = forms.get_search_form(cls, request.GET) return HttpResponse(form.as_table()) else: return HttpResponseForbidden()
def search(self): from haystack.query import EmptySearchQuerySet from openPLM.plmapp.search import SmartSearchQuerySet if self.is_valid(): cls = m.get_all_users_and_plmobjects()[self.cleaned_data["type"]] d = {} m._get_all_subclasses(cls, d) mods = d.values() query = self.cleaned_data["q"].strip() if issubclass(cls, m.Document) and query.strip() not in ("", "*"): # include documentfiles if we search for a document and # if the query does not retrieve all documents mods.append(m.DocumentFile) sqs = SmartSearchQuerySet().highlight().models(*mods) if not query or query == "*": return sqs results = sqs.auto_query(query) return results else: return EmptySearchQuerySet()
def create_object(request, from_registered_view=False, creation_form=None): """ View to create a :class:`.PLMObject` or a :class:`.GroupInfo`. :url: ``/object/create/`` Requests (POST and GET) must contain a ``type`` variable that validates a :class:`.TypeForm`. POST requests must validate the creation form, fields depend on the given type. If the creation form is valid, an object is created and in case of success, this view redirects to the created object. Requests may contain a ``__next__`` variable. A successful creation will redirect to this URL. Some special strings are replaced: * ``##type##`` with the created object's type * ``##ref##`` with the created object's reference * ``##rev##`` with the created object's reference Requests may also contain other special variables (at most one of them): ``related_doc`` Id of a document. The created part will be attached to this document. Object's type is restricted to part types. Two context variables (``related_doc`` and ``related``) are set to the document controller. ``related_part`` Id of a part. The created document will be attached to this part. Object's type is restricted to document types. Two context variables (``related_part`` and ``related``) are set to the part controller. ``related_parent`` Id of a part. Object's type is restricted to part types. Two context variables (``related_parent`` and ``related``) are set to the part controller. .. note:: If *from_registered_view* is False, this view delegates its treatment to a registered view that handles creation of objects of the given type. (see :func:`.get_creation_view` and :func:`.register_creation_view`) :param from_registered_view: True if this function is called by another creation view :param creation_form: a creation form that will be used instead of the default one **Template:** :file:`create.html` **Context:** ``RequestContext`` ``creation_form`` ``creation_type_form`` :class:`.TypeForm` to select the type of the created object ``object_type`` type of the created object ``next`` value of the ``__next__`` request variable if given """ obj, ctx = get_generic_data(request) Form = forms.TypeForm # it is possible that the created object must be attached to a part # or a document # related_doc and related_part should be a plmobject id # If the related_doc/part is not a doc/part, we let python raise # an AttributeError, since a user should not play with the URL # and openPLM must be smart enough to produce valid URLs attach = related = None if "related_doc" in request.REQUEST: Form = forms.PartTypeForm doc = get_obj_by_id(int(request.REQUEST["related_doc"]), request.user) attach = doc.attach_to_part ctx["related_doc"] = request.REQUEST["related_doc"] related = ctx["related"] = doc elif "related_part" in request.REQUEST: Form = forms.DocumentTypeForm part = get_obj_by_id(int(request.REQUEST["related_part"]), request.user) attach = part.attach_to_document ctx["related_part"] = request.REQUEST["related_part"] related = ctx["related"] = part elif "related_parent" in request.REQUEST: Form = forms.PartTypeForm parent = get_obj_by_id(int(request.REQUEST["related_parent"]), request.user) ctx["related_parent"] = request.REQUEST["related_parent"] related = ctx["related"] = parent if "pfiles" in request.REQUEST: Form = forms.Document2TypeForm if "__next__" in request.REQUEST: redirect_to = request.REQUEST["__next__"] ctx["next"] = redirect_to else: # will redirect to the created object redirect_to = None type_form = Form(request.REQUEST) if type_form.is_valid(): type_ = type_form.cleaned_data["type"] cls = models.get_all_users_and_plmobjects()[type_] if not from_registered_view: view = get_creation_view(cls) if view is not None: # view has been registered to create an object of type 'cls' return view(request) else: ctx["creation_type_form"] = type_form return r2r('create.html', ctx, request) if request.method == 'GET' and creation_form is None: creation_form = forms.get_creation_form(request.user, cls, template="pfiles" not in request.GET) if related is not None: creation_form.fields["group"].initial = related.group creation_form.initial["lifecycle"] = related.lifecycle if "pfiles" in request.GET: pfiles = request.GET.getlist("pfiles") creation_form.initial["pfiles"] = pfiles try: name = filename_to_name( obj.files.get(id=int(pfiles[0])).filename) creation_form.initial["name"] = name except Exception: pass elif request.method == 'POST': if creation_form is None: creation_form = forms.get_creation_form(request.user, cls, request.POST) if creation_form.is_valid(): ctrl_cls = get_controller(type_) ctrl = ctrl_cls.create_from_form(creation_form, request.user) message = _(u"The %(Object_type)s has been created") % dict( Object_type=type_) messages.info(request, message) if attach is not None: try: attach(ctrl) message = _(u"The %(Object_type)s has been attached" ) % dict(Object_type=type_) messages.info(request, message) except (ControllerError, ValueError) as e: # crtl cannot be attached (maybe the state of the # related object as changed) # alerting the user using the messages framework since # the response is redirected message = _(u"Error: %(details)s") % dict( details=unicode(e)) messages.error(request, message) # redirecting to the ctrl page that lists its attached # objects if ctrl.is_document: return HttpResponseRedirect(ctrl.plmobject_url + "parts/") else: return HttpResponseRedirect(ctrl.plmobject_url + "doc-cad/") if redirect_to: redirect_to = redirect_to.replace("##ref##", ctrl.reference) redirect_to = redirect_to.replace("##rev##", ctrl.revision) redirect_to = redirect_to.replace("##type##", ctrl.type) return HttpResponseRedirect(redirect_to or ctrl.plmobject_url) ctx.update({ 'creation_form': creation_form, 'object_type': type_, 'creation_type_form': type_form, }) return r2r('create.html', ctx, request)
def clone(request, obj_type, obj_ref, obj_revi,creation_form=None): """ Manage html page to display the cloning form of the selected object (part or document) or clone it. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/clone/` .. include:: views_params.txt **Template:** :file:`clone.html` :param creation_form: the creation form that will be used to clone the object If the object is a part : :post params: a valid :class:`.SelectDocumentFormset` Only required if *is_linked* is True, see below. a valid :class:`.SelectChildFormset` Only required if *is_linked* is True, see below. A cloned part may be attached to some documents. These documents are given by :meth:`.PartController.get_suggested_documents`. A cloned part may also have some children from the original revision. If the object is a document : :post params: a valid :class:`.SelectPartFormset` Only required if *is_linked* is True, see below. A cloned document may be attached to some parts, given by :meth:`.DocumentController.get_suggested_parts`. **Context:** ``RequestContext`` ``is_linked`` True if the object is linked (attached) to other object , at least one. ``creation_form`` form to clone the object. Fields in this form are set according to the current object. ``doc_formset`` a :class:`.SelectDocmentFormset` of documents that the new object, if it is a part, may be attached to. Only set if *is_linked* is True. ``children_formset`` a :class:`.SelectChildFormset` of parts that the new object, if it is a part, may be linked with. Only set if *is_linked* is True. ``parts_formset`` a :class:`.SelectPartFormset` of parts that the new object, if it is a document, may be attached to. Only set if *is_linked* is True. """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) obj.check_clone() cls = models.get_all_users_and_plmobjects()[obj_type] is_linked = True if issubclass(cls, models.Part): children = [c.link for c in obj.get_children(1)] documents = obj.get_suggested_documents() is_linked = ctx['is_linked'] = bool(children or documents) else: parts = obj.get_suggested_parts() is_linked = ctx['is_linked'] = bool(parts) formsets ={} if request.method == 'GET': # generate and fill the creation form not_auto_cloned_fields = ['reference','revision', 'group','lifecycle', 'auto', 'pfiles', 'template'] creation_form = forms.get_creation_form(request.user, cls, template=False) if bool(request.user.groups.filter(id=obj.group.id)): creation_form.fields["group"].initial = obj.group.id if not obj.is_cancelled: creation_form.initial["lifecycle"] = obj.lifecycle for f in creation_form.fields: if f not in not_auto_cloned_fields: creation_form.fields[f].initial = getattr(obj, f) # generate the links form if issubclass(cls, models.Part) and is_linked: initial = [dict(link=link) for link in children] formsets["children_formset"] = forms.SelectChildFormset(prefix="children", initial=initial) initial = [dict(document=d) for d in documents] formsets["doc_formset"] = forms.SelectDocumentFormset(prefix="documents", initial=initial) else: if issubclass(cls, models.Document) and is_linked : formsets["part_formset"] = forms.SelectPartFormset(queryset=parts) elif request.method == 'POST': if issubclass(cls, models.Part) and is_linked: formsets.update({ "children_formset":forms.SelectChildFormset(request.POST, prefix="children"), "doc_formset": forms.SelectDocumentFormset(request.POST, prefix="documents"), }) elif is_linked: formsets["part_formset"]=forms.SelectPartFormset(request.POST) if creation_form is None: creation_form = forms.get_creation_form(request.user, cls, request.POST) if creation_form.is_valid(): if is_linked : valid_forms = False if issubclass(cls, models.Part): valid_forms, selected_children, selected_documents = clone_part(request.user, request.POST, children, documents) if valid_forms : new_ctrl = obj.clone(creation_form, request.user, selected_children, selected_documents) return HttpResponseRedirect(new_ctrl.plmobject_url) else : formsets.update({ "children_formset":forms.SelectChildFormset(request.POST, prefix="children"), "doc_formset": forms.SelectDocumentFormset(request.POST, prefix="document"), }) elif issubclass(cls, models.Document) and is_linked: valid_forms, selected_parts = clone_document(request.user, request.POST, parts) if valid_forms: new_ctrl = obj.clone(creation_form, request.user, selected_parts) return HttpResponseRedirect(new_ctrl.plmobject_url) else : formsets["part_formset"]=forms.SelectPartFormset(request.POST) else: if issubclass(cls, models.Part): new_ctrl = obj.clone(creation_form, request.user, [], []) else: new_ctrl = obj.clone(creation_form, request.user, []) return HttpResponseRedirect(new_ctrl.plmobject_url) ctx['creation_form'] = creation_form ctx.update(formsets) return r2r('clone.html', ctx, request)
def create_object(request, from_registered_view=False, creation_form=None): """ View to create a :class:`.PLMObject` or a :class:`.GroupInfo`. :url: ``/object/create/`` Requests (POST and GET) must contain a ``type`` variable that validates a :class:`.TypeForm`. POST requests must validate the creation form, fields depend on the given type. If the creation form is valid, an object is created and in case of success, this view redirects to the created object. Requests may contain a ``__next__`` variable. A successful creation will redirect to this URL. Some special strings are replaced: * ``##type##`` with the created object's type * ``##ref##`` with the created object's reference * ``##rev##`` with the created object's reference Requests may also contain other special variables (at most one of them): ``related_doc`` Id of a document. The created part will be attached to this document. Object's type is restricted to part types. Two context variables (``related_doc`` and ``related``) are set to the document controller. ``related_part`` Id of a part. The created document will be attached to this part. Object's type is restricted to document types. Two context variables (``related_part`` and ``related``) are set to the part controller. ``related_parent`` Id of a part. Object's type is restricted to part types. Two context variables (``related_parent`` and ``related``) are set to the part controller. .. note:: If *from_registered_view* is False, this view delegates its treatment to a registered view that handles creation of objects of the given type. (see :func:`.get_creation_view` and :func:`.register_creation_view`) :param from_registered_view: True if this function is called by another creation view :param creation_form: a creation form that will be used instead of the default one **Template:** :file:`create.html` **Context:** ``RequestContext`` ``creation_form`` ``creation_type_form`` :class:`.TypeForm` to select the type of the created object ``object_type`` type of the created object ``next`` value of the ``__next__`` request variable if given """ obj, ctx = get_generic_data(request) Form = forms.TypeForm # it is possible that the created object must be attached to a part # or a document # related_doc and related_part should be a plmobject id # If the related_doc/part is not a doc/part, we let python raise # an AttributeError, since a user should not play with the URL # and openPLM must be smart enough to produce valid URLs attach = related = None if "related_doc" in request.REQUEST: Form = forms.PartTypeForm doc = get_obj_by_id(int(request.REQUEST["related_doc"]), request.user) attach = doc.attach_to_part ctx["related_doc"] = request.REQUEST["related_doc"] related = ctx["related"] = doc elif "related_part" in request.REQUEST: Form = forms.DocumentTypeForm part = get_obj_by_id(int(request.REQUEST["related_part"]), request.user) attach = part.attach_to_document ctx["related_part"] = request.REQUEST["related_part"] related = ctx["related"] = part elif "related_parent" in request.REQUEST: Form = forms.PartTypeForm parent = get_obj_by_id(int(request.REQUEST["related_parent"]), request.user) ctx["related_parent"] = request.REQUEST["related_parent"] related = ctx["related"] = parent if "pfiles" in request.REQUEST: Form = forms.Document2TypeForm if "__next__" in request.REQUEST: redirect_to = request.REQUEST["__next__"] ctx["next"] = redirect_to else: # will redirect to the created object redirect_to = None type_form = Form(request.REQUEST) if type_form.is_valid(): type_ = type_form.cleaned_data["type"] cls = models.get_all_users_and_plmobjects()[type_] if not from_registered_view: view = get_creation_view(cls) if view is not None: # view has been registered to create an object of type 'cls' return view(request) else: ctx["creation_type_form"] = type_form return r2r('create.html', ctx, request) if request.method == 'GET' and creation_form is None: creation_form = forms.get_creation_form(request.user, cls, template="pfiles" not in request.GET) if related is not None: creation_form.fields["group"].initial = related.group creation_form.initial["lifecycle"] = related.lifecycle if "pfiles" in request.GET: pfiles = request.GET.getlist("pfiles") creation_form.initial["pfiles"] = pfiles try: name = filename_to_name(obj.files.get(id=int(pfiles[0])).filename) creation_form.initial["name"] = name except Exception: pass elif request.method == 'POST': if creation_form is None: creation_form = forms.get_creation_form(request.user, cls, request.POST) if creation_form.is_valid(): ctrl_cls = get_controller(type_) ctrl = ctrl_cls.create_from_form(creation_form, request.user) message = _(u"The %(Object_type)s has been created") % dict(Object_type = type_) messages.info(request, message) if attach is not None: try: attach(ctrl) message = _(u"The %(Object_type)s has been attached") % dict(Object_type = type_) messages.info(request, message) except (ControllerError, ValueError) as e: # crtl cannot be attached (maybe the state of the # related object as changed) # alerting the user using the messages framework since # the response is redirected message = _(u"Error: %(details)s") % dict(details=unicode(e)) messages.error(request, message) # redirecting to the ctrl page that lists its attached # objects if ctrl.is_document: return HttpResponseRedirect(ctrl.plmobject_url + "parts/") else: return HttpResponseRedirect(ctrl.plmobject_url + "doc-cad/") if redirect_to: redirect_to = redirect_to.replace("##ref##", ctrl.reference) redirect_to = redirect_to.replace("##rev##", ctrl.revision) redirect_to = redirect_to.replace("##type##", ctrl.type) return HttpResponseRedirect(redirect_to or ctrl.plmobject_url) ctx.update({ 'creation_form' : creation_form, 'object_type' : type_, 'creation_type_form' : type_form, }) return r2r('create.html', ctx, request)
def clone(request, obj_type, obj_ref, obj_revi,creation_form=None): """ Manage html page to display the cloning form of the selected object (part or document) or clone it. :url: :samp:`/object/{obj_type}/{obj_ref}/{obj_revi}/clone/` .. include:: views_params.txt **Template:** :file:`clone.html` :param creation_form: the creation form that will be used to clone the object If the object is a part : :post params: a valid :class:`.SelectDocumentFormset` Only required if *is_linked* is True, see below. a valid :class:`.SelectChildFormset` Only required if *is_linked* is True, see below. A cloned part may be attached to some documents. These documents are given by :meth:`.PartController.get_suggested_documents`. A cloned part may also have some children from the original revision. If the object is a document : :post params: a valid :class:`.SelectPartFormset` Only required if *is_linked* is True, see below. A cloned document may be attached to some parts, given by :meth:`.DocumentController.get_suggested_parts`. **Context:** ``RequestContext`` ``is_linked`` True if the object is linked (attached) to other object , at least one. ``creation_form`` form to clone the object. Fields in this form are set according to the current object. ``doc_formset`` a :class:`.SelectDocmentFormset` of documents that the new object, if it is a part, may be attached to. Only set if *is_linked* is True. ``children_formset`` a :class:`.SelectChildFormset` of parts that the new object, if it is a part, may be linked with. Only set if *is_linked* is True. ``parts_formset`` a :class:`.SelectPartFormset` of parts that the new object, if it is a document, may be attached to. Only set if *is_linked* is True. """ obj, ctx = get_generic_data(request, obj_type, obj_ref, obj_revi) obj.check_clone() cls = models.get_all_users_and_plmobjects()[obj_type] is_linked = True if issubclass(cls, models.Part): children = [c.link for c in obj.get_children(1)] documents = obj.get_suggested_documents() is_linked = ctx['is_linked'] = bool(children or documents) else: parts = obj.get_suggested_parts() is_linked = ctx['is_linked'] = bool(parts) formsets ={} if request.method == 'GET': # generate and fill the creation form not_auto_cloned_fields = ['reference','revision', 'group','lifecycle', 'auto', 'pfiles'] creation_form = forms.get_creation_form(request.user, cls) if bool(request.user.groups.filter(id=obj.group.id)): creation_form.fields["group"].initial = obj.group.id if not obj.is_cancelled: creation_form.initial["lifecycle"] = obj.lifecycle for f in creation_form.fields: if f not in not_auto_cloned_fields: creation_form.fields[f].initial = getattr(obj, f) # generate the links form if issubclass(cls, models.Part) and is_linked: initial = [dict(link=link) for link in children] formsets["children_formset"] = forms.SelectChildFormset(prefix="children", initial=initial) initial = [dict(document=d) for d in documents] formsets["doc_formset"] = forms.SelectDocumentFormset(prefix="documents", initial=initial) else: if issubclass(cls, models.Document) and is_linked : formsets["part_formset"] = forms.SelectPartFormset(queryset=parts) elif request.method == 'POST': if issubclass(cls, models.Part) and is_linked: formsets.update({ "children_formset":forms.SelectChildFormset(request.POST, prefix="children"), "doc_formset": forms.SelectDocumentFormset(request.POST, prefix="documents"), }) elif is_linked: formsets["part_formset"]=forms.SelectPartFormset(request.POST) if creation_form is None: creation_form = forms.get_creation_form(request.user, cls, request.POST) if creation_form.is_valid(): if is_linked : valid_forms = False if issubclass(cls, models.Part): valid_forms, selected_children, selected_documents = clone_part(request.user, request.POST, children, documents) if valid_forms : new_ctrl = obj.clone(creation_form, request.user, selected_children, selected_documents) return HttpResponseRedirect(new_ctrl.plmobject_url) else : formsets.update({ "children_formset":forms.SelectChildFormset(request.POST, prefix="children"), "doc_formset": forms.SelectDocumentFormset(request.POST, prefix="document"), }) elif issubclass(cls, models.Document) and is_linked: valid_forms, selected_parts = clone_document(request.user, request.POST, parts) if valid_forms: new_ctrl = obj.clone(creation_form, request.user, selected_parts) return HttpResponseRedirect(new_ctrl.plmobject_url) else : formsets["part_formset"]=forms.SelectPartFormset(request.POST) else: if issubclass(cls, models.Part): new_ctrl = obj.clone(creation_form, request.user, [], []) else: new_ctrl = obj.clone(creation_form, request.user, []) return HttpResponseRedirect(new_ctrl.plmobject_url) ctx['creation_form'] = creation_form ctx.update(formsets) return r2r('clone.html', ctx, request)