From be447f48625ac54cf1dcd4697fdc74c8bc2d6128 Mon Sep 17 00:00:00 2001 From: Holger Sielaff Date: Tue, 10 Sep 2024 12:32:53 +0200 Subject: [PATCH] ... --- content/admin.py | 28 ++++++++++++- content/models.py | 49 ++++++++++++++++++++++- content/templates/questions.html | 1 + content/templates/submit-question.html | 50 ++++++++++++++++++++++++ content/urls.py | 1 + content/views/public.py | 54 ++++++++++++++++++++++++-- requirements.txt | 1 + tablequizwiki/settings.py | 1 + templates/base.html | 1 + 9 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 content/templates/submit-question.html diff --git a/content/admin.py b/content/admin.py index 1d459b6..61995d2 100644 --- a/content/admin.py +++ b/content/admin.py @@ -1,11 +1,32 @@ from django.contrib import admin from django.utils.safestring import mark_safe -from content.models import Link, MediaFile, Question, QuestionVersion, Level, Label, SharedQuestion +from content.models import Link, MediaFile, Question, QuestionVersion, Level, Label, SharedQuestion, SubmittedQuestion from lib.mixins import PermissionsAdminMixin from lib.utils import color_label +class ActiveFilter(admin.SimpleListFilter): + title = "Aktiv/Inaktiv" + parameter_name = 'released' + + def lookups(self, request, model_admin): + return [ + (1, 'Inaktiv'), + (0, 'Aktiv') + ] + + def queryset(self, request, queryset): + v = int(self.value() or -1) + if v == 1: + return queryset.filter(**{self.parameter_name: True}) + elif v == 0: + return queryset.filter(**{self.parameter_name: False}) + else: + return queryset.filter(**{self.parameter_name: False}) + # return queryset + + @admin.register(SharedQuestion) class SharedQuestionAdmin(admin.ModelAdmin): search_fields = ('user__username',) @@ -25,6 +46,11 @@ class LabelAdmin(PermissionsAdminMixin, admin.ModelAdmin): list_editable = ('color',) +@admin.register(SubmittedQuestion) +class SubmittedQuestionAdmin(admin.ModelAdmin): + list_filter = [ActiveFilter,] + + @admin.register(Question) class QuestionAdmin(PermissionsAdminMixin, admin.ModelAdmin): autocomplete_fields = ('medias', 'links', 'labels', 'shares') diff --git a/content/models.py b/content/models.py index 5eade18..f53871a 100644 --- a/content/models.py +++ b/content/models.py @@ -1,11 +1,11 @@ import csv +from datetime import datetime import json import os from colorfield.fields import ColorField from django.contrib.auth.models import User from django.db import models -from django.dispatch import receiver from django.forms.models import model_to_dict from django.utils.safestring import mark_safe from filer.fields.file import FilerFileField @@ -63,10 +63,55 @@ class SharedQuestion(SharedPermissionBase): abstract = False +class SubmittedQuestion(DateAware): + name = models.CharField(max_length=500, unique=True) + buzzword = models.CharField(max_length=25, null=True, blank=True) + question = models.TextField() + awnser = models.TextField() + level = models.ForeignKey(Level, on_delete=models.SET_NULL, null=True, blank=True) + labels = models.ManyToManyField(Label, blank=True) + medias = models.ManyToManyField(MediaFile, blank=True) + links = models.ManyToManyField(Link, blank=True) + shares = models.ManyToManyField(SharedQuestion, blank=True) + + release = models.BooleanField(default=False) + released = models.BooleanField(default=False) + released_at = models.DateTimeField(null=True,blank=True) + + def __str__(self): + return f"{self.name} (#{self.id})" + + +from django.db.models.signals import post_save +from django.dispatch import receiver + + +@receiver(post_save, sender=SubmittedQuestion) +def release_submitted(sender, instance: SubmittedQuestion, **kwargs): + if instance.release: + n = Question.objects.create( + name=instance.name, + buzzword=instance.buzzword, + question=instance.question, + awnser=instance.awnser, + ) + try: + n.labels.set(instance.labels.all()) + n.level_id = instance.level_id + n.save() + except: + n.delete() + raise + instance.released = True + instance.release = False + instance.released_at = datetime.now() + instance.save() + + class Question(DateAware, AuthorAware, PublishedAware, DescriptionAware): name = models.CharField(max_length=500, unique=True, db_index=True) - question = models.TextField(db_index=True) buzzword = models.CharField(max_length=25, null=True, blank=True) + question = models.TextField(db_index=True) awnser = models.TextField(db_index=True) level = models.ForeignKey(Level, on_delete=models.SET_NULL, null=True) labels = models.ManyToManyField(Label, blank=True) diff --git a/content/templates/questions.html b/content/templates/questions.html index 612cbeb..5957eff 100644 --- a/content/templates/questions.html +++ b/content/templates/questions.html @@ -12,6 +12,7 @@ + {# {{ form.captcha }} #} diff --git a/content/templates/submit-question.html b/content/templates/submit-question.html new file mode 100644 index 0000000..e0a22d6 --- /dev/null +++ b/content/templates/submit-question.html @@ -0,0 +1,50 @@ +{% extends 'base.html' %} +{% block content %} + + {% if messages %} + + {% endif %} +
+
+ {% csrf_token %} + {{ form.as_div }} + +
+
+{% endblock %} diff --git a/content/urls.py b/content/urls.py index 861c6f3..4f31ec9 100644 --- a/content/urls.py +++ b/content/urls.py @@ -2,6 +2,7 @@ from django.urls.conf import path from content.views import public urlpatterns = [ + path('add-question/', public.submit_question, name='add-questions'), path('questions/', public.search_question, name='search-questions'), path('questions//csv/', public.as_csv, name='csv-question'), path('', public.search_question, name='search-questions'), diff --git a/content/views/public.py b/content/views/public.py index 386afa1..9325591 100644 --- a/content/views/public.py +++ b/content/views/public.py @@ -1,18 +1,64 @@ +from django import forms from django.http import HttpResponseNotFound, HttpResponse, HttpResponseBadRequest -from django.shortcuts import render +from django.shortcuts import render, redirect +from simplemathcaptcha.fields import MathCaptchaField -from content.models import Question +from content.models import Question, SubmittedQuestion + + +class SearchForm(forms.Form): + term = forms.CharField(max_length=100) + # captcha = MathCaptchaField() + + +class SubmitQuestion(forms.Form): + name = forms.CharField(max_length=500, required=True) + buzzword = forms.CharField(max_length=150, required=False) + question = forms.CharField(max_length=100000, widget=forms.Textarea, required=True) + awnser = forms.CharField(max_length=100000, widget=forms.Textarea, required=True) + captcha = MathCaptchaField() + # level = forms.ForeignKey(Level, on_delete=models.SET_NULL, null=True) + # labels = forms.ManyToManyField(Label, blank=True) + # medias = forms.ManyToManyField(MediaFile, blank=True) + # links = forms.ManyToManyField(Link, blank=True) + # shares = forms.ManyToManyField(SharedQuestion, blank=True) def search_question(request): term = request.GET.get('term') items = [] published = Question.objects.filter(is_published=True) + form = SearchForm(data=request.GET) if term: - items = Question.get_by_tearchterm(term, published) + if form.is_valid(): + items = Question.get_by_tearchterm(term, published) + form.term = term + else: + return redirect('/') else: items = published.all()[:10] - return render(request, 'questions.html', {'items': items}) + return render(request, 'questions.html', {'form': SearchForm(), 'items': items}) + +from django.contrib import messages + +def submit_question(request): + if request.method == 'POST': + form = SubmitQuestion(data=request.POST) + if form.is_valid(): + subq = SubmittedQuestion.objects.create( + name=form.cleaned_data['name'], + buzzword=form.cleaned_data['buzzword'], + question=form.cleaned_data['question'], + awnser=form.cleaned_data['awnser'], + ) + messages.info(request, f"Angelegt mit ID {subq.id}") + return render(request, 'submit-question.html', {'form': SubmitQuestion()}) + else: + [messages.error(request,f'Error in {err}') for err in form.errors] + return render(request, 'submit-question.html', {'form': form}) + else: + form = SubmitQuestion() + return render(request, 'submit-question.html', {'form': form}) def as_csv(request, **kwargs): diff --git a/requirements.txt b/requirements.txt index 7d762c5..71f1c88 100644 --- a/requirements.txt +++ b/requirements.txt @@ -15,4 +15,5 @@ django-jazzmin requests django-rest-swagger drf-yasg +django-simple-math-captcha django-guardian diff --git a/tablequizwiki/settings.py b/tablequizwiki/settings.py index b4a2a68..4360fd6 100644 --- a/tablequizwiki/settings.py +++ b/tablequizwiki/settings.py @@ -41,6 +41,7 @@ INSTALLED_APPS = [ 'colorfield', 'filer', 'rest_framework_swagger', + 'simplemathcaptcha', # 'guardian', 'api', 'content', diff --git a/templates/base.html b/templates/base.html index f6e17f7..c2ff1c0 100644 --- a/templates/base.html +++ b/templates/base.html @@ -35,6 +35,7 @@