Создание мастера форм / набора форм для ответа на вопросы из таблицы и сохранение их в другой (опрос) - PullRequest
0 голосов
/ 12 февраля 2019

Я новичок в Джанго.Я прошу прощения, если у меня нет особого смысла.У меня есть проект ЕС по созданию инструмента для обучения взрослых педагогов, которые помогают мигрантам и беженцам.Я хотел бы использовать WizardView / SessionView вместе с formset, чтобы ответить на набор из 24 вопросов из матрицы, основанной на теории человеческих потребностей Макса-Нефа и теории самоопределения.Идея состоит в том, что модель опроса будет наследовать 24 вопроса с ForeignKey один за другим в WizardView с функциями «предыдущий / следующий / сохранить», поскольку заполненное пользователем поле отражения сохраняет их в таблицу опроса.Я размышлял, как я могу сохранить код вместо создания 24 таблиц для вида мастера и использовать гибрид форм и set_tools.

Как создать такой инструмент?

Любая помощь будетнаиболее ценится.Заранее спасибо.

Я попробовал ModelForms и представления на основе классов, следуя нескольким учебникам в Интернете и на платных сайтах.

models.py

from django.urls import reverse
from django.db import models
from django.utils import timezone
from django.contrib.auth.models import User
from django.forms import ModelChoiceField


class QuestionChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "Question: {}".format(obj.name)

    def formfield_for_foreignkey(self, question, request, **kwargs):
        if question.name == 'question':
            return QuestionChoiceField(queryset=Question.objects.all())
        return super().formfield_for_foreignkey(question, request, **kwargs)


class Question(models.Model):

    LEVELS = (
        ('Self', 'Relationship with myself'),
        ('Peers', 'Relationship with my peers'),
        ('Learners', 'Relationship with my learners'),
        ('Workplace', 'Relationship with my workplace'),
        ('Society', 'Relationship with my community'),
        ('Planet', 'Relationship with the global society'),
    )

    COMPETENCES = (
        ('Life Internal', 'Life Internal'),
        ('Life External', 'Life External'),
        ('Relatedness', 'Relatedness'),
        ('Autonomy', 'Autonomy'),
    )

    level = models.CharField(max_length=64, choices=LEVELS)
    competence = models.CharField(max_length=64, choices=COMPETENCES)
    question = models.TextField(max_length=400)
    objects = models.Manager()

    class Meta:
        ordering = ['competence']
        verbose_name = "Question"
        verbose_name_plural = "Questions"

    def __str__(self):
        return f'{self.question}'


class Survey(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE,
                                 related_name="surveys", verbose_name="Survey Question:")
    reflection = models.TextField(max_length=400)
    started_at = models.DateTimeField(default=timezone.now)
    is_complete = models.BooleanField(verbose_name="Completed?")
    author = models.ForeignKey(User, related_name="surveys", on_delete=models.CASCADE, verbose_name="Author:")
    objects = models.Manager()

    class Meta:
        ordering = ['author']
        verbose_name = "Survey"
        verbose_name_plural = "Surveys"

    def __str__(self):
        return f'{self.author.username}' ': ''\n' \
            f'{self.question}' '\n' \
            f'{self.reflection}'

    def get_indexed_objects(self):
        return Survey.objects.filter(live=True)

    def save(self, *args, **kwargs):
        super().save(*args, **kwargs)

    def get_absolute_url(self):
        return reverse('Survey-detail', kwargs={'pk': self.pk})

forms.py

from django import forms
from SDAM.models import Survey, Question
from selectable.forms import AutoComboboxSelectWidget
from .lookups import QuestionLookup


class QuestionForm(forms.ModelForm):

    def clean(self):
        super(QuestionForm, self).clean()

    class Meta:
        model = Question
        fields = ['question', 'level', 'competence']
        widgets = {
            'level': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
            'competence': AutoComboboxSelectWidget(lookup_class=QuestionLookup),

        }


class SurveyForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    class Meta:
        model = Survey
        fields = ['question', 'reflection', 'author', 'started_at', 'is_complete']
        widgets = {
            'level': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
            'competence': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
            'question': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
        }

    def clean(self):
        # Super the clean method to maintain main validation and error messages
        super(SurveyForm, self).clean()

        question = self.cleaned_data.get('question')
        author = self.cleaned_data.get('author')
        reflection = self.cleaned_data.get('reflection')
        started_at = self.cleaned_data.get('started_at')
        is_complete = self.cleaned_data.get('is_complete')
        survey = Survey.objects.get(question=question,
                                    reflection=reflection,
                                    author=author, started_at=started_at,
                                    is_complete=is_complete)
        return survey.save()

    def save(self, commit=True):
        instance = super(SurveyForm, self).save(commit=False)

        if commit:
            # save
            instance.save(update_fields=['question', 'reflection', 'author', 'started_at', 'is_complete'])
        return instance

views.py

from django.contrib.auth.mixins import LoginRequiredMixin, UserPassesTestMixin
from django.contrib.auth.models import User
from django.utils import timezone
from django.shortcuts import get_object_or_404, render, reverse
from django.views.generic import (CreateView, DeleteView, DetailView, ListView, UpdateView)
from .filters import SurveyFilter
from .forms import SurveyForm
from .models import Survey


"""
@login_required
def home(request):
    context = {
        'surveys': Survey.objects.all()
    }
    return render(request, 'SDAM/survey.html', context)
"""


class SurveyListView(LoginRequiredMixin, ListView):
    model = Survey
    form_class = SurveyForm
    context_object_name = 'survey_list'
    ordering = ['-started_at']
    template_name = "SDAM/survey_list.html"
    paginate_by = 3

    def get_queryset(self, *args, **kwargs):
            return super().get_queryset()

    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['is_complete'] = True
        context['surveys'] = Survey.objects.all()
        return context


class UserSurveyListView(LoginRequiredMixin, ListView):
    model = Survey
    context_object_name = 'user_surveys'
    template_name = 'SDAM/user_surveys.html'  # <app>/<model>_<viewtype>.html
    paginate_by = 3

    def get_queryset(self):
        author = get_object_or_404(User, username=self.kwargs.get('author'))
        return Survey.objects.filter(author=author, is_complete=True).order_by('-started_at')

    def get_context_data(self, **kwargs):
        context = super(UserSurveyListView, self).get_context_data(**kwargs)
        context['user_surveys'] = Survey.objects.all()
        context['is_complete'] = True
        context['filter'] = SurveyFilter(self.request.GET, queryset=self.queryset())
        return context


class SurveyDetailView(LoginRequiredMixin, DetailView):
    model = Survey
    template_name = "SDAM/survey_detail.html"
    queryset = Survey.objects.all()

    def get_object(self):
        obj = super().get_object()
        # Record the last accessed date
        obj.last_accessed = timezone.now()
        obj.save()
        return obj


class SurveyCreateView(LoginRequiredMixin, CreateView):
    model = Survey
    fields = ['question', 'reflection', 'started_at', 'is_complete']

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)


class SurveyUpdateView(LoginRequiredMixin, UserPassesTestMixin, UpdateView):
    model = Survey
    fields = ['reflection', 'started_at', 'is_complete']
    template_name = "SDAM/survey_update.html"

    def form_valid(self, form):
        form.instance.author = self.request.user
        return super().form_valid(form)

    def test_func(self):
        survey = self.get_object()
        if self.request.user == survey.author:
            return True
        return False


class SurveyDeleteView(LoginRequiredMixin, UserPassesTestMixin, DeleteView):
    model = Survey
    success_url = '/sdam/'

    def test_func(self):
        survey = self.get_object()
        if self.request.user == survey.author:
            return True
        return False

lookups.py

from selectable.base import LookupBase
from selectable.registry import registry
from .models import Survey, Question


