Django 'ModelForm'对象没有M2M的'cleaned_data'属性

时间:2021-09-21 17:18:59

Hi everyone I'm facing issues with create a M2M through.

大家好,我正面临创建M2M的问题。

With the code below, I get the message: 'SendCandForm' object has no attribute 'cleaned_data'

通过下面的代码,我得到消息:'SendCandForm'对象没有属性'cleaned_data'

If I change

如果我改变

#forms.py
cojobs=Company.objects.select_related('job').values_list('job__title', flat=True)

To

#forms.py
cojobs=Company.objects.select_related('job__id').values_list('job__id', flat=True)

And

#views.py
job = form.cleaned_data['job']
status = form.cleaned_data['status']

To

#views.py
job = form.data.get('job')
status = form.data.get('status')

When data exists(), everything goes right. But when it tries to make the post, I get the error:

当数据存在时,一切正常。但当它试图发表文章时,我得到了一个错误:

Cannot assign "u'2'": "CandidateToJob.job" must be a "Job" instance. 

Hope you can help me.

希望你能帮助我。

Here is my code

这是我的代码

#models.py
class Company(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    name = models.CharField(max_length=50)
    ...

class Job(models.Model):
    company = models.ForeignKey(Company)
    candidate = models.ManyToManyField('Candidate', through='CandidateToJob')
    title = models.CharField(max_length=500)
    ...

class Candidate(models.Model):
    user = models.OneToOneField(User, primary_key=True)
    ...

class CandidateToJob(models.Model):
    job = models.ForeignKey(Job, related_name='applied_to')
    candidate = models.ForeignKey(Candidate, related_name='from_user')
    STATUS_CHOICES = (
        ('0', 'New'),
        ('1', 'Not approved'),
        ('2', 'Approved')
     )
    status = models.CharField(max_length=2, choices=STATUS_CHOICES)

The form

表单

#forms.py
class SendCandForm(ModelForm):

    cojobs=Company.objects.select_related('job').values_list('job__title', flat=True)
    cojobs_choices = [('', 'Choose')] + [(id, id) for id in cojobs]

    job = forms.ChoiceField(choices=cojobs_choices ,label="Vaga", required=True, widget=forms.Select(attrs={'class': 'form-control'}))

    STATUS_CHOICES = (
        ('0', 'New'),
        ('1', 'Not approved'),
        ('2', 'Approved')
     )
    status = forms.ChoiceField(required=True, widget=forms.RadioSelect(attrs={'class': ''}), choices=STATUS_CHOICES)

    class Meta:
    model = CandidateToJob
        exclude = ['candidate']

Here is my view

这是我的观点

#views.py
class MyCandidateDetail(SuccessMessageMixin, UpdateView):

    model = Candidate
    template_name = 'dashboard/my-candidate-detail.html'
    form_class = SendCandForm

    def get_context_data(self, **kwargs):
        context = super(MyCandidateDetail, self).get_context_data(**kwargs)
        return context

    def get_initial(self, *args, **kwargs):
        candidate = self.get_object()
        self.initial = {'candidate': candidate}
        return self.initial

    def get_form_kwargs(self, *args, **kwargs):
        kwargs = {'initial': self.get_initial()}
        return kwargs

    def post(self, request, *args, **kwargs):

        form = self.form_class(request.POST)

        #get job and status from form
        job = form.cleaned_data['job']
        status = form.cleaned_data['status']

        #get candidate
        candidate = self.get_object()

        #check if objects exists before save
        if CandidateToJob.objects.filter(job = job, candidate = candidate).exists():

            messages.error(request, 'Error!')

            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

        else:

            if form.is_valid():
                form.save(commit=False)

                #assign to the through table
                candidatetojob = CandidateToJob.objects.create(job=job, candidate=candidate, status=status)

                candidatetojob.save()

                messages.success(request, 'Success!')

            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

2 个解决方案

#1


1  

SOLVED

解决了

I had to change my form from ModelForm to forms.Form

我必须把我的表格从模型变成形式。

Here is the code:

这是代码:

#forms.py
class SendCandForm(forms.Form):

    job = Company.objects.select_related('job').values_list('job__title', flat=True)
    jobs_choices = [('', 'Escolher')] + [(id, id) for id in job]

    job = forms.ChoiceField(choices=jobs_choices, label="Vaga", required=True, widget=forms.Select(attrs={'class': 'form-control'}))

    STATUS_CHOICES = (
        ('0', 'Novo'),
        ('1', 'Não aprovado'),
        ('2', 'Pré Selecionado'),
        ('3', 'Contratado')
    )
    status = forms.ChoiceField(required=True, widget=forms.RadioSelect(attrs={'class': ''}), choices=STATUS_CHOICES)

    def save():
        job = self.cleaned_data['job']
        status = self.cleaned_data['status']
        ctj = CandidateToJob(
            job = job,
            status = status,
            candidate = candidate,
        )
        ctj.save()

        return ctj

And the post function in UpdateView

和UpdateView中的post函数

#views.py
def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)

    if form.is_valid():

        joblist = form.cleaned_data['job']
        job = Job.objects.get(title=joblist)
        status = form.cleaned_data['status']
        candidate=self.get_object()

        if CandidateToJob.objects.filter(job=job, candidate=candidate).exists():
            messages.error(request, 'Ops, este candidato já está na vaga selecionada')
            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

        else:
            candidatetojob = CandidateToJob.objects.create(job=job, candidate=candidate, status=status)
            candidatetojob.save()
            messages.success(request, 'Sucesso! Candidato inserido na Vaga.')

        return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

