0

我是 Django 的新手。如果我没有多大意义,我很抱歉。我有一个欧盟项目,旨在为帮助移民和难民的成人教育工作者创建一个调查工具。我想使用 WizardView/SessionView 和 formset 从基于 Max-Neef 的人类需求理论和自决理论的矩阵中回答一组 24 个问题。这个想法是,当用户填充反射字段并将它们保存到调查表中时,Survey 模型将在具有上一个/下一个/保存功能的 WizardView 中一一继承 24 个带有 ForeignKey 的问题。我一直在思考如何保存代码而不是为向导视图创建 24 个表并使用表单集和 form_tools 的混合。

一个人怎么能创造出这样的工具呢?

任何帮助将不胜感激。先感谢您。

我按照网络和付费网站上的几个教程尝试了 ModelForms 和基于类的视图。

模型.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})

表格.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

视图.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

查找.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)

过滤器.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",)

管理员.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}'

网址.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'),
]
4

0 回答 0