class QuestionLookup(LookupBase):
    model = Question
    search_fields = ('level', 'competence', 'question',)

    def get_query(self, request, term):
        data = ['Level', 'Competence', 'Question']
        return [x for x in data if x.startswith(term)]


class SurveyLookup(LookupBase):
    model = Survey
    search_fields = ('question', 'reflection', 'author', 'started_at', 'is_complete',)

    def get_query(self, request, term):
        data = ['Question', 'Reflection', 'Author', 'Started_at', 'Is_complete']
        return [x for x in data if x.startswith(term)]


registry.register(QuestionLookup)
registry.register(SurveyLookup)

filters.py

import django_filters
from .models import Survey, Question


class SurveyFilter(django_filters.FilterSet):

    class Meta:
        model = Survey
        fields = ("question", "reflection", "author", "started_at", "is_complete",)


class QuestionFilter(django_filters.FilterSet):

    class Meta:
        model = Question
        fields = ("competence", "level", "question",)

admin.py

from ckeditor.widgets import CKEditorWidget
from selectable.forms import AutoComboboxSelectWidget, AutoCompleteSelectField, AutoCompleteSelectMultipleWidget
from django.forms import ModelChoiceField
from django.contrib import admin
from django import forms
from SDAM.models import Survey, Question
from .lookups import QuestionLookup, SurveyLookup


class QuestionChoiceField(ModelChoiceField):
    def label_from_instance(self, obj):
        return "Question: {}".format(obj.name)

    def formfield_for_foreignkey(self, question, request, **kwargs):
        if question.name == 'question':
            return QuestionChoiceField(queryset=Question.objects.all())
        return super().formfield_for_foreignkey(question, request, **kwargs)


class QuestionAdminForm(forms.ModelForm):
    question = forms.CharField(widget=CKEditorWidget())

    class Meta:
        model = Question
        fields = ['level', 'competence', 'question']

        widgets = {
            'level': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
            'competence': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
        }


class SurveyAdminForm(forms.ModelForm):
    reflection = forms.CharField(widget=CKEditorWidget())

    class Meta:
        model = Survey
        fields = ['question', 'reflection', 'author', 'started_at', 'is_complete']
        widgets = {
            'question': AutoCompleteSelectField(lookup_class=SurveyLookup),
            'level': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
            'competence': AutoComboboxSelectWidget(lookup_class=QuestionLookup),
        }


@admin.register(Question)
class QuestionAdmin(admin.ModelAdmin):
    list_display = ['question', 'competence', 'level', "id"]
    list_filter = ['competence', 'level']
    fieldsets = [
        ("Question details", {"fields": [
         "competence", "level", "question"]}),
    ]

    def question(self):
        return f'{self.question}'


@admin.register(Survey)
class SurveyAdmin(admin.ModelAdmin):
    list_display = ["author", "question", "reflection", "started_at", "is_complete"]
    list_filter = ["author", "question", "is_complete"]
    fieldsets = [
        ("Reflection Details", {"fields": ["question", "reflection", "author", "started_at", "is_complete"]}),
    ]

    def survey_author(self):
        return f'{self.author.username}'

urls.py

from django.urls import path

from .views import (
    SurveyListView,
    UserSurveyListView,
    SurveyDetailView,
    SurveyCreateView,
    SurveyUpdateView,
    SurveyDeleteView,
)
# from . import views


urlpatterns = [
    path('sdam/', SurveyListView.as_view(), name='Survey-list'),
    path('user/<str:username>', UserSurveyListView.as_view(), name='User-surveys'),
    path('sdam/<int:pk>/', SurveyDetailView.as_view(), name='Survey-detail'),
    path('sdam/new/', SurveyCreateView.as_view(), name='Survey-create'),
    path('sdam/<int:pk>/update/', SurveyUpdateView.as_view(), name='Survey-update'),
    path('sdam/<int:pk>/delete/', SurveyDeleteView.as_view(), name='Survey-delete'),
]
...