我正在尝试制作一个包含2个字段的表单集,第一个用于文本,第二个用于选择字段。我在主题中遇到错误,不知道如何替换“cleaning_data”。当我通过POST推送数据时出现错误。
错误来自:“proficiency = x.cleaned_data.get('proficiency')” 在意见中。
这是我的代码:
views.py:
@login_required
def skill_settings(request):
"""
Allows a user to update their own profile.
"""
userrr = request.user
#has_skills = Skill.objects.count() > 0
SkillFormSet = formset_factory(SkillForm, formset=BaseSkillFormSet)
user_skills = UserSkill.objects.filter(user=request.user).order_by('skill__name')
skill_data = [{'skill': s.skill, 'proficiency': s.proficiency}
for s in user_skills]
LinkFormSet = formset_factory(LinkForm, formset=BaseLinkFormSet)
user_links = SkillMod.objects.filter(userrr=userrr)
link_data = [{'skil': l.skil}
for l in user_links]
if request.method == 'POST':
skill_formset = SkillFormSet(request.POST, prefix='skill')
link_formset = LinkFormSet(request.POST, prefix='link')
forms = [link_formset, skill_formset]
if link_formset.is_valid():
objj = []
objj2 = []
for link_form in link_formset:
skil = link_form.cleaned_data.get('skil')
objj.append(SkillMod(userrr=userrr, skil=skil))
for x in skill_formset:
proficiency = x.cleaned_data.get('proficiency')
objj2.append(UserSkill(user=request.user, proficiency=proficiency))
try:
with transaction.atomic():
SkillMod.objects.filter(userrr=userrr).delete()
SkillMod.objects.bulk_create(objj)
UserSkill.objects.filter(user=request.user).delete()
UserSkill.objects.bulk_create(objj2)
messages.success(request, 'You have updated your profile.')
except IntegrityError:
messages.error(request, 'There was an error.')
return redirect(reverse('skill_settings'))
else:
skill_formset = SkillFormSet(initial=skill_data, prefix='skill')
link_formset = LinkFormSet(initial=link_data, prefix='link')
context = {
'skill_formset': skill_formset,
'link_formset': link_formset,
#'has_skills': has_skills,
}
return render(request, 'skill_settings.html', context)
models.py:
class Skill(models.Model):
"""
Represents a skill in the community.
"""
name = models.CharField(('name'), max_length=100, unique=True)
owner = models.ManyToManyField(settings.AUTH_USER_MODEL,
through='UserSkill',
verbose_name=('owner'))
class Meta:
verbose_name = ('skill')
verbose_name_plural = ('skills')
def __str__(self):
return self.name
class UserSkill(models.Model):
"""
How proficient an individual user is at a particular skill.
This model joins User and Skill ('through' table).
"""
BEGINNER = 10
INTERMEDIATE = 20
ADVANCED = 30
EXPERT = 40
PROFICIENCY_CHOICES = (
('', '---------'),
(BEGINNER, ('Beginner')),
(INTERMEDIATE, ('Intermediate')),
(ADVANCED, ('Advanced')),
(EXPERT, ('Expert')),
)
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name=("user"))
skill = models.ForeignKey(Skill, verbose_name=('skill'))
proficiency = models.IntegerField(('proficiency'),
choices=PROFICIENCY_CHOICES,
default=BEGINNER)
def get_proficiency_percentage(self):
"""
Return a user's profiency in a particular skill as a percentage,
based on the position of the proficiency in PROFICIENCY_CHOICES.
"""
choice_values = [choice[0] for choice in self.PROFICIENCY_CHOICES]
if '' in choice_values:
choice_values.remove('') # Remove the empty proficiency choice
choice_values.sort() # Ensure values are in the correct order
value = choice_values.index(self.proficiency) + 1
factor = 100 / len(choice_values)
percentage = round(value * factor)
return percentage
class Meta:
verbose_name = ('user skill')
verbose_name_plural = ('user skills')
unique_together = ('user', 'skill')
def __str__(self):
return '{} - {}'.format(self.user.get_full_name(), self.skill.name)
class SkillMod(models.Model):
userrr = models.ForeignKey(settings.AUTH_USER_MODEL,
verbose_name=('userrr'),
related_name='linksss')
skil = models.CharField(max_length=50)
def __str__(self):
return self.skil
def save(self, *args, **kwargs):
"""
Attempt to match a user link to a recognised brand (LinkBrand).
"""
super(SkillMod, self).save(*args, **kwargs)
forms.py:
class SkillForm(forms.Form):
"""
Form for individual user skills
"""
skills = Skill.objects.all()
skill = forms.ModelChoiceField(queryset=skills, required=False)
proficiency = forms.ChoiceField(choices=UserSkill.PROFICIENCY_CHOICES,
required=False)
class LinkForm(forms.Form):
skil = forms.CharField(
max_length= 50,
widget = forms.TextInput(attrs = {'placeholder': 'Skill',}), required = False)
skill_settings.html:
{% block profile %}
<p></p>
<div class="jumbotron">
{% if messages %}
{% for message in messages %}
<p>{{ message }}</p>
{% endfor %}
{% endif %}
<form method="post">
{% csrf_token %}
{{ link_formset.management_form }}
{{ skill_formset.management_form }}
{{ form.management_form }}
<div class="link-formset">
<div style="border-style:groove; border-radius: 8px; padding: 12px 0 0 7px;">
{% for link_form in link_formset %}
<p style="font-size:15px">Firma:
{{ link_form.skil }}
{% if link_form.skil.errors %}
{% for error in link_form.skil.errors %}
{{ error|escape }}
{% endfor %}
{% endif %}</p>
{% endfor %}
{% for form in skill_formset %}
{{ form.proficiency }}
{% endfor %}
</div>
</div>
{% if skill_formset.non_form_errors %}
<div>
<span class="form-error">
{% for error in skill_formset.non_form_errors %}
<span><i class="fa fa-exclamation-triangle"></i>{{ error|escape }}</span>
{% endfor %}
</span>
</div>
{% endif %}
{% if link_formset.non_form_errors %}
{% for error in link_formset.non_form_errors %}
{{ error|escape }}
{% endfor %}
{% endif %}
<input type="submit" value="Update Profile" class="button"/>
</form>
<!-- Include formset plugin - including jQuery dependency -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
<script src="{% static 'js/jquery.formset.js' %}"></script>
<script>
$('.link-formset').formset({
addText: 'add next',
deleteText: 'remove'
});
</script>
</div>
{% endblock %}
答案 0 :(得分:1)
cleaned_data
仅在使用is_valid()
验证表单后才可用。您目前只验证link_formset
,但之后尝试访问尚未创建的cleaned_data
x in skill_formset
。
在此处详细了解:https://docs.djangoproject.com/en/1.9/ref/forms/api/#django.forms.Form.cleaned_data