1

I use MultipleChoiceField in my form. I want to add all selected values to database, but next code which I use add only last value which user select. I tried in my view create multiple number objects. Where I did mistake?

models.py:

class Requirement(models.Model):
    code = models.UUIDField(_('Code'), primary_key=True, default=uuid.uuid4, editable=False)
    symbol = models.CharField(_('Symbol'), max_length=250)
    name = models.CharField(_('Name'), max_length=250)

forms.py:

class AddForm(forms.ModelForm):
    symbol= forms.MultipleChoiceField(required=False, widget=forms.CheckboxSelectMultiple, choices=REQUIREMENTS_CHOICES,)

    class Meta:
        model = Requirement
        fields = ('symbol',)


REQUIREMENTS_CHOICES = (
    ('A', 'Name A'),
    ('B', 'Name B'),
    ('C', 'Name C'),
)

views.py:

def requirement_add(request):
    data = dict()
    if request.method == 'POST':
        form = AddForm(request.POST)
        if form.is_valid():
            list = dict(REQUIREMENTS_CHOICES) # {'C': 'Name C', 'A': 'Name A', 'B': 'Name B'}
            symbols = form.cleaned_data.get('symbol') # ['A', 'B', 'C']
            requirement = form.save(commit=False)
            for symbol in symbols:
                requirement.symbol = symbol
                requirement.name = list[symbol]
                requirement.save()
            data['form_is_valid'] = True
            requirements = Requirement.objects.filter()
            context = {requirement': requirement, 'requirements': requirements}
            data['html_requirement'] = render_to_string('project/requirement_list.html', context)
        else:
            data['form_is_valid'] = False
    else:
        form = AddForm()
    context = {'form': form}
    data['html_requirement_form'] = render_to_string('project/requirement_add.html', context, request=request)
    return JsonResponse(data)
Nurzhan Nogerbek
  • 4,806
  • 16
  • 87
  • 193

1 Answers1

1

You should add requirement.pk = None so that every call to save will insert a new row in the database :

for symbol in symbols:
    requirement.symbol = symbol
    requirement.name = group_requirement_list[symbol]
    requirement.pk = None
    requirement.save()

See the documentation here https://docs.djangoproject.com/en/dev/ref/models/instances/#how-django-knows-to-update-vs-insert.

Edit:

Explanation : in the first iteration of this loop requirement.save() will insert a new row in the database as you would expect. But after that requirement will have the primary key of the new row and Django will try to update it instead of creating a new one.

Alternative solution : you could avoid all of this if you put requirement = form.save(commit=False) in the for loop like this :

symbols = form.cleaned_data.get('symbol') # ['A', 'B', 'C']
for symbol in symbols:
    requirement = form.save(commit=False)
    requirement.symbol = symbol
    requirement.name = group_requirement_list[symbol]
    requirement.save()
  • Thank you! `requirement.pk = None` works for me but I dont understand why it works xD Can you explain little bit? As you can see code field is my pk, also I use default=uuid.uuid4. So I thought it will create pk automatically. Also thanks for the link. – Nurzhan Nogerbek Apr 24 '17 at 15:40
  • You're welcome ! I added an explanation and an alternative solution. – Ahmed Cheikh Apr 25 '17 at 10:21