锯Meduza Web问卷:初学者分步指南

我叫Egor,我是Leader-ID的全栈开发人员。在本文中,我想分享一个简单的秘诀,用于创建与Meduza相似的漂亮且方便的基于Web的调查表。他知道在回答单个问题后如何显示统计信息,计算总得分,发表评论,上传数据进行分析以及在社交网络上弄不清结果。为此,我选择了Django,DRF,Python和PostgreSQL数据库。



所有细节都在剪裁中。

在看了一个小时的砌体后(不过,这是粘性课程),第一个结果以现成模型的形式出现,十分钟后在Dzhang中进行了描述。

如果您是初学者,建议您阅读Djnago教程,该教程介绍了如何逐步创建调查。在完成DRF教程之后,最终可以深入探讨该主题。

因此,在项目中,我使用了:

  • Django 3.0.3。对于后端;
  • django-rest-framework。创建rest-api;
  • 蟒蛇
  • PostgreSQL作为数据库;
  • 前端-Nuxt.js,Axios,Element-UI。

现在的步骤


pip install Django-安装库。

django-admin startproject核心-创建djang项目。

cd core-转到包含项目的目录。

python manage.py startapp池-添加轮询应用程序。

接下来,我们在民意调查中的models.py中描述模型,并为DRF创建一个序列化器。

class Question(models.Model):
    title = models.CharField(max_length=4096)
    visible = models.BooleanField(default=False)
    max_points = models.FloatField()

    def __str__(self):
           return self.title

class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.DO_NOTHING)
    title = models.CharField(max_length=4096)
    points = models.FloatField()
    lock_other = models.BooleanField(default=False)

    def __str__(self):
        return self.title

class Answer(models.Model):
    user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING)
    question = models.ForeignKey(Question, on_delete=models.DO_NOTHING)
    choice = models.ForeignKey(Choice, on_delete=models.DO_NOTHING)
    created = models.DateTimeField(auto_now_add=True)

    def __str__(self):
        return self.choice.title


代码文字在这里
from rest_framework import serializers
from .models import Answer, Question, Choice


class ChoiceSerializer(serializers.ModelSerializer):
    percent = serializers.SerializerMethodField()

    class Meta:
        model = Choice
        fields = ['pk', 'title', 'points', 'percent', 'lock_other', ]

    def get_percent(self, obj):
        total = Answer.objects.filter(question=obj.question).count()
        current = Answer.objects.filter(question=obj.question, choice=obj).count()
        if total != 0:
            return float(current * 100 / total)
        else:
            return float(0)


class QuestionSerializer(serializers.ModelSerializer):
    choices = ChoiceSerializer(many=True, source='choice_set', )

    class Meta:
        model = Question
        fields = ['pk', 'title', 'choices', 'max_points', ]


class AnswerSerializer(serializers.Serializer):
    answers = serializers.JSONField()

    def validate_answers(self, answers):
        if not answers:
            raise serializers.Validationerror("Answers must be not null.")
        return answers

    def save(self):
        answers = self.data['answers']
        user = self.context.user
        for question_id, in answers:  #     ,    
            question = Question.objects.get(pk=question_id)
            choices = answers[question_id]
            for choice_id in choices:
                choice = Choice.objects.get(pk=choice_id)
                Answer(user=user, question=question, choice=choice).save()
                user.is_answer = True
                user.save()


然后,我们在views.py中编写两个DRF视图,这些视图为所有问题提供选项并接受用户的所有答案。


代码文字在这里
from .serializers import QuestionSerializer, AnswerSerializer
from rest_framework.permissions import IsAuthenticated
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from .models import Question


class GetQuestion(GenericAPIView):
    permission_classes = (IsAuthenticated,)
    serializer_class = QuestionSerializer

    def get(self, request, format=None):
        questions = Question.objects.filter(visible=True, )
        last_point = QuestionSerializer(questions, many=True)
        return Response(last_point.data)


class QuestionAnswer(GenericAPIView):
    permission_classes = (IsAuthenticated,)
    serializer_class = AnswerSerializer

    def post(self, request, format=None):
        answer = AnswerSerializer(data=request.data, context=request)
        if answer.is_valid(raise_exception=True):
            answer.save()
            return Response({'result': 'OK'})


现在,我们在urls.py中描述链接:

urlpatterns = [
    path('', GetQuestion.as_view()),
    path('answer/', QuestionAnswer.as_view()),
]

将模型添加到admin.py:


