├── api ├── __init__.py ├── quizs │ ├── __init__.py │ └── filters.py ├── tags │ ├── __init__.py │ ├── views.py │ └── serializers.py ├── tests │ └── __init__.py ├── users │ ├── __init__.py │ └── serializers.py ├── categories │ ├── __init__.py │ ├── views.py │ └── serializers.py ├── glossary │ ├── __init__.py │ ├── filters.py │ ├── serializers.py │ ├── views.py │ └── tests.py ├── questions │ ├── __init__.py │ └── filters.py ├── contributions │ ├── __init__.py │ ├── views.py │ └── serializers.py └── serializers.py ├── app ├── __init__.py ├── asgi.py ├── wsgi.py └── urls.py ├── core ├── __init__.py ├── tests │ └── __init__.py ├── migrations │ ├── __init__.py │ ├── 0003_configuration_helloasso_url.py │ ├── 0002_alter_configuration_application_open_source_code_url.py │ └── 0004_configuration_office_address_and_url.py ├── templatetags │ ├── __init__.py │ ├── strip_html.py │ ├── user_can_edit.py │ ├── get_language_flag.py │ ├── dict_filters.py │ ├── array_choices_item_display.py │ ├── array_choices_display.py │ ├── get_verbose_name.py │ └── custom_filters.py ├── static │ ├── images │ │ └── favicon.ico │ └── css │ │ └── admin │ │ └── extra.css ├── templates │ ├── admin │ │ └── base.html │ └── layouts │ │ └── main.html └── fields.py ├── quizs ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0009_remove_quiz_author.py │ ├── 0011_quizrelationship_updated.py │ ├── 0006_rename_quiz_author.py │ ├── 0015_quiz_publish_date.py │ ├── 0013_historicalquiz_history_changed_fields.py │ ├── 0028_alter_historicalquiz_history_changed_fields.py │ ├── 0020_remove_historicalquiz_author_and_more.py │ ├── 0002_quiz_author_link.py │ ├── 0012_alter_historicalquiz_options_and_more.py │ ├── 0019_forward_data_author_to_authors.py │ ├── 0003_populate_quiz_author_link.py │ ├── 0014_alter_historicalquiz_language_alter_quiz_language.py │ ├── 0021_quiz_language_migration.py │ ├── 0017_alter_historicalquiz_created_alter_quiz_created_and_more.py │ ├── 0005_alter_quiz_timestamps.py │ ├── 0026_quiz_language_spanish_italian.py │ ├── 0010_quiz_visibility.py │ ├── 0024_alter_historicalquiz_validation_status_and_more.py │ └── 0027_quiz_visibility_translation_fix.py ├── factories.py ├── management │ └── commands │ │ └── sanitize_quiz_question_ordering.py └── filters.py ├── stats ├── __init__.py ├── tests │ └── __init__.py ├── migrations │ ├── __init__.py │ ├── 0007_linkclickevent_field_name.py │ ├── 0003_quizanswerevent_question_answer_split.py │ ├── 0004_dailystat_question_public_and_quiz_public_answer_count.py │ ├── 0002_questionanswerevent_quiz_questionfeedbackevent_quiz.py │ └── 0008_alter_linkclickevent_question_and_more.py ├── urls.py └── constants.py ├── tags ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0004_alter_tag_created.py │ ├── 0003_alter_tag_timestamps.py │ ├── 0002_add_verbose_names.py │ ├── 0005_tag_model_translation.py │ └── 0001_initial.py ├── factories.py ├── forms.py ├── filters.py ├── admin.py └── templates │ └── admin │ └── tags │ └── tag │ └── change_list.html ├── users ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0002_alter_user_managers.py │ ├── 0009_user_logs.py │ ├── 0005_alter_user_created.py │ ├── 0011_user_profile_comments_last_seen_date.py │ ├── 0004_alter_user_timestamps.py │ ├── 0010_user_profile_home_last_seen_date.py │ └── 0003_user_roles.py ├── factories.py ├── forms.py ├── tables.py ├── constants.py └── filters.py ├── www ├── __init__.py ├── admin │ ├── __init__.py │ └── urls.py ├── auth │ ├── __init__.py │ ├── forms.py │ ├── views.py │ └── urls.py ├── pages │ ├── __init__.py │ ├── urls.py │ └── views.py ├── profile │ └── __init__.py ├── quizs │ ├── __init__.py │ └── urls.py ├── tags │ ├── __init__.py │ └── urls.py ├── users │ ├── __init__.py │ ├── urls.py │ └── views.py ├── activity │ ├── __init__.py │ ├── urls.py │ └── views.py ├── categories │ ├── __init__.py │ └── urls.py ├── glossary │ ├── __init__.py │ └── urls.py ├── questions │ └── __init__.py └── contributions │ ├── __init__.py │ └── urls.py ├── activity ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0004_alter_event_actor_id_object_id_allow_null.py │ ├── 0005_alter_event_event_object_type_monthly_agg_stat.py │ └── 0002_alter_event_created_alter_event_event_object_type.py ├── factories.py └── admin.py ├── categories ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0004_alter_category_created.py │ ├── 0003_alter_category_timestamps.py │ ├── 0002_add_verbose_names.py │ ├── 0005_category_model_translation.py │ └── 0001_initial.py ├── factories.py ├── forms.py ├── admin.py ├── templates │ └── admin │ │ └── categories │ │ └── category │ │ └── change_list.html ├── tables.py └── models.py ├── glossary ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0004_remove_glossaryitem_added_and_more.py │ ├── 0003_alter_glossaryitem_timestamps.py │ ├── 0006_historicalglossaryitem_history_changed_fields.py │ ├── 0008_alter_historicalglossaryitem_history_changed_fields.py │ ├── 0007_alter_glossaryitem_created_and_more.py │ ├── 0002_add_verbose_names.py │ ├── 0001_initial.py │ └── 0010_glossaryitem_language.py ├── factories.py ├── admin.py ├── forms.py ├── filters.py └── tables.py ├── history ├── __init__.py ├── utilities.py └── tables.py ├── questions ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0009_remove_question_author_validator.py │ ├── 0010_remove_historicalquestion_added_and_more.py │ ├── 0005_alter_question_timestamps.py │ ├── 0015_question_validation_date.py │ ├── 0013_historicalquestion_history_changed_fields.py │ ├── 0028_alter_historicalquestion_history_changed_fields.py │ ├── 0016_alter_historicalquestion_created_and_more.py │ ├── 0012_alter_historicalquestion_options_and_more.py │ ├── 0006_rename_question_author_validator.py │ ├── 0017_rename_answer_audio_historicalquestion_answer_audio_url_and_more.py │ ├── 0014_alter_historicalquestion_language_and_more.py │ ├── 0022_question_language_migration.py │ ├── 0002_question_author_link_question_validator_link.py │ ├── 0026_question_language_spanish_italian.py │ ├── 0025_alter_historicalquestion_validation_status_and_more.py │ ├── 0027_question_visibility_translation_fix.py │ └── 0011_question_visibility.py └── factories.py ├── contributions ├── __init__.py ├── migrations │ ├── __init__.py │ ├── 0005_contribution_updated.py │ ├── 0010_alter_contribution_created.py │ ├── 0012_rename_contribution_comment.py │ ├── 0007_contribution_parent.py │ ├── 0014_comment_remove_status_replied.py │ ├── 0004_contribution_author.py │ ├── 0008_alter_contribution_status.py │ ├── 0016_comment_publish.py │ ├── 0009_alter_contribution_type.py │ ├── 0002_contribution_question_contribution_quiz.py │ └── 0017_alter_comment_status_default.py ├── factories.py └── filters.py ├── Procfile ├── templates ├── auth │ ├── password_reset_email_subject.txt │ ├── password_reset_email_body.html │ ├── password_reset_complete.html │ ├── password_reset.html │ ├── password_reset_sent.html │ └── login.html ├── glossary │ ├── _table_action_items.html │ └── detail_edit.html ├── contributions │ └── _table_action_items.html ├── includes │ ├── _header_notice_env.html │ ├── _header_notice_beta.html │ ├── _filter_badge_list.html │ ├── _badge_item.html │ ├── _language_form.html │ ├── _paginator.html │ └── _s3_upload_form.html ├── tags │ ├── _badge_list.html │ ├── detail_view.html │ ├── detail_edit.html │ └── detail_quizs.html ├── activity │ ├── _event_list.html │ ├── _recent_actions_home_card.html │ └── list.html ├── history │ ├── _table_changed_fields_list.html │ └── _table_id_link.html ├── profile │ ├── quizs_stats.html │ ├── questions_stats.html │ ├── quizs_view.html │ ├── history.html │ ├── info_card_view.html │ └── comments_view.html ├── categories │ ├── _badge_item.html │ ├── detail_view.html │ ├── detail_edit.html │ └── list.html ├── 404.html ├── questions │ ├── detail_quizs.html │ ├── detail_stats.html │ └── detail_comments.html ├── 500.html ├── 403.html ├── quizs │ └── detail_stats.html ├── admin │ └── history.html └── users │ └── administrator_list.html ├── .coveragerc ├── locale ├── de │ └── LC_MESSAGES │ │ └── django.mo ├── en │ └── LC_MESSAGES │ │ └── django.mo ├── es │ └── LC_MESSAGES │ │ └── django.mo ├── fr │ └── LC_MESSAGES │ │ └── django.mo └── it │ └── LC_MESSAGES │ └── django.mo ├── release-tasks.sh ├── crowdin.yml ├── .github └── workflows │ ├── auto-assign-pr.yml │ ├── semantic-pr.yml │ ├── release-please.yml │ └── automerge.yml ├── setup.cfg ├── .gitignore ├── pyproject.toml ├── cron.json ├── manage.py ├── .env.example ├── .pre-commit-config.yaml └── Pipfile /api/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /app/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /quizs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stats/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /users/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /activity/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/quizs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/tags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/users/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /categories/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /glossary/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /history/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /questions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stats/tests/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/admin/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/auth/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/pages/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/profile/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/quizs/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/tags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/users/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/categories/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/glossary/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/questions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contributions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /quizs/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /stats/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tags/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /users/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/activity/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/categories/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/glossary/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/questions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /activity/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /api/contributions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /categories/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /core/templatetags/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /glossary/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /questions/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /www/contributions/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /contributions/migrations/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /Procfile: -------------------------------------------------------------------------------- 1 | postdeploy: ./release-tasks.sh 2 | web: gunicorn app.wsgi --log-file - 3 | -------------------------------------------------------------------------------- /templates/auth/password_reset_email_subject.txt: -------------------------------------------------------------------------------- 1 | Réinitialisation de votre mot de passe 2 | -------------------------------------------------------------------------------- /.coveragerc: -------------------------------------------------------------------------------- 1 | [run] 2 | source= 3 | . 4 | omit= 5 | /usr/* 6 | [report] 7 | #skip_covered=True 8 | #exclude_lines= 9 | -------------------------------------------------------------------------------- /core/static/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/core/static/images/favicon.ico -------------------------------------------------------------------------------- /locale/de/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/locale/de/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /locale/en/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/locale/en/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /locale/es/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/locale/es/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /locale/fr/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/locale/fr/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /locale/it/LC_MESSAGES/django.mo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/quiz-anthropocene/admin-backend/HEAD/locale/it/LC_MESSAGES/django.mo -------------------------------------------------------------------------------- /templates/glossary/_table_action_items.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | {% translate "View" %} 4 | -------------------------------------------------------------------------------- /templates/contributions/_table_action_items.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 | {% translate "View" %} 4 | -------------------------------------------------------------------------------- /release-tasks.sh: -------------------------------------------------------------------------------- 1 | python manage.py migrate 2 | # python manage.py loaddata data/ressources-glossaire.yaml --model=glossary --format=yaml-pretty-flat # won't work if DEPLOY_FOLDER set 3 | -------------------------------------------------------------------------------- /activity/factories.py: -------------------------------------------------------------------------------- 1 | import factory 2 | 3 | from activity.models import Event 4 | 5 | 6 | class EventFactory(factory.django.DjangoModelFactory): 7 | class Meta: 8 | model = Event 9 | -------------------------------------------------------------------------------- /api/serializers.py: -------------------------------------------------------------------------------- 1 | from rest_framework import serializers 2 | 3 | 4 | class SimpleChoiceSerializer(serializers.Serializer): 5 | id = serializers.CharField() 6 | name = serializers.CharField() 7 | -------------------------------------------------------------------------------- /templates/includes/_header_notice_env.html: -------------------------------------------------------------------------------- 1 |
3 | DEBUG 4 |
5 |5 | {% translate "Website under construction. Feedback is gladly welcome (bugs, improvements...)" %} 🙏🏻👉 {% translate "contact us" %} 6 |
7 |La page que vous avez demandée n'a pas pu être trouvée.
12 |Une erreur technique s'est produite. L'équipe technique a été notifiée :)
12 | {#Notre équipe technique a été informée du problème et s'en occupera le plus rapidement possible.
#} 13 |{{ exception }}
16 |Accès refusé
19 | {% endif %} 20 | 21 |19 | Statistiques avancées 20 | (être patient…) 21 |
22 | 23 | {% endblock %} 24 | -------------------------------------------------------------------------------- /contributions/migrations/0012_rename_contribution_comment.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.5 on 2023-03-20 15:53 2 | 3 | from django.conf import settings 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("questions", "0028_alter_historicalquestion_history_changed_fields"), 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ("quizs", "0028_alter_historicalquiz_history_changed_fields"), 13 | ("contributions", "0011_contribution_model_translation"), 14 | ] 15 | 16 | operations = [ 17 | migrations.RenameModel( 18 | old_name="Contribution", 19 | new_name="Comment", 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /history/utilities.py: -------------------------------------------------------------------------------- 1 | def get_diff_between_two_history_records(new_record, old_record=None, excluded_fields=None, returns="delta"): 2 | if not old_record: 3 | if new_record.prev_record: 4 | old_record = new_record.prev_record 5 | else: 6 | raise Exception("get_diff_between_two_history_records old_record not found") 7 | 8 | delta = new_record.diff_against(old_record, excluded_fields=excluded_fields) 9 | 10 | if returns == "changed_fields": 11 | # flat list of fields 12 | return delta.changed_fields 13 | elif returns == "changes": 14 | # object list : {"field": "test", "old": "previous value", new": "fresh value"} 15 | return delta.changes 16 | return delta 17 | -------------------------------------------------------------------------------- /core/templatetags/array_choices_display.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | from django.utils.encoding import force_str 3 | 4 | from users import constants 5 | 6 | 7 | register = template.Library() 8 | 9 | 10 | @register.simple_tag 11 | def array_choices_display(obj, field): 12 | """Pretty rendering of ArrayField with choices.""" 13 | 14 | choices_dict = dict() 15 | 16 | if field == "roles": 17 | choices_dict = dict(constants.USER_ROLE_CHOICES) 18 | 19 | try: 20 | keys = obj.get(field, []) 21 | except: # noqa 22 | keys = getattr(obj, field, []) 23 | 24 | value_display_list = [force_str(choices_dict.get(key, "")) for key in (keys or [])] 25 | return ", ".join(filter(None, value_display_list)) 26 | -------------------------------------------------------------------------------- /tags/migrations/0003_alter_tag_timestamps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-01 21:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("tags", "0002_add_verbose_names"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="tag", 15 | name="updated", 16 | field=models.DateTimeField(auto_now=True, verbose_name="Date de dernière modification"), 17 | ), 18 | migrations.AlterField( 19 | model_name="tag", 20 | name="created", 21 | field=models.DateTimeField(auto_now_add=True, verbose_name="Date de création"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /users/migrations/0004_alter_user_timestamps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-01 21:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("users", "0003_user_roles"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="user", 15 | name="created", 16 | field=models.DateTimeField(auto_now_add=True, verbose_name="Date de création"), 17 | ), 18 | migrations.AlterField( 19 | model_name="user", 20 | name="updated", 21 | field=models.DateTimeField(auto_now=True, verbose_name="Date de dernière modification"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /glossary/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from core.admin import ExportMixin, admin_site 4 | from glossary.models import GlossaryItem 5 | 6 | 7 | class GlossaryAdmin(ExportMixin, admin.ModelAdmin): 8 | list_display = ( 9 | "id", 10 | "name", 11 | "definition_short", 12 | "language", 13 | "created", 14 | ) 15 | 16 | readonly_fields = ["created", "updated"] 17 | 18 | def has_add_permission(self, request, obj=None): 19 | return False 20 | 21 | def has_change_permission(self, request, obj=None): 22 | return False 23 | 24 | def has_delete_permission(self, request, obj=None): 25 | return False 26 | 27 | 28 | admin_site.register(GlossaryItem, GlossaryAdmin) 29 | -------------------------------------------------------------------------------- /questions/factories.py: -------------------------------------------------------------------------------- 1 | import factory 2 | 3 | from categories.factories import CategoryFactory 4 | from core import constants 5 | from questions.models import Question 6 | 7 | 8 | class QuestionFactory(factory.django.DjangoModelFactory): 9 | class Meta: 10 | model = Question 11 | 12 | text = "La question" 13 | type = constants.QUESTION_TYPE_QCM 14 | difficulty = constants.QUESTION_DIFFICULTY_EASY 15 | language = constants.LANGUAGE_FRENCH 16 | category = factory.SubFactory(CategoryFactory, name="Energie") 17 | answer_choice_a = "La réponse A" 18 | answer_choice_b = "La réponse B" 19 | answer_correct = "a" # constants.QUESTION_ANSWER_CHOICE_LIST[0] 20 | validation_status = constants.VALIDATION_STATUS_VALIDATED 21 | -------------------------------------------------------------------------------- /core/migrations/0002_alter_configuration_application_open_source_code_url.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-18 21:30 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("core", "0001_initial"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="configuration", 15 | name="application_open_source_code_url", 16 | field=models.URLField( 17 | default="https://github.com/quiz-anthropocene", 18 | editable=False, 19 | help_text="Le lien vers le code de l'application", 20 | max_length=500, 21 | ), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /core/fields.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.contrib.postgres.fields import ArrayField 3 | 4 | 5 | # https://stackoverflow.com/a/66059615/4293684 6 | class ChoiceArrayField(ArrayField): 7 | """ 8 | Custom ArrayField with a ChoiceField as default field. 9 | The default field is a comma-separated InputText, which is not very useful. 10 | """ 11 | 12 | def formfield(self, **kwargs): 13 | defaults = { 14 | "form_class": forms.TypedMultipleChoiceField, 15 | "choices": self.base_field.choices, 16 | "coerce": self.base_field.to_python, 17 | "widget": forms.CheckboxSelectMultiple, 18 | } 19 | defaults.update(kwargs) 20 | return super(ArrayField, self).formfield(**defaults) 21 | -------------------------------------------------------------------------------- /activity/migrations/0004_alter_event_actor_id_object_id_allow_null.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2 on 2023-04-28 18:59 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("activity", "0003_event_model_translate"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="event", 15 | name="actor_id", 16 | field=models.IntegerField(blank=True, null=True, verbose_name="Actor ID"), 17 | ), 18 | migrations.AlterField( 19 | model_name="event", 20 | name="event_object_id", 21 | field=models.IntegerField(blank=True, null=True, verbose_name="Object ID"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /questions/migrations/0005_alter_question_timestamps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-01 21:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("questions", "0004_add_verbose_names"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="question", 15 | name="created", 16 | field=models.DateTimeField(auto_now_add=True, verbose_name="Date de création"), 17 | ), 18 | migrations.AlterField( 19 | model_name="question", 20 | name="updated", 21 | field=models.DateTimeField(auto_now=True, verbose_name="Date de dernière modification"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | DEBUG=True # False for prod 2 | 3 | SECRET_KEY=yourappsecret 4 | 5 | # DATABASE_URL="sqlite:///db.sqlite3" 6 | DATABASE_URL = "postgres://quiz_anthropocene_team:password@localhost:/quiz_anthropocene" 7 | 8 | # Security measures 9 | SESSION_COOKIE_SECURE = False # True in prod 10 | CSRF_COOKIE_SECURE = False # True in prod 11 | SECURE_HSTS_SECONDS = 0 # should be more than 31556952 (one year) in prod 12 | SECURE_SSL_REDIRECT = False # True in prod 13 | 14 | # Github API 15 | GITHUB_ACCESS_TOKEN = "" 16 | 17 | # Notion.so API 18 | NOTION_API_SECRET = "" 19 | NOTION_QUESTION_TABLE_ID = "" 20 | NOTION_CONTRIBUTION_TABLE_ID = "" 21 | IMPORT_DATA_FROM_NOTION = False 22 | 23 | # Sendinblue API 24 | SIB_API_KEY = "" 25 | SIB_NEWSLETTER_LIST_ID= 26 | SIB_NEWSLETTER_DOI_TEMPLATE_ID= 27 | -------------------------------------------------------------------------------- /api/quizs/filters.py: -------------------------------------------------------------------------------- 1 | import django_filters 2 | from django.utils.translation import gettext_lazy as _ 3 | 4 | from core import constants 5 | from tags.models import Tag 6 | from users.models import User 7 | 8 | 9 | class QuizFilter(django_filters.FilterSet): 10 | language = django_filters.MultipleChoiceFilter(label=_("Language(s)"), choices=constants.LANGUAGE_CHOICES) 11 | tags = django_filters.ModelMultipleChoiceFilter( 12 | label=_("Tag(s)"), 13 | queryset=Tag.objects.all(), 14 | ) 15 | authors = django_filters.ModelMultipleChoiceFilter( 16 | label=_("Author(s)"), 17 | queryset=User.objects.all_contributors(), 18 | ) 19 | spotlight = django_filters.BooleanFilter() 20 | # TODO: QuizFullSerializer, QuizWithQuestionOrderSerializer 21 | -------------------------------------------------------------------------------- /glossary/migrations/0003_alter_glossaryitem_timestamps.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-01 21:09 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("glossary", "0002_add_verbose_names"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="glossaryitem", 15 | name="created", 16 | field=models.DateTimeField(auto_now_add=True, verbose_name="Date de création"), 17 | ), 18 | migrations.AlterField( 19 | model_name="glossaryitem", 20 | name="updated", 21 | field=models.DateTimeField(auto_now=True, verbose_name="Date de dernière modification"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /users/migrations/0010_user_profile_home_last_seen_date.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.5 on 2023-09-24 12:17 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("users", "0009_user_logs"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="user", 14 | name="profile_home_last_seen_date", 15 | field=models.DateTimeField(blank=True, null=True, verbose_name="Last seen date on page 'My space'"), 16 | ), 17 | migrations.AlterField( 18 | model_name="user", 19 | name="logs", 20 | field=models.JSONField(default=list, editable=False, verbose_name="Historical logs"), 21 | ), 22 | ] 23 | -------------------------------------------------------------------------------- /glossary/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from glossary.models import GlossaryItem 4 | 5 | 6 | GLOSSARY_ITEM_FORM_FIELDS = [ 7 | field.name for field in GlossaryItem._meta.fields if field.name not in GlossaryItem.GLOSSARY_ITEM_READONLY_FIELDS 8 | ] 9 | 10 | 11 | class GlossaryItemCreateForm(forms.ModelForm): 12 | class Meta: 13 | model = GlossaryItem 14 | fields = GLOSSARY_ITEM_FORM_FIELDS 15 | widgets = { 16 | "name_alternatives": forms.Textarea(attrs={"rows": 1}), 17 | "description": forms.Textarea(attrs={"rows": 3}), 18 | } 19 | 20 | 21 | class GlossaryItemEditForm(GlossaryItemCreateForm): 22 | def __init__(self, *args, **kwargs): 23 | super().__init__(*args, **kwargs) 24 | self.fields["name"].disabled = True 25 | -------------------------------------------------------------------------------- /quizs/migrations/0015_quiz_publish_date.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-07-21 10:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("quizs", "0014_alter_historicalquiz_language_alter_quiz_language"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="historicalquiz", 15 | name="publish_date", 16 | field=models.DateTimeField(blank=True, null=True, verbose_name="Date de publication"), 17 | ), 18 | migrations.AddField( 19 | model_name="quiz", 20 | name="publish_date", 21 | field=models.DateTimeField(blank=True, null=True, verbose_name="Date de publication"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /questions/migrations/0015_question_validation_date.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-07-21 10:42 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("questions", "0014_alter_historicalquestion_language_and_more"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="historicalquestion", 15 | name="validation_date", 16 | field=models.DateTimeField(blank=True, null=True, verbose_name="Date de validation"), 17 | ), 18 | migrations.AddField( 19 | model_name="question", 20 | name="validation_date", 21 | field=models.DateTimeField(blank=True, null=True, verbose_name="Date de validation"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /tags/filters.py: -------------------------------------------------------------------------------- 1 | import django_filters 2 | from django import forms 3 | from django.utils.translation import gettext_lazy as _ 4 | 5 | from tags.models import Tag 6 | 7 | 8 | TEXT_SEARCH_PLACEHOLDER = f"{_('In the following fields:')} " f"{Tag._meta.get_field('name').verbose_name}" 9 | 10 | 11 | class TagFilter(django_filters.FilterSet): 12 | q = django_filters.CharFilter( 13 | label=_("Text search"), 14 | method="text_search", 15 | widget=forms.TextInput(attrs={"placeholder": TEXT_SEARCH_PLACEHOLDER}), 16 | ) 17 | 18 | class Meta: 19 | model = Tag 20 | fields = ["q"] 21 | 22 | def text_search(self, queryset, name, value): 23 | if not value: 24 | return queryset 25 | # normal name filtering 26 | return queryset.filter(name__icontains=value) 27 | -------------------------------------------------------------------------------- /contributions/migrations/0007_contribution_parent.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-05-22 17:33 2 | 3 | import django.db.models.deletion 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("contributions", "0006_contribution_status_and_type"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="contribution", 16 | name="parent", 17 | field=models.ForeignKey( 18 | blank=True, 19 | null=True, 20 | on_delete=django.db.models.deletion.CASCADE, 21 | related_name="replies", 22 | to="contributions.contribution", 23 | verbose_name="En réponse à", 24 | ), 25 | ), 26 | ] 27 | -------------------------------------------------------------------------------- /quizs/migrations/0013_historicalquiz_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-05-26 14:38 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("quizs", "0012_alter_historicalquiz_options_and_more"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="historicalquiz", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Champs modifiés", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /quizs/migrations/0028_alter_historicalquiz_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.5 on 2023-02-23 09:36 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("quizs", "0027_quiz_visibility_translation_fix"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="historicalquiz", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Changed fields", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /glossary/migrations/0006_historicalglossaryitem_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-05-26 13:57 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("glossary", "0005_historicalglossaryitem"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="historicalglossaryitem", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Champs modifiés", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /quizs/migrations/0020_remove_historicalquiz_author_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-09-24 16:25 2 | 3 | from django.db import migrations 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("quizs", "0019_forward_data_author_to_authors"), 10 | ] 11 | 12 | operations = [ 13 | migrations.RemoveField( 14 | model_name="historicalquiz", 15 | name="author", 16 | ), 17 | migrations.RemoveField( 18 | model_name="historicalquiz", 19 | name="author_string", 20 | ), 21 | migrations.RemoveField( 22 | model_name="quiz", 23 | name="author", 24 | ), 25 | migrations.RemoveField( 26 | model_name="quiz", 27 | name="author_string", 28 | ), 29 | ] 30 | -------------------------------------------------------------------------------- /questions/migrations/0013_historicalquestion_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1a1 on 2022-05-26 14:38 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("questions", "0012_alter_historicalquestion_options_and_more"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AddField( 15 | model_name="historicalquestion", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Champs modifiés", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /questions/migrations/0028_alter_historicalquestion_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.5 on 2023-02-23 09:36 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("questions", "0027_question_visibility_translation_fix"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="historicalquestion", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Changed fields", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /glossary/migrations/0008_alter_historicalglossaryitem_history_changed_fields.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.5 on 2023-02-23 09:36 2 | 3 | import django.contrib.postgres.fields 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("glossary", "0007_alter_glossaryitem_created_and_more"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="historicalglossaryitem", 16 | name="history_changed_fields", 17 | field=django.contrib.postgres.fields.ArrayField( 18 | base_field=models.CharField(max_length=50), 19 | blank=True, 20 | default=list, 21 | size=None, 22 | verbose_name="Changed fields", 23 | ), 24 | ), 25 | ] 26 | -------------------------------------------------------------------------------- /questions/migrations/0016_alter_historicalquestion_created_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-17 14:19 2 | 3 | import django.utils.timezone 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("questions", "0015_question_validation_date"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="historicalquestion", 16 | name="created", 17 | field=models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), 18 | ), 19 | migrations.AlterField( 20 | model_name="question", 21 | name="created", 22 | field=models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /core/migrations/0004_configuration_office_address_and_url.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.2.9 on 2025-03-18 16:41 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | dependencies = [ 8 | ("core", "0003_configuration_helloasso_url"), 9 | ] 10 | 11 | operations = [ 12 | migrations.AddField( 13 | model_name="configuration", 14 | name="office_address", 15 | field=models.CharField(blank=True, help_text="L'adresse du bureau de l'association", max_length=255), 16 | ), 17 | migrations.AddField( 18 | model_name="configuration", 19 | name="office_url", 20 | field=models.URLField( 21 | blank=True, help_text="Le lien vers la page du bureau de l'association", max_length=500 22 | ), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /glossary/filters.py: -------------------------------------------------------------------------------- 1 | import django_filters 2 | from django import forms 3 | from django.utils.translation import gettext_lazy as _ 4 | 5 | from glossary.models import GlossaryItem 6 | 7 | 8 | TEXT_SEARCH_PLACEHOLDER = f"{_('In the following fields:')} " f"{GlossaryItem._meta.get_field('name').verbose_name}" 9 | 10 | 11 | class GlossaryItemFilter(django_filters.FilterSet): 12 | q = django_filters.CharFilter( 13 | label=_("Text search"), 14 | method="text_search", 15 | widget=forms.TextInput(attrs={"placeholder": TEXT_SEARCH_PLACEHOLDER}), 16 | ) 17 | 18 | class Meta: 19 | model = GlossaryItem 20 | fields = ["language", "q"] 21 | 22 | def text_search(self, queryset, name, value): 23 | if not value: 24 | return queryset 25 | # normal name filtering 26 | return queryset.filter(name__icontains=value) 27 | -------------------------------------------------------------------------------- /glossary/migrations/0007_alter_glossaryitem_created_and_more.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1 on 2022-08-17 14:19 2 | 3 | import django.utils.timezone 4 | from django.db import migrations, models 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ("glossary", "0006_historicalglossaryitem_history_changed_fields"), 11 | ] 12 | 13 | operations = [ 14 | migrations.AlterField( 15 | model_name="glossaryitem", 16 | name="created", 17 | field=models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), 18 | ), 19 | migrations.AlterField( 20 | model_name="historicalglossaryitem", 21 | name="created", 22 | field=models.DateTimeField(default=django.utils.timezone.now, verbose_name="Date de création"), 23 | ), 24 | ] 25 | -------------------------------------------------------------------------------- /stats/migrations/0004_dailystat_question_public_and_quiz_public_answer_count.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.4 on 2022-05-11 21:12 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("stats", "0003_quizanswerevent_question_answer_split"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name="dailystat", 15 | name="question_public_answer_count", 16 | field=models.PositiveIntegerField(default=0, help_text="Le nombre de questions publiques répondues"), 17 | ), 18 | migrations.AddField( 19 | model_name="dailystat", 20 | name="quiz_public_answer_count", 21 | field=models.PositiveIntegerField(default=0, help_text="Le nombre de quizs publiques répondus"), 22 | ), 23 | ] 24 | -------------------------------------------------------------------------------- /templates/includes/_language_form.html: -------------------------------------------------------------------------------- 1 | {% load i18n get_language_flag %} 2 | 3 | {% get_current_language as LANGUAGE_CODE %} 4 | {% get_available_languages as LANGUAGES %} 5 | {% get_language_info_list for LANGUAGES as languages %} 6 | 7 | {% if languages|length > 1 %} 8 | 20 | {% endif %} 21 | -------------------------------------------------------------------------------- /contributions/migrations/0014_comment_remove_status_replied.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.1.5 on 2023-03-21 15:26 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ("contributions", "0013_comment_meta_and_rename_fks"), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name="comment", 15 | name="status", 16 | field=models.CharField( 17 | blank=True, 18 | choices=[ 19 | ("NEW", "To process"), 20 | ("PENDING", "In progress"), 21 | ("PROCESSED", "Processed"), 22 | ("IGNORED", "Ignored"), 23 | ], 24 | max_length=150, 25 | verbose_name="Status", 26 | ), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /quizs/migrations/0002_quiz_author_link.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 4.0.3 on 2022-04-16 09:19 2 | 3 | import django.db.models.deletion 4 | from django.conf import settings 5 | from django.db import migrations, models 6 | 7 | 8 | class Migration(migrations.Migration): 9 | 10 | dependencies = [ 11 | migrations.swappable_dependency(settings.AUTH_USER_MODEL), 12 | ("quizs", "0001_initial"), 13 | ] 14 | 15 | operations = [ 16 | migrations.AddField( 17 | model_name="quiz", 18 | name="author_link", 19 | field=models.ForeignKey( 20 | help_text="L'auteur du quiz", 21 | blank=True, 22 | null=True, 23 | on_delete=django.db.models.deletion.SET_NULL, 24 | related_name="quizs", 25 | to=settings.AUTH_USER_MODEL, 26 | ), 27 | ), 28 | ] 29 | -------------------------------------------------------------------------------- /stats/urls.py: -------------------------------------------------------------------------------- 1 | from rest_framework import routers 2 | 3 | from stats.views import ( 4 | LinkClickEventViewSet, 5 | QuestionAnswerEventViewSet, 6 | QuestionFeedbackEventViewSet, 7 | QuizAnswerEventViewSet, 8 | QuizFeedbackEventViewSet, 9 | ) 10 | 11 | 12 | app_name = "stats" 13 | 14 | router = routers.DefaultRouter() 15 | router.register(r"question-answer-event", QuestionAnswerEventViewSet, basename="question-answer-event") 16 | router.register(r"question-feedback-event", QuestionFeedbackEventViewSet, basename="question-feedback-event") 17 | router.register(r"quiz-answer-event", QuizAnswerEventViewSet, basename="quiz-answer-event") 18 | router.register(r"quiz-feedback-event", QuizFeedbackEventViewSet, basename="quiz-feedback-event") 19 | router.register(r"link-click-event", LinkClickEventViewSet, basename="link-click-event") 20 | 21 | urlpatterns = [] 22 | 23 | urlpatterns += router.urls 24 | -------------------------------------------------------------------------------- /templates/includes/_paginator.html: -------------------------------------------------------------------------------- 1 | {% load i18n %} 2 | 3 || {% translate "Field" %} | 12 |{% translate "Value" %} | 13 |
|---|---|
| {% get_verbose_name tag field %} | 19 |{{ tag_dict|get_obj_attr:field|default:"" }} | 20 |
| {% translate "Field" %} | 12 |{% translate "Value" %} | 13 |
|---|---|
| {% get_verbose_name category field %} | 19 |{{ category_dict|get_obj_attr:field|default:"" }} | 20 |
| ID | 12 |{% translate "Quiz" %} | 13 |{% translate "Tags" %} | 14 |
|---|---|---|
| 20 | {{ quiz.id }} 21 | | 22 |{{ quiz.name }} | 23 |24 | {% include "tags/_badge_list.html" with tag_list=quiz.tags.all %} 25 | | 26 |
Indiquez votre adresse e-mail ci-dessous, et nous vous enverrons un e-mail pour le réinitialiser.
13 | 14 | 37 |12 | Si un compte existe, vous recevrez un e-mail de réinitialisation 13 | {% if request.GET.email %} 14 | 15 | à l'adresse email : {{ request.GET.email }} 16 | {% endif %} 17 |
18 |Il contient les instructions pour réinitialiser votre mot de passe.
21 |Si vous le ne recevez pas dans les minutes qui suivent :
22 |21 | {% include "includes/_filter_badge_list.html" with search_filters=search_filters model_name="Comment" %} 22 |
23 | {% endif %} 24 | 25 | 31 | 32 |