Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1import logging 

2 

3from django.conf import settings 

4from django.contrib.auth.mixins import LoginRequiredMixin 

5from django.core.exceptions import PermissionDenied 

6from django.core.paginator import EmptyPage, PageNotAnInteger, Paginator 

7from django.db.models import F 

8from django.http import Http404, HttpResponse 

9from django.shortcuts import get_object_or_404, render 

10from django.utils.decorators import method_decorator 

11from django.utils.translation import gettext as _ 

12from django.views.generic import View 

13from django.views.generic.list import ListView 

14from elasticsearch_dsl import Q 

15from guardian.core import ObjectPermissionChecker 

16from wagtail.core.models import Page 

17 

18from discuss_data.core.decorators import dd_tou_accepted 

19from discuss_data.core.documents import DataSetDocument, UserDocument 

20from discuss_data.core.models import KeywordTagged, LanguageTagged 

21from discuss_data.core.helpers import ( 

22 index_search, 

23 split_items_2, 

24 split_items_3, 

25) 

26from discuss_data.dddatasets.models import ( 

27 Category, 

28 CollectionMethodsTagged, 

29 AnalysisMethodsTagged, 

30 DisciplinesTagged, 

31) 

32from discuss_data.ddusers.models import Country, User 

33from discuss_data.pages.models import LandingPage, ManualPage, TextPage 

34 

35 

36logger = logging.getLogger(__name__) 

37 

38SLUG_LANDING = getattr(settings, "WAGTAIL_LANDING_PAGE", None) 

39SLUG_CONTACTS = getattr(settings, "WAGTAIL_CONTACTS_PAGE", None) 

40SLUG_SECURITY = getattr(settings, "WAGTAIL_SECURITY_PAGE", None) 

41 

42 

43class SearchUsersAndDatasetsView(ListView): 

44 paginate_by = 25 

45 template_name = "core/_search_results.html" 

46 

47 def get_queryset(self): 

48 query = self.request.GET.get("q") 

49 countries = self.request.GET.getlist("countries") 

50 categories = self.request.GET.getlist("categories") 

51 

52 queryset = index_search( 

53 "user_index", query, countries=countries, categories=categories 

54 ) 

55 

56 # hide hidden and inactive users 

57 filtered = queryset.exclude(profile_accessibility="HID").exclude( 

58 is_active=False 

59 ) 

60 

61 if self.request.user.is_authenticated: 

62 return filtered 

63 

64 # also hide network users by default (when not logged in) 

65 return filtered.exclude(profile_accessibility="NET") 

66 

67 

68def help_search(request): 

69 return core_search_view(request, "help_index", 10) 

70 

71 

72@method_decorator(dd_tou_accepted, name="dispatch") 

73class ProtectedView(LoginRequiredMixin, View): 

74 """ base class for views that require the user to log in and to accept 

75 the terms of use 

76 """ 

77 

78 login_url = getattr(settings, "LOGIN_URL", None) 

79 redirect_field_name = getattr(settings, "LOGIN_REDIRECT_URL", None) 

80 

81 

82def get_search_params(request, order_by_filter=None, category=None): 

83 search_params = dict() 

84 search_params["q"] = request.GET.get("q") 

85 

86 # extract country slugs from GET 

87 search_params["countries"] = request.GET.getlist("countries") 

88 search_params["countries_all"] = Country.objects.all() 

89 

90 # extract category slugs from GET 

91 categories = request.GET.getlist("categories") 

92 if category: 

93 categories.append(category.name) 

94 search_params["categories"] = categories 

95 search_params["categories_all"] = Category.objects.all() 

96 

97 # extract keyword slugs from GET 

98 search_params["keywords"] = request.GET.getlist("keywords") 

99 search_params["keywords_all"] = KeywordTagged.objects.all() 

100 

101 # extract language slugs from GET 

102 search_params["languages"] = request.GET.getlist("languages") 

103 search_params["languages_all"] = LanguageTagged.objects.all() 

104 

105 # extract disciplines slugs from GET 

106 search_params["disciplines"] = request.GET.getlist("disciplines") 

107 search_params["disciplines_all"] = DisciplinesTagged.objects.all() 

108 

109 # extract methods_of_data_collection slugs from GET 

110 search_params["methods_of_data_collection"] = request.GET.getlist( 

111 "methods_of_data_collection" 

112 ) 

113 search_params[ 

114 "methods_of_data_collection_all" 

115 ] = CollectionMethodsTagged.objects.all() 

116 

117 # extract methods_of_data_analysis slugs from GET 

118 search_params["methods_of_data_analysis"] = request.GET.getlist( 

119 "methods_of_data_analysis" 

120 ) 

121 search_params["methods_of_data_analysis_all"] = AnalysisMethodsTagged.objects.all() 

122 try: 

123 search_params["orderby"] = [order_by_filter] 

124 except UnboundLocalError: 

125 pass 

126 return search_params 

127 

128 

129def core_search_view(request, search_index, objects_on_page, category=None): 

130 # search result ordering 

131 order_by_filter = request.GET.get("orderby") 

132 if order_by_filter == "alpha": 

133 order_by = "title" 

134 else: 

135 order_by = "-publication_date" 

136 

137 search_params = get_search_params(request, order_by_filter, category) 

138 if search_index == "dataset_index": 

139 template = "dddatasets/search_results.html" 

140 queryset = index_search( 

141 "dataset_index", 

142 search_params["q"], 

143 countries=search_params["countries"], 

144 categories=search_params["categories"], 

145 keywords=search_params["keywords"], 

146 languages=search_params["languages"], 

147 methods_of_data_analysis=search_params["methods_of_data_analysis"], 

148 methods_of_data_collection=search_params["methods_of_data_collection"], 

149 disciplines=search_params["disciplines"], 

150 ) 

