Coverage for apis_core/apis_entities/views.py: 55%
31 statements
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-20 09:24 +0000
« prev ^ index » next coverage.py v7.6.8, created at 2024-12-20 09:24 +0000
1from dal import autocomplete
2from django.contrib import messages
3from django.contrib.auth.mixins import PermissionRequiredMixin
4from django.contrib.contenttypes.models import ContentType
5from django.db.models import Q
6from django.shortcuts import get_object_or_404, redirect
7from django.utils.html import format_html
8from django.views import View
10from apis_core.apis_metainfo.models import RootObject
11from apis_core.generic.helpers import generate_search_filter
12from apis_core.generic.views import GenericModelMixin
15class EntitiesDuplicate(GenericModelMixin, PermissionRequiredMixin, View):
16 permission_action_required = "create"
18 def get(self, request, *args, **kwargs):
19 source_obj = get_object_or_404(self.model, pk=kwargs["pk"])
20 newobj = source_obj.duplicate()
22 messages.success(
23 request,
24 format_html(
25 "<a href={}>{}</a> was successfully duplicated to the current object:",
26 source_obj.get_absolute_url(),
27 source_obj,
28 ),
29 )
30 return redirect(newobj.get_edit_url())
33class EntitiesAutocomplete(autocomplete.Select2QuerySetView):
34 """
35 This endpoint allows us to use autocomplete over multiple model classes.
36 It takes a parameter `entities` which is a list of ContentType natural
37 keys and searches for the query in all instances of those entities
38 (using `generate_search_filter`, which means it uses a different search
39 approach for every model).
40 The return values of the endpoint are then prefixed with the id of the
41 contenttype of the results, separated by an underscore.
43 Example:
44 Using this endpoint with the parameters:
46 ?entities=apis_ontology.person&entities=apis_ontology.place&q=ammer
48 gives you all the persons and places that have `ammer` in their names
49 and labels.
50 """
52 def get_result_value(self, result) -> str:
53 content_type = ContentType.objects.get_for_model(result)
54 return f"{content_type.id}_" + super().get_result_value(result)
56 def get_queryset(self):
57 q = Q()
58 if entities := self.request.GET.getlist("entities"):
59 for entity in entities:
60 app_label, model = entity.split(".")
61 content_type = get_object_or_404(
62 ContentType, app_label=app_label, model=model
63 )
64 name = (
65 RootObject.objects_inheritance.get_queryset()._get_ancestors_path(
66 content_type.model_class()
67 )
68 )
69 q |= Q(**{f"{name}__isnull": False}) & generate_search_filter(
70 content_type.model_class(), self.q, prefix=f"{name}__"
71 )
72 return RootObject.objects_inheritance.select_subclasses().filter(q)