Автосохранение пользователя во встроенных наборах форм Django с представлениями на основе классов и четкими формами - PullRequest
0 голосов
/ 28 июня 2019

Я использую встроенные наборы форм Django с представлениями на основе классов и четкими формами.В настоящее время в моем проекте есть требование, согласно которому пользователь может отправить запрос на новую концепцию обучения, а любой пользователь в приложении может предоставить комментарии и поделиться своим мнением о концепции исследования.Когда пользователь вводит свои комментарии и отправляет форму, я хочу автоматически сохранить пользователя, вошедшего в систему, в поле пользователя.

Например, пользователь А создал новую концепцию исследования и предоставил комментарий (пожалуйста,утвердить мой запрос) при создании нового запроса.Затем для приведенного выше комментария пользователь А должен быть сохранен.

Позже приходит пользователь Б, редактирует этот запрос и комментирует «Запрос выглядит хорошо для меня» и обновляет форму.Теперь пользователь B должен быть автоматически сохранен для этого комментария.

Это новое требование для проекта.Я пробовал различные решения, доступные для переполнения стека, но мне пока не удалось.Вы можете проверить в моем коде то, что я сейчас пытаюсь достичь.

Пожалуйста, найдите мой код ниже:

models.py:

class StudyRequestConcept(models.Model):
    CHOICES = (
        ('Yes', 'Yes'),
        ('No', 'No'),
    )

    REQUEST_STATUS = (
        ('Pending', 'Pending'),
        ('Approved', 'Approved'),
        ('Denied', 'Denied'),
    )

    APPROVER_CHOICES = (
        ('Amey Kelekar', 'Amey Kelekar'),
    )

    requestor_name = models.CharField(max_length=240, blank=False, null=False)
    project = models.CharField(max_length=240, blank=False, null=False)
    date_of_request = models.DateField(blank=False, null=False)
    brief_summary = models.CharField(max_length=4000, blank=False, null=False)
    scientific_question = models.CharField(max_length=2000, blank=False, null=False)
    strategic_fit = models.CharField(max_length=2000, blank=False, null=False)
    collaborators = models.CharField(max_length=1000, blank=False, null=False)
    risk_assessment = models.CharField(max_length=2000, blank=False, null=False)
    devices = models.CharField(max_length=1000, blank=False, null=False)
    statistics = models.CharField(max_length=2000, blank=False, null=False)
    personnel = models.CharField(max_length=1000, blank=False, null=False)
    sample_size = models.PositiveIntegerField(blank=False, null=False, default=0)
    population = models.CharField(max_length=2000, blank=False, null=False)
    dmti_study_start_date = models.DateField(blank=False, null=False)
    duration = models.PositiveIntegerField(blank=False, null=False, default=0)
    decision_date = models.DateField(blank=False, null=False)
    deliverables = models.CharField(max_length=4000, blank=False, null=False)
    logistics_flag = models.CharField(max_length=3, choices=CHOICES, default='No')

    status = models.CharField(max_length=20, choices=REQUEST_STATUS, default='Pending')
    approver_date = models.DateField(blank=True, null=True)
    approver_name = models.CharField(max_length=240, choices=APPROVER_CHOICES, blank=True, null=True)

    user = models.ForeignKey(User, on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

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

    def get_commentsStudyRequestConcept(self):
        return ','.join([str(i) for i in self.commentsStudyRequestConcept.all().values_list('id', flat=True)])


class CommentsStudyRequestConcept(models.Model):
    """
    A Class for Study Request Concept Comments.
    """
    comments = models.CharField('Comment', max_length=2000, blank=True, null=True)
    commented_on = models.DateTimeField(default=timezone.now)
    user = models.ForeignKey(User, on_delete=models.CASCADE)
    studyRequestConcept = models.ForeignKey(StudyRequestConcept, related_name='commentsStudyRequestConcept', on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

forms.py:

class StudyRequestConceptForm(forms.ModelForm):
    requestor_name = forms.CharField(label=mark_safe('<b>Name of Requestor</b>'))
    project = forms.CharField(label=mark_safe('<b>On behalf of which project or platform</b> <br/>  <i>(What is the portfolio project / asset team / RU which will benefit from this study? At what development stage is it?)</i>'))
    date_of_request = forms.DateField(label=mark_safe('<b>Date of Request</b>'), 
        input_formats=['%Y-%m-%d'],
        widget=XDSoftDateTimePickerInput()
    )
    brief_summary = forms.CharField(label=mark_safe('<b>Brief Summary of Project</b>'))
    scientific_question = forms.CharField(label=mark_safe('<b>Scientific Question</b> <br/><i>(What is the question you would like answered? What is the challenge we are trying to address?)</i>'))
    strategic_fit = forms.CharField(label=mark_safe('<b>Strategic Fit / Impact Statement </b><br/><i>(What is the rationale for this study? What is the potential value to Pfizer? What asset team would it support, and have you secured endorsement from that asset team?)</i>'))
    collaborators = forms.CharField(label=mark_safe('<b>Potential Collaborators (Internal & External)</b> <br/><i>(Who are the key collaborators required to execute the study?)</i>'))
    risk_assessment = forms.CharField(label=mark_safe('<b>Risk Assessment</b> <br/> <i>(What are the risks you foresee? If so, what is your proposed mitigation plan?)</i>'))
    devices = forms.CharField(label=mark_safe('<b>Devices / imaging modality</b> <br/> <i>(What device(s) will be deployed, if known)</i>'))
    statistics = forms.CharField(label=mark_safe('<b>Statistics</b> <br/><i>(Have you consulted with a statistician? If so, with whom?)</i>'))
    personnel = forms.CharField(label=mark_safe('<b>Anticipated personnel needs</b> <br/> <i>(Technician(s), Data Manager(s), CTS, etc.)</i>'))
    sample_size = forms.IntegerField(label=mark_safe('<b>Anticipated sample size</b>'), min_value=0, max_value=2147483647)
    population = forms.CharField(label=mark_safe('<b>Anticipated study population, or animal model</b><br/><i> (Pfizer internal, healthy, specific disease population…)</i>'))
    dmti_study_start_date = forms.DateField(label=mark_safe('<b>Anticipated DMTI study start date</b>'), 
        input_formats=['%Y-%m-%d'],
        widget=XDSoftDateTimePickerInput()
    )
    duration = forms.IntegerField(label=mark_safe('<b>Estimated study duration (months)</b>'), min_value=0, max_value=2147483647)
    decision_date = forms.DateField(label=mark_safe('<b>Anticipated Asset Team study start date (or asset decision date)</b><br/><i> (For decision making to inform internal phased study design</i>'), 
        input_formats=['%Y-%m-%d'],
        widget=XDSoftDateTimePickerInput()
    )
    deliverables = forms.CharField(label=mark_safe('<b>Expected deliverables</b><br/><i> (Device selection & validation, algorithm developed to qualify…)</i>'))
    source = forms.CharField(max_length=50, widget=forms.HiddenInput(), required=False)

    def clean(self):
        requestor_name = self.cleaned_data.get('requestor_name')
        project = self.cleaned_data.get('project')
        date_of_request = self.cleaned_data.get('date_of_request')
        brief_summary = self.cleaned_data.get('brief_summary')
        scientific_question = self.cleaned_data.get('scientific_question')
        strategic_fit = self.cleaned_data.get('strategic_fit')
        collaborators = self.cleaned_data.get('collaborators')
        risk_assessment = self.cleaned_data.get('risk_assessment')
        devices = self.cleaned_data.get('devices')
        statistics = self.cleaned_data.get('statistics')
        personnel = self.cleaned_data.get('personnel')
        sample_size = self.cleaned_data.get('sample_size')
        population = self.cleaned_data.get('population')
        dmti_study_start_date = self.cleaned_data.get('dmti_study_start_date')
        duration = self.cleaned_data.get('duration')
        decision_date = self.cleaned_data.get('decision_date')
        deliverables = self.cleaned_data.get('deliverables')

        if (dmti_study_start_date not in EMPTY_VALUES) and (dmti_study_start_date < datetime.date.today()):
            self._errors['dmti_study_start_date'] = self.error_class([
                'The date cannot be in the past.'])

        if (dmti_study_start_date not in EMPTY_VALUES) and (decision_date not in EMPTY_VALUES) and (decision_date < dmti_study_start_date):
            self._errors['decision_date'] = self.error_class([
                'The date cannot be earlier Anticipated DMTI study start date.'])

        return self.cleaned_data

    class Meta:
        model = StudyRequestConcept
        exclude = ('user', 'logistics_flag', 'status','approver_date','approver_name')



class CommentsStudyRequestConceptForm(forms.ModelForm):
    comments = forms.CharField(label='Comments',
                                    widget=forms.TextInput(attrs={
                                        'class': 'form-control',
                                    }))


    def clean(self):
        comments = self.cleaned_data.get('comments')

    class Meta:
        model = CommentsStudyRequestConcept
        exclude = ('commented_on', 'user')

CommentsStudyRequestConceptFormset = inlineformset_factory(StudyRequestConcept, CommentsStudyRequestConcept, form=CommentsStudyRequestConceptForm, extra=1)

views.py:

class StudyRequestConceptCreate(CreateView):
    model = StudyRequestConcept
    form_class = StudyRequestConceptForm


class StudyRequestConceptFormsetCreate(CreateView):
    model = StudyRequestConcept
    template_name = 'createStudyRequestConcept.html'
    form_class = StudyRequestConceptForm
    success_url = reverse_lazy('create_StudyRequestConcept')

    def get_context_data(self, **kwargs):
        data = super(StudyRequestConceptFormsetCreate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['comment'] = CommentsStudyRequestConceptFormset(self.request.POST, prefix='comments')
        else:
            data['comment'] = CommentsStudyRequestConceptFormset(prefix='comments')
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        comment = context['comment']
        with transaction.atomic():
            if comment.is_valid():
                self.object = form.save(commit=False)
                self.object.user = self.request.user
                self.object = form.save()
                comment.instance = self.object
                commentinstance = comment.save(commit=False)
                commentinstance.user = self.request.user
                commentinstance.save()

                messages.success(self.request, StudyRequestConcept.__name__ +' Form ID: '+ str(self.object.id) + ' was submitted successfully')
                return super(StudyRequestConceptFormsetCreate, self).form_valid(form)
            else:
                return self.render_to_response(self.get_context_data(form=form))


class StudyRequestConceptUpdate(UpdateView):
    model = StudyRequestConcept
    form_class = StudyRequestConceptEditForm
    template_name = 'updateStudyRequestConcept.html'
    success_url = '/'


class StudyRequestConceptFormsetUpdate(UpdateView):
    model = StudyRequestConcept
    form_class = StudyRequestConceptEditForm
    template_name = 'updateStudyRequestConcept.html'
    success_url = reverse_lazy('edit_StudyRequestConcept')

    def get_context_data(self, **kwargs):
        data = super(StudyRequestConceptFormsetUpdate, self).get_context_data(**kwargs)
        if self.request.POST:
            data['comment'] = CommentsStudyRequestConceptFormset(self.request.POST, prefix='comments', instance=self.object)
        else:
            data['comment'] = CommentsStudyRequestConceptFormset(prefix='comments', instance=self.object)
        return data

    def form_valid(self, form):
        context = self.get_context_data()
        comment = context['comment'] 

        with transaction.atomic():
            self.object = form.save()

            if comment.is_valid():
                comment.instance = self.object
                commentinstance = comment.save(commit=False)    
                commentinstance.user = self.request.user
                commentinstance.save()


        messages.success(self.request, (StudyRequestConcept.__name__) +' Form ID: '+ str(self.object.id) + ' was updated successfully')
        return super(StudyRequestConceptFormsetUpdate, self).form_valid(form)

Поскольку для поля 'commented_on' по умолчанию используется timezone.now, оно автоматически сохраняет его в таблице.Но это не тот случай с пользователем.

Я получаю ошибку:

IntegrityError в / 1 / updateStudyRequestConcept / RequestPortal_commentsstudyrequestconcept.user_id не может быть NULL

AnyПомощь или совет будут оценены!Я буду более чем рад предоставить любой дополнительный код или необходимую информацию.Заранее благодарим за поддержку и помощь.

С уважением,

Амей Келекар

1 Ответ

0 голосов
/ 03 июля 2019

Я верю, что вместо того, чтобы сказать это как ответ на мой вопрос, я скажу, что это обходной путь.Поскольку мне просто требуется имя человека, написавшего комментарий, я обновил свой models.py, как показано ниже:

class CommentsStudyRequestConcept(models.Model):
    """
    A Class for Study Request Concept Comments.
    """
    comments = models.CharField('Comment', max_length=2000, blank=True, null=True)
    commented_on = models.DateTimeField(default=timezone.now)
    commented_by = models.CharField(max_length=2000, blank=True, null=True)
    studyRequestConcept = models.ForeignKey(StudyRequestConcept, related_name='commentsStudyRequestConcept', on_delete=models.CASCADE)

    def __str__(self):
        return str(self.id)

Я удалил внешний ключ user и заменил его необязательным символьным полемcommented_by.Соответственно, я обновил свой forms.py, как показано ниже:

class CommentsStudyRequestConceptForm(forms.ModelForm):
    comments = forms.CharField(label='Comments',
                                    widget=forms.TextInput(attrs={
                                        'class': 'form-control',
                                    }),
                                    required=False)

    commented_by = forms.CharField(label='Commented By',
                                    widget=forms.TextInput(attrs={
                                        'class': 'form-control',
                                        'readonly': 'readonly'
                                    }),
                                    required=False)
    def clean(self):
        comments = self.cleaned_data.get('comments')
        commented_by = self.cleaned_data.get('commented_by')

    class Meta:
        model = CommentsStudyRequestConcept
        exclude = ('commented_on', )

Я также убедился, что поле commented_by только для чтения.

В моем views.py, как только формадействительно, я обновил таблицу комментариев, как показано ниже:

#While creating a new Study concept
CommentsStudyRequestConcept.objects.filter(studyRequestConcept_id=self.object.id).update(commented_by=self.request.user.first_name + " " + self.request.user.last_name)

#while adding a new comment to the Study concept:
CommentsStudyRequestConcept.objects.filter(studyRequestConcept_id=self.object.id).filter(commented_by__exact='').update(commented_by=self.request.user.first_name + " " + self.request.user.last_name)

Любое лучшее решение приветствуется.Обратите внимание, что в этом решении вы должны указать имя и фамилию при создании порядка пользователей, чтобы эта логика работала без каких-либо проблем.Если вы хотите, вы можете сохранить внешний ключ user вместо commented_by, но сделать его необязательным и использовать ту же логику, что и описанная выше.

С уважением,

Амей Келекар

...