Я новичок в Джанго.Я прошу прощения, если у меня нет особого смысла.У меня есть проект ЕС по созданию инструмента для обучения взрослых педагогов, которые помогают мигрантам и беженцам.Я хотел бы использовать 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'),
]