codeforlife-portal 8.3.8__py2.py3-none-any.whl → 8.4.1__py2.py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of codeforlife-portal might be problematic. Click here for more details.

@@ -49,6 +49,7 @@ CSP_STYLE_SRC = (
49
49
  )
50
50
  CSP_FRAME_SRC = (
51
51
  "https://storage.googleapis.com/",
52
+ "https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/"
52
53
  "https://www.youtube-nocookie.com/",
53
54
  "https://www.recaptcha.net/",
54
55
  "https://www.google.com/recaptcha/",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: codeforlife-portal
3
- Version: 8.3.8
3
+ Version: 8.4.1
4
4
  Classifier: Programming Language :: Python
5
5
  Classifier: Programming Language :: Python :: 3.12
6
6
  Classifier: Framework :: Django
@@ -4,7 +4,7 @@ cfl_common/common/__init__.py,sha256=XlncBOpKp_gekbKH7Y_i6yu1qy5tJc3Y8sn8cDy-Vgk
4
4
  cfl_common/common/app_settings.py,sha256=Bw1DXkZpNIdwUJ-cIOjZnngH5_NbMXC0koW7NgQ0pKY,2495
5
5
  cfl_common/common/apps.py,sha256=49UXZ3bSkFKvIEOL4zM7y1sAhccQJyRtsoOg5XVd_8Y,129
6
6
  cfl_common/common/context_processors.py,sha256=X0iuX5qu9kMWa7q8osE9CJ2LgM7pPOYQFGdjm8X3rk0,236
7
- cfl_common/common/csp_config.py,sha256=ex0--OwvUAEbrdI37p8FSlDhB8IVyl_XWbCPVVF9MY8,2790
7
+ cfl_common/common/csp_config.py,sha256=oOXxEh0LqGl89HBn8VHa1nFGTGIhEBqRTo-CzVCsdsw,2873
8
8
  cfl_common/common/mail.py,sha256=pIRfUMVoJWxdv74UqToj_0_pTVTC51z6QlFVLI3QBOw,6874
9
9
  cfl_common/common/models.py,sha256=_uD8pIO5fGVbOD8NydJVIzpiEDAaR2hIfpOhDT6jB34,16106
10
10
  cfl_common/common/permissions.py,sha256=gC6RQGZI2QDBbglx-xr_V4Hl2C2nf1V2_uPmEuoEcJo,2416
@@ -111,7 +111,7 @@ example_project/portal_test_settings.py,sha256=mTyObCGkZEI0IQSZkqCjb1WZ7ebjQLwui
111
111
  example_project/settings.py,sha256=pHQDI_A_yXV3u1efj689tc-vPI6nBFma4gMMPBzj0aI,5652
112
112
  example_project/urls.py,sha256=FUTzHPlUS1O5kqMHjL5V4L552N2ln7uTDXcw9wjKUto,422
113
113
  example_project/wsgi.py,sha256=U1W6WzZxZaIdYZ5tks7w9fqp5WS5qvn2iThsVcskrWw,829
114
- portal/__init__.py,sha256=830gX8muYFc22AmswN648u89HvKPUixSiF0sI1T7I1g,22
114
+ portal/__init__.py,sha256=6yCd3vhnQem22chqsom8x3AUg4DeTLyaMeAcm2HpMtk,22
115
115
  portal/admin.py,sha256=RKJizTF6dPJKmGPZw7nZUM0X8jkiTjgyKhLQxtvHJ0I,6148
116
116
  portal/app_settings.py,sha256=DhWLQOwM0zVOXE3O5TNKbMM9K6agfLuCsHOdr1J7xEI,651
117
117
  portal/backends.py,sha256=2Dss6_WoQwPuDzJUF1yEaTQTNG4eUrD12ujJQ5cp5Tc,812
@@ -119,7 +119,7 @@ portal/beta.py,sha256=0TCC-9_KZoM1nuzJ9FiuKR5n9JITdMYenHGQtRvn9UU,255
119
119
  portal/context_processors.py,sha256=1TrUZqnMqGa5f7ERph9EpBqojSMJvOrcpnJzTdeCLDI,133
120
120
  portal/handlers.py,sha256=gF99OfQrGcIGDnUyONhvylZNU8sl6XHYEurwu0fuiss,422
121
121
  portal/models.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
122
- portal/urls.py,sha256=LFSumASmTGjFciMcc6OEFvJ1MWgFUS5wNRugGWON40E,18211
122
+ portal/urls.py,sha256=BWhRI-9rGEydbasI0UCtYYASqHbyUXokfepNWty7cQg,18218
123
123
  portal/wsgi.py,sha256=3yRcNxBQG30NhzrVi93bX-DrbXtsIQBc70HiW5wbOyE,401
124
124
  portal/forms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
125
125
  portal/forms/admin.py,sha256=Cdl8-wvasAzvMfgUlFYzQjYeuyC7gIsSiy8V_-jMp7w,2080
@@ -419,7 +419,7 @@ portal/static/portal/sass/partials/_ui-dialog.scss,sha256=gaXrY_uGqT6SyxYsCJmEiw
419
419
  portal/static/portal/sass/partials/_utils.scss,sha256=v0rzXvmkmA4sex_DdZ0LPYQybP8HXqDAE4q-kQKkPgk,3468
420
420
  portal/static/portal/video/code for life .pdf,sha256=0dVvxGFmCOhIzdMBjGhZJLhIoUX4vPll3_vFnZQqeAc,277957
421
421
  portal/strings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
422
- portal/strings/about.py,sha256=noSrUV6c4gLvg4Cm7xpeE7cGbWTixi7_HJcw6EXdvqY,644
422
+ portal/strings/about.py,sha256=ROt_UFX9eBzTJRkBTFF0591EO4_6WM4_kEy-vRrlPlk,962
423
423
  portal/strings/coding_club.py,sha256=fMQt829owRrqsH7CWTxo_TUrTOx70ll92XciRgqhlUw,312
424
424
  portal/strings/help_and_support.py,sha256=S6lQU6y0WhwBl33KDPlFA48NGQpuuBUGOY9WsB_ys0U,386
425
425
  portal/strings/home_learning.py,sha256=ZZ9rLupgBGrawxQ1kovCyYId6mK3w5LHchX8Ct8J2Lc,273
@@ -466,13 +466,13 @@ portal/templates/portal/login/independent_student.html,sha256=G4u82m0lko4yQvqRDM
466
466
  portal/templates/portal/login/student.html,sha256=s5rUyT-u7gei2xWQ-Ba35ePC5WbtwReEzUZAKwUoZVY,1261
467
467
  portal/templates/portal/login/student_class_code.html,sha256=rJr6NB4Oz7XjZXDOUHpwzT6r6yxh7nZ5joca-z2bK-s,966
468
468
  portal/templates/portal/login/teacher.html,sha256=s-8s55_D0jCf7ejEDIN2Vexpde0BljojRAz9QODLSUk,2671
469
- portal/templates/portal/partials/banner.html,sha256=HV6XG99ZEuN8Njlx-bGenZMTUI69-1NsxX3YfccX2CA,1531
469
+ portal/templates/portal/partials/banner.html,sha256=5MzRKCZWFPDzcRzHPqG5MeED_KsmvAcKoA74YYXmlPY,2101
470
470
  portal/templates/portal/partials/benefits.html,sha256=TZm4U_XimgivkPMjDXxxkV7PLfRyi2PAwkH8Y4sFDps,2363
471
471
  portal/templates/portal/partials/card_list.html,sha256=yHcp4oc0WRG9H6Ek871VCHbwYkDRcwQYbZ320gtsFn8,1550
472
472
  portal/templates/portal/partials/character_list.html,sha256=SnNFHzbIkOSaiRPIvSdplEf_B87UYgJ1pOvMltNDxLE,415
473
473
  portal/templates/portal/partials/delete_popup.html,sha256=nEhnwgnmKoFzb6LlCwdX973Em9bVOFh6MON36RPteYs,1275
474
- portal/templates/portal/partials/footer.html,sha256=mJFsBJY1jfDUdujuceh0Y1bIXccIEWzbvEfsmNGl6D4,5036
475
- portal/templates/portal/partials/header.html,sha256=aRFgTy5JSQTqXSGUo7XQWd3a4Ia4auvJl3D3iNgJhm0,20250
474
+ portal/templates/portal/partials/footer.html,sha256=IKEUmghaiiuQs5g9JfE97oNzjRTzBTu3SoFgJhRMyi8,5533
475
+ portal/templates/portal/partials/header.html,sha256=xorEsPYzbmZGXHBOKm_6SHXQJxkCFKEWfMJbADG3k3I,20816
476
476
  portal/templates/portal/partials/headline.html,sha256=xKb-WtkT0FyQqT0smyNSKkXFvU7KQ5Czad8ca6YKQg4,89
477
477
  portal/templates/portal/partials/hero_card.html,sha256=UN5hyxrw-McuXFsDzPBIECB9yGrv9VjsFf8SEBowwXc,786
478
478
  portal/templates/portal/partials/info_popup.html,sha256=gzffd5MBVb7p2hGQuZMNDudThrRgs847hCu9ziT9uLE,566
@@ -611,6 +611,7 @@ portal/views/admin.py,sha256=4Xt3zEyQH7sUwQSrwuRtoCodWidjOzd7gJUwWU96pXY,957
611
611
  portal/views/api.py,sha256=mdWmFkV5mxmR-mvj6ttIe8uwW9tbcx9-5ykk5dpX0LI,7047
612
612
  portal/views/dotmailer.py,sha256=OH06IXuqqjhQbEie8g8y2ZY1oZvsCtNHhkQRLa-julg,2467
613
613
  portal/views/email.py,sha256=V3wXRxIjeZ4OJBVqGCQrPn-GQWKZK1PCXbR1f2Zpa_4,2174
614
+ portal/views/google_analytics.py,sha256=cbNq9apCVpjoXCdovjrwo2jshWu5tUOItB-fTr-losw,769
614
615
  portal/views/home.py,sha256=8leK4ADxRg-gK-bm7D08CR44bhV3I8lt5pCV59HXMkk,9619
615
616
  portal/views/legal.py,sha256=yarJgxmr0q2Bn5TAKfBdVdxc964YIJN2ByG2SvY6IP0,348
616
617
  portal/views/organisation.py,sha256=sPDbiM7hdtpF8GKyh_4n4VPl2a-WnAgnF4q9aSvQCVI,3341
@@ -633,8 +634,8 @@ portal/views/two_factor/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
633
634
  portal/views/two_factor/core.py,sha256=Lk32z2SN2Pg0rRkK-N-LXMvXC1kKKsH3l692kiSDQ4E,964
634
635
  portal/views/two_factor/form.py,sha256=lnHNKI-BMlpncTuW3zUzjPaJJNuEra2I_nOam0eOKFY,257
635
636
  portal/views/two_factor/profile.py,sha256=SHSg_xHccE5PtD-OfuOkYhREYz_er4bj5ro1RjJ88Yw,393
636
- codeforlife_portal-8.3.8.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
637
- codeforlife_portal-8.3.8.dist-info/METADATA,sha256=dErvdzhb1YJeLyK8zaMuy9llsy1GEi6VzzbRC_zkjS0,3077
638
- codeforlife_portal-8.3.8.dist-info/WHEEL,sha256=WDDPHYzpiOIm6GP1C2_8y8W6q16ICddAgOHlhTje9Qc,109
639
- codeforlife_portal-8.3.8.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
640
- codeforlife_portal-8.3.8.dist-info/RECORD,,
637
+ codeforlife_portal-8.4.1.dist-info/LICENSE.md,sha256=9AbRlCDqD2D1tPibimysFv3zg3AIc49-eyv9aEsyq9w,115
638
+ codeforlife_portal-8.4.1.dist-info/METADATA,sha256=bU_r6aXVNL0xdvKY25Bd42t6lWnJuswz2NejKBwUb9w,3077
639
+ codeforlife_portal-8.4.1.dist-info/WHEEL,sha256=WDDPHYzpiOIm6GP1C2_8y8W6q16ICddAgOHlhTje9Qc,109
640
+ codeforlife_portal-8.4.1.dist-info/top_level.txt,sha256=8e5pdsuIoTqEAMqpelHBjGjLbffcBtgOoggmd2q7nMw,41
641
+ codeforlife_portal-8.4.1.dist-info/RECORD,,
portal/__init__.py CHANGED
@@ -1 +1 @@
1
- __version__ = "8.3.8"
1
+ __version__ = "8.4.1"
portal/strings/about.py CHANGED
@@ -9,6 +9,11 @@ GETINVOLVED_BANNER = {
9
9
  "title": "Get involved",
10
10
  "subtitle": "How you can get involved with the creation of Code for Life products and resources",
11
11
  "image_class": "banner--picture--getinvolved",
12
+ "button": {
13
+ "external": True,
14
+ "text": "Opportunities with Code for Life",
15
+ "link": "https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FPavvCifcuUeZZZLkV01C%2FOpportunities%20with%20Code%20for%20Life.pdf?alt=media",
16
+ },
12
17
  }
13
18
 
14
19
  CONTRIBUTE_BANNER = {
@@ -12,10 +12,18 @@
12
12
  {% endif %}
13
13
  <div class="button-group">
14
14
  {% if button %}
15
- <a href="{% url button.link %}" class="button button--primary button-right-arrow">{{ button.text}}</a>
15
+ {% if button.external %}
16
+ <a href="{{ button.link }}" target="_blank" class="button button--primary button-right-arrow">{{ button.text }}</a>
17
+ {% else %}
18
+ <a href="{% url button.link %}" class="button button--primary button-right-arrow">{{ button.text}}</a>
19
+ {% endif %}
16
20
  {% endif %}
17
21
  {% if button2 %}
18
- <a href="{% url button2.link %}" class="button button--primary button-right-arrow">{{ button2.text}}</a>
22
+ {% if button.external %}
23
+ <a href="{{ button2.link }}" target="_blank" class="button button--primary button-right-arrow">{{ button2.text }}</a>
24
+ {% else %}
25
+ <a href="{% url button2.link %}" class="button button--primary button-right-arrow">{{ button2.text}}</a>
26
+ {% endif %}
19
27
  {% endif %}
20
28
  </div>
21
29
  </div>
@@ -9,9 +9,9 @@
9
9
  <div class="col-sm-4 col-xs-12">
10
10
  <p><a href="{% url 'about' %}">About us</a></p>
11
11
  <p><a class="freshdesk__contact-us">Help and support</a></p>
12
- <p><a href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2023.pdf"
12
+ <p><a href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FHx2kJLPwUER9Ez7gdQFp%2F2023_Impact_Report_Final.pdf?alt=media"
13
13
  target="_blank">Impact Report 2023</a></p>
14
- <p><a href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2024.pdf"
14
+ <p><a href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FzLy8JN9TSFpzunetkWET%2FImpact_Report_24.V.10.pdf?alt=media"
15
15
  target="_blank">Impact Report 2024</a></p>
16
16
  </div>
17
17
  <div class="col-sm-4 col-xs-12">
@@ -23,6 +23,8 @@
23
23
  <p><a href="{% url 'home-learning' %}">Home learning</a></p>
24
24
  <p><a href="{% url 'getinvolved' %}">Get involved</a></p>
25
25
  <p><a href="{% url 'codingClub' %}">Coding clubs</a></p>
26
+ <p><a href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FPavvCifcuUeZZZLkV01C%2FOpportunities%20with%20Code%20for%20Life.pdf?alt=media"
27
+ target="_blank">Opportunities with CFL</a></p>
26
28
  </div>
27
29
  </div>
28
30
  </div>
@@ -259,10 +259,10 @@
259
259
  <a class="button button--menu__item freshdesk__contact-us">Help and support
260
260
  <span class="material-icons-outlined md-32">chevron_right</span></a>
261
261
  <a class="button button--menu__item" target="_blank"
262
- href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2023.pdf">
262
+ href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FHx2kJLPwUER9Ez7gdQFp%2F2023_Impact_Report_Final.pdf?alt=media">
263
263
  Impact Report 2023<span class="material-icons-outlined md-32">chevron_right</span></a>
264
264
  <a class="button button--menu__item" target="_blank"
265
- href="https://storage.googleapis.com/codeforlife-assets/impact_reports/impact_report_2024.pdf">
265
+ href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FzLy8JN9TSFpzunetkWET%2FImpact_Report_24.V.10.pdf?alt=media">
266
266
  Impact Report 2024<span class="material-icons-outlined md-32">chevron_right</span></a>
267
267
  <a class="button button--menu__item optanon-toggle-display">Cookie settings
268
268
  <span class="material-icons-outlined md-32">chevron_right</span></a>
@@ -274,6 +274,9 @@
274
274
  <span class="material-icons-outlined md-32">chevron_right</span></a>
275
275
  <a class="button button--menu__item" href="{% url 'getinvolved' %}">Get involved
276
276
  <span class="material-icons-outlined md-32">chevron_right</span></a>
277
+ <a class="button button--menu__item" target="_blank"
278
+ href="https://2662351606-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-M_6UDUiGoJDhr_OXetO%2Fuploads%2FPavvCifcuUeZZZLkV01C%2FOpportunities%20with%20Code%20for%20Life.pdf?alt=media">Opportunities with CFL
279
+ <span class="material-icons-outlined md-32">chevron_right</span></a>
277
280
  {% if user|is_logged_in %}
278
281
  {% if user|is_logged_in_as_teacher %}
279
282
  {% if user|has_teacher_finished_onboarding %}
portal/urls.py CHANGED
@@ -21,12 +21,9 @@ from portal.helpers.ratelimit import (
21
21
  school_student_key,
22
22
  )
23
23
  from portal.helpers.regexes import ACCESS_CODE_REGEX, JWT_REGEX
24
- from portal.views import cron
24
+ from portal.views import cron, google_analytics
25
25
  from portal.views.about import about, contribute, getinvolved
26
- from portal.views.admin import (
27
- AdminChangePasswordDoneView,
28
- AdminChangePasswordView,
29
- )
26
+ from portal.views.admin import AdminChangePasswordDoneView, AdminChangePasswordView
30
27
  from portal.views.api import (
31
28
  AnonymiseOrphanSchoolsView,
32
29
  InactiveUsersView,
@@ -35,10 +32,7 @@ from portal.views.api import (
35
32
  number_users_per_country,
36
33
  registered_users,
37
34
  )
38
- from portal.views.dotmailer import (
39
- dotmailer_consent_form,
40
- process_newsletter_form,
41
- )
35
+ from portal.views.dotmailer import dotmailer_consent_form, process_newsletter_form
42
36
  from portal.views.email import verify_email
43
37
  from portal.views.home import (
44
38
  coding_club,
@@ -111,12 +105,8 @@ from portal.views.two_factor.profile import CustomDisableView
111
105
  js_info_dict = {"packages": ("conf.locale",)}
112
106
 
113
107
  two_factor_patterns = [
114
- re_path(
115
- r"^account/two_factor/setup/$", CustomSetupView.as_view(), name="setup"
116
- ),
117
- re_path(
118
- r"^account/two_factor/qrcode/$", QRGeneratorView.as_view(), name="qr"
119
- ),
108
+ re_path(r"^account/two_factor/setup/$", CustomSetupView.as_view(), name="setup"),
109
+ re_path(r"^account/two_factor/qrcode/$", QRGeneratorView.as_view(), name="qr"),
120
110
  re_path(
121
111
  r"^account/two_factor/setup/complete/$",
122
112
  SetupCompleteView.as_view(),
@@ -141,6 +131,11 @@ two_factor_patterns = [
141
131
 
142
132
 
143
133
  urlpatterns = [
134
+ path(
135
+ "google-analytics/collect/",
136
+ google_analytics.collect,
137
+ name="collect-google-analytics",
138
+ ),
144
139
  path(
145
140
  "cron/",
146
141
  include(
@@ -187,9 +182,7 @@ urlpatterns = [
187
182
  ),
188
183
  re_path(
189
184
  r"^favicon\.ico$",
190
- RedirectView.as_view(
191
- url="/static/portal/img/favicon.ico", permanent=True
192
- ),
185
+ RedirectView.as_view(url="/static/portal/img/favicon.ico", permanent=True),
193
186
  ),
194
187
  re_path(
195
188
  r"^administration/password_change/$",
@@ -201,9 +194,7 @@ urlpatterns = [
201
194
  AdminChangePasswordDoneView.as_view(),
202
195
  name="administration_password_change_done",
203
196
  ),
204
- re_path(
205
- r"^users/inactive/", InactiveUsersView.as_view(), name="inactive_users"
206
- ),
197
+ re_path(r"^users/inactive/", InactiveUsersView.as_view(), name="inactive_users"),
207
198
  re_path(
208
199
  r"^locked_out/$",
209
200
  TemplateView.as_view(template_name="portal/locked_out.html"),
@@ -281,9 +272,7 @@ urlpatterns = [
281
272
  re_path(r"^consent_form/$", dotmailer_consent_form, name="consent_form"),
282
273
  re_path(
283
274
  r"^verify_email/$",
284
- TemplateView.as_view(
285
- template_name="portal/email_verification_needed.html"
286
- ),
275
+ TemplateView.as_view(template_name="portal/email_verification_needed.html"),
287
276
  name="email_verification",
288
277
  ),
289
278
  re_path(
@@ -368,9 +357,7 @@ urlpatterns = [
368
357
  IndependentStudentDashboard.as_view(),
369
358
  name="independent_student_details",
370
359
  ),
371
- re_path(
372
- r"^play/account/$", student_edit_account, name="student_edit_account"
373
- ),
360
+ re_path(r"^play/account/$", student_edit_account, name="student_edit_account"),
374
361
  re_path(
375
362
  r"^play/account/independent/$",
376
363
  ratelimit(
@@ -398,9 +385,7 @@ urlpatterns = [
398
385
  re_path(r"^contribute", contribute, name="contribute"),
399
386
  re_path(r"^terms", terms, name="terms"),
400
387
  re_path(r"^privacy-notice/$", privacy_notice, name="privacy_notice"),
401
- re_path(
402
- r"^privacy-policy/$", privacy_notice, name="privacy_policy"
403
- ), # Keeping this to route from old URL
388
+ re_path(r"^privacy-policy/$", privacy_notice, name="privacy_policy"), # Keeping this to route from old URL
404
389
  re_path(r"^teach/dashboard/$", dashboard_manage, name="dashboard"),
405
390
  re_path(
406
391
  r"^teach/dashboard/kick/(?P<pk>[0-9]+)/$",
@@ -0,0 +1,28 @@
1
+ import json
2
+
3
+ import requests
4
+ from django.http import HttpRequest, JsonResponse
5
+ from django.views.decorators.csrf import csrf_exempt
6
+
7
+
8
+ @csrf_exempt
9
+ def collect(request: HttpRequest):
10
+ body: dict = json.loads(request.body)
11
+ measurement_id = body["measurement_id"]
12
+ api_secret = body["api_secret"]
13
+ debug = body.get("debug", False)
14
+
15
+ response = requests.post(
16
+ url=(
17
+ "https://www.google-analytics.com/debug/mp/collect"
18
+ if debug
19
+ else "https://www.google-analytics.com/mp/collect"
20
+ )
21
+ + f"?measurement_id=${measurement_id}&api_secret=${api_secret}",
22
+ json=body["payload"],
23
+ )
24
+
25
+ return JsonResponse(
26
+ data=response.json() if debug else {},
27
+ status=response.status_code,
28
+ )