代码文字在这里
from django.contrib import admin
from .models import Question, Answer, Choice


class QuestionAdmin(admin.ModelAdmin):
    list_display = (
        'title',
        'visible',
        'max_points',
    )


class ChoiceAdmin(admin.ModelAdmin):
    list_display = (
        'title',
        'question',
        'points',
        'lock_other',
    )
    list_filter = ('question',)


class AnswerAdmin(admin.ModelAdmin):
    list_display = (
        'user',
        'question',
        'choice',
    )
    list_filter = ('user',)


admin.site.register(Question, QuestionAdmin)
admin.site.register(Choice, ChoiceAdmin)
admin.site.register(Answer, AnswerAdmin)


下一步是将民意调查应用程序添加到INSTALLED_APPS中的settings.py(在核心目录中)。并执行启动命令:

  • python manage.py makemigrations-为创建的模型创建迁移
  • python manage.py migration-执行向数据库的迁移
  • python manage.py createsuperuser-创建超级用户(管理员)
  • python manage.py runserver-启动服务器

为了计算问题的总分,我们向该方法添加了一个简单的计算功能,根据该功能可以计算出分数。我不会发布功能代码,因为它可用于破解我们的问卷。现在,每个答案都有自己的“权重”。

我们使用控制台中提供的链接通过浏览器转到管理面板(默认为http://127.0.0.1:8000 / admin),并为其创建问题和解答,并写下要点。



对于我来说,重要的是向我们的合作伙伴提供完成调查的人员名单及其答案。但是为此,仅将答案与问题联系在一起是不够的。因此,我添加了另一个表-“选项”。因此,用户的问题答案与几个答案选项之间形成了联系。这使我们能够以合作伙伴可以轻松解释的形式上载数据。

结果,数据库结构如下所示:


现在连接前面。

在其中,我们删除了问题和答案的列表,将每个元素都进行到最后。根据问题的类型,我们使用自己的逻辑和样式来更改组件。因此,当列表中没有剩余问题时,我们将结果发送到背面,并获得包含分数的答案。收到分数后,我们打开结果页面,如果有分数,我们不再显示问题。

在这个阶段,我们已经准备好一份问卷,可以做它需要做的所有事情:提问,接收和收集答案,以要点和评论的形式给出结果。

加面包


首先,我需要定期上传数据。为此,我刚刚添加了管理命令。

其次,最好在社交网络中实现调查结果的共享。好。锯切功能可让您与VKontakte和Facebook点共享图片。

我们生成了一百种不同的图片,分别反映了VK和Facebook的点(不同的分辨率)。现在,我们将链接的传输连接到前端部分的社交组件中的图片。使用VKontakte,一切变得很简单:我们将带有直接URL的image参数传递给所需的参数。但是我不得不修补Facebook。原来,他们不接受API的媒体,如果我从图片的URL传输图片或图片,则帖子中会显示一个大的空白字段。后来证明,他从网站本身的metainf(图片:image)中拍摄了一张自己共享的照片(我们在链接中传递了参数u)。除其他事项外,她还必须动态更改。我不想进行不必要的重定向,也不想在后面进行操作,所以我决定在前面将SPA(单页应用)转换为SSR(服务器端渲染),因此,根据要求,在浏览器中启动JavaScript之前,带有元元得分的图像的URL会发生变化。幸运的是,以Nuxt.js框架为基础,可以简单地通过切换模式来完成此操作。现在剩下的工作就是草绘仅用于客户端的标签,并添加用于从查询得分的出现改变头部的逻辑。



此外,在服务器上,有必要启动守护程序服务以提供生成的页面,并将静态变量也留给nginx。全部赢利!



我们恢复问卷


为了在填写调查过程中保持参与者的兴趣水平,我为每个问题添加了动态的统计显示。回答问题后,用户可以看到其他人如何回答。有时一个人不清楚为什么要问这些问题。因此,我用有趣的解释补充了每个问题。好吧,振兴我的问卷的最重要的窍门是由我们公司的设计师执行的。



摘要


这样的媒体调查非常容易实施,最重要的是,用户非常喜欢它们。它们可以在尾部和鬃毛中使用:用于社会学研究,告知/测试知识或在站点和服务上创建交互式元素。我试图详细描述它们的创建过程,但是如果您有任何疑问,欢迎发表评论。调查在此引擎的例子可以在这两个链接查看:healthcare.leader-id.rucovid.leader-id.ru

All Articles