#2


0  

Solved cleaned_data issue.

cleaned_data解决问题。

Needed to change views.py def post like below code. But still getting error

需要改变的观点。代码如下所示。但仍然错误

Cannot assign "u'2'": "CandidateToJob.job" must be a "Job" instance.

or

Cannot assign "u'title'": "CandidateToJob.job" must be a "Job" instance.

New def post in views.py

新的def post在view .py中

def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)

    if form.is_valid():

        #get job and status from form
        job = Job.objects.get(id=form.cleaned_data['job'])
        status = form.cleaned_data['status']

        #get candidate
        candidate = self.get_object()

        #check if objects exists before save
        if CandidateToJob.objects.filter(job = job, candidate = candidate).exists():

            messages.error(request, 'Ops, este candidato já está na vaga selecionada')

            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

        else:
            form.save(commit=False)

            #assign to the through table
            candidatetojob = CandidateToJob.objects.create(job=job, candidate=candidate, status=status)

            candidatetojob.save()

            messages.success(request, 'Sucesso! Candidato inserido na Vaga.')

        return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

#1


1  

SOLVED

解决了

I had to change my form from ModelForm to forms.Form

我必须把我的表格从模型变成形式。

Here is the code:

这是代码:

#forms.py
class SendCandForm(forms.Form):

    job = Company.objects.select_related('job').values_list('job__title', flat=True)
    jobs_choices = [('', 'Escolher')] + [(id, id) for id in job]

    job = forms.ChoiceField(choices=jobs_choices, label="Vaga", required=True, widget=forms.Select(attrs={'class': 'form-control'}))

    STATUS_CHOICES = (
        ('0', 'Novo'),
        ('1', 'Não aprovado'),
        ('2', 'Pré Selecionado'),
        ('3', 'Contratado')
    )
    status = forms.ChoiceField(required=True, widget=forms.RadioSelect(attrs={'class': ''}), choices=STATUS_CHOICES)

    def save():
        job = self.cleaned_data['job']
        status = self.cleaned_data['status']
        ctj = CandidateToJob(
            job = job,
            status = status,
            candidate = candidate,
        )
        ctj.save()

        return ctj

And the post function in UpdateView

和UpdateView中的post函数

#views.py
def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)

    if form.is_valid():

        joblist = form.cleaned_data['job']
        job = Job.objects.get(title=joblist)
        status = form.cleaned_data['status']
        candidate=self.get_object()

        if CandidateToJob.objects.filter(job=job, candidate=candidate).exists():
            messages.error(request, 'Ops, este candidato já está na vaga selecionada')
            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

        else:
            candidatetojob = CandidateToJob.objects.create(job=job, candidate=candidate, status=status)
            candidatetojob.save()
            messages.success(request, 'Sucesso! Candidato inserido na Vaga.')

        return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

#2


0  

Solved cleaned_data issue.

cleaned_data解决问题。

Needed to change views.py def post like below code. But still getting error

需要改变的观点。代码如下所示。但仍然错误

Cannot assign "u'2'": "CandidateToJob.job" must be a "Job" instance.

or

Cannot assign "u'title'": "CandidateToJob.job" must be a "Job" instance.

New def post in views.py

新的def post在view .py中

def post(self, request, *args, **kwargs):

    form = self.form_class(request.POST)

    if form.is_valid():

        #get job and status from form
        job = Job.objects.get(id=form.cleaned_data['job'])
        status = form.cleaned_data['status']

        #get candidate
        candidate = self.get_object()

        #check if objects exists before save
        if CandidateToJob.objects.filter(job = job, candidate = candidate).exists():

            messages.error(request, 'Ops, este candidato já está na vaga selecionada')

            return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))

        else:
            form.save(commit=False)

            #assign to the through table
            candidatetojob = CandidateToJob.objects.create(job=job, candidate=candidate, status=status)

            candidatetojob.save()

            messages.success(request, 'Sucesso! Candidato inserido na Vaga.')

        return HttpResponseRedirect(reverse('mycandidatedetail', kwargs={'pk': candidate.pk}))