151 # only the dataset with the highest published version per dsmo will be listed in search results 

152 # generate SQL join using Django F() expressions 

153 # https://docs.djangoproject.com/en/3.0/topics/db/queries/#filters-can-reference-fields-on-the-model 

154 queryset = queryset.filter( 

155 dataset_management_object__main_published_ds_id=F("id") 

156 ).order_by(order_by) 

157 

158 elif search_index == "user_index": 

159 template = "ddusers/_search_results.html" 

160 queryset = ( 

161 index_search( 

162 "user_index", 

163 search_params["q"], 

164 countries=search_params["countries"], 

165 keywords=search_params["keywords"], 

166 ) 

167 .exclude(profile_accessibility="HID") # exclude hidden users from search 

168 .order_by("last_name") 

169 ) 

170 

171 elif search_index == "help_index": 

172 template = "pages/index_page_search.html" 

173 queryset = Page.objects.live().search(search_params["q"]) 

174 else: 

175 logger.debug("no search index given") 

176 

177 pagination = False 

178 paginator_range = None 

179 paginator_last_page = None 

180 # deactivate paging by setting objects_on_page to an unrealistic high value 

181 objects_on_page = 1000 

182 

183 # remove existing GET page key from querydict 

184 get_params_without_page = request.GET.copy() 

185 if get_params_without_page.get("page"): 

186 del get_params_without_page["page"] 

187 

188 # if more then 24 users activate pagination 

189 if queryset.count() > objects_on_page: 

190 

191 paginator = Paginator(queryset, objects_on_page) # Show 25 contacts per page 

192 pagination = True 

193 page = request.GET.get("page") 

194 paginator_range = range(1, paginator.num_pages + 1) 

195 paginator_last_page = paginator.num_pages + 1 

196 try: 

197 objects = paginator.page(page) 

198 except PageNotAnInteger: 

199 # If page is not an integer, deliver first page. 

200 objects = paginator.page(1) 

201 except EmptyPage: 

202 # If page is out of range (e.g. 9999), deliver last page of results. 

203 objects = paginator.page(paginator.num_pages) 

204 else: 

205 objects = queryset 

206 

207 return render( 

208 request, 

209 template, 

210 { 

211 "object_list": objects, 

212 "pagination": pagination, 

213 "paginator_range": paginator_range, 

214 "paginator_last_page": paginator_last_page, 

215 "search_params": search_params, 

216 "query": search_params["q"], 

217 "get_params": get_params_without_page, 

218 "category": category, 

219 }, 

220 ) 

221 

222 

223def landing_page(request): 

224 """ 

225 Dashboard User Page 

226 """ 

227 page = get_object_or_404(LandingPage, slug="discuss-data-landingpage") 

228 news_items = split_items_2(page.news_item.all()) 

229 slogan_items = split_items_3(page.slogans_item.all()) 

230 return render( 

231 request, 

232 "landingpage/landing_page.html", 

233 {"page": page, "news_items": news_items, "slogan_items": slogan_items}, 

234 ) 

235 

236 

237def about_page(request): 

238 """ 

239 Platform about page 

240 """ 

241 page = get_object_or_404(LandingPage, slug="discuss-data-landingpage") 

242 return render(request, "about.html", {"page": page},) 

243 

244 

245def contacts_page(request): 

246 """ 

247 Platform contacts page 

248 """ 

249 page = get_object_or_404(TextPage, slug=SLUG_CONTACTS) 

250 return render(request, "pages/text_page.html", {"page": page},) 

251 

252 

253def security_page(request): 

254 """ 

255 Platform security page 

256 """ 

257 page = get_object_or_404(TextPage, slug=SLUG_SECURITY) 

258 return render(request, "pages/text_page.html", {"page": page},) 

259 

260 

261def login_page(request): 

262 """ 

263 Platform login page 

264 """ 

265 page = get_object_or_404(TextPage, slug="discuss-data-loginpage") 

266 return render(request, "login.html", {"page": page},) 

267 

268 

269def handler404(request): 

270 response = render(request, "404.html") 

271 response.status_code = 404 

272 return response 

273 

274 

275def handler403(request): 

276 response = render(request, "403.html") 

277 response.status_code = 403 

278 return response 

279 

280 

281def response403(message): 

282 response = HttpResponse(_(message)) 

283 # response.status_code = 403 

284 return response 

285 

286 

287def handler500(request, *args, **argv): 

288 try: 

289 from sentry_sdk import last_event_id 

290 except ImportError: 

291 response = render(request, "500.html") 

292 response.status_code = 500 

293 return response 

294 else: 

295 return render( 

296 request, "500.html", {"sentry_event_id": last_event_id()}, status=500 

297 ) 

298 

299 

300def get_keyword_tags(request): 

301 qs = KeywordTagged.objects.all() 

302 query = None 

303 if query: 

304 return qs.filter(name__istartswith=query) 

305 

306 return render(request, "core/_tags.html", {"qs": qs}) 

307 

308 

309def polling_start(request): 

310 response = HttpResponse() 

311 response["X-IC-ResumePolling"] = "true" 

312 return response 

313 

314 

315def polling_stop(request): 

316 response = HttpResponse() 

317 response["X-IC-CancelPolling"] = "true" 

318 return response 

319 

320 

321def load(request): 

322 # return an empty response when core:load url is called. 

323 # needed for js initialisation in _tag_add_control.html 

324 response = HttpResponse() 

325 return response 

326 

327 

328def messages(request): 

329 return render(request, "core/_messages.html", {})