Search code examples
djangodjango-modelsdjango-formsmanytomanyfield

Django ValueError when trying to save ManyToMany Values from a Form


I get the error "" needs to have a value for field "dataset" before this many-to-many relationship can be used." when trying to assign values to a ManyToMany field in my views. I've looked at many related questions here on SO that say I must save my Dataset object first. I think I am doing that...what is going wrong?? My database already contains four Subject items.

models.py

class Subject(TimeStampedModel):
    subject_type = models.CharField(max_length=128, blank=False)

    def __unicode__(self):
        return self.subject_type

class Dataset(TimeStampedModel):
    dataset_id = models.CharField(max_length=256)    
    dataset_doi = models.CharField(max_length=15)       
    dataset_name = models.CharField(max_length=256, blank=False)
    dataset_description = models.TextField(blank=False)
    lab = models.CharField(max_length=256, blank=False)
    biological_sample = models.CharField(max_length=256, blank=False)
    subject_type = models.ManyToManyField('Subject', related_name='datasets', blank=True)
    date_collected = models.DateField(blank=True)  

    collection_facility = models.ManyToManyField('CollectionFacility', related_name='datasets', blank=True)
    processing_notes = models.TextField(blank=True)

    release_date = models.DateField()   
    release_asap = models.BooleanField()    
    pdb_code = models.CharField(max_length=256, blank=True)     
    publication_link = models.URLField(blank=True)      

    def create_name(self):
        self.dataset_name = "%s %s" % (self.biological_sample, self.lab)

    def save(self, *args, **kwargs):
        self.dataset_id = self.id

    def __unicode__(self):
        return "%s : %s" % (self.dataset_name, self.dataset_id)

forms.py RegistrationForm:

class RegistrationForm(forms.Form):

    subject_type = forms.ModelMultipleChoiceField(
        label="Subject",
        queryset = Subject.objects.all(),
        widget=forms.CheckboxSelectMultiple(),  
        required = True,
    )

views.py

def create_registration(form):
    dataset = Dataset()
    dataset.DOI = "preUpload"
    dataset.lab = form.cleaned_data['lab']
    dataset.biological_sample = form.cleaned_data['sample']
    dataset.resource_type = form.cleaned_data['dataset_type']
    dataset.dataset_description = form.cleaned_data['dataset_description']

    dataset.date_collected = form.cleaned_data['date_collected']
    dataset.release_date = form.cleaned_data['release_date']
    dataset.release_asap = form.cleaned_data['release_asap']

    if form.cleaned_data['pdb_code']:
        dataset.pdb_code = form.cleaned_data['pdb_code']

    if form.cleaned_data['publication_link']:
        dataset.publication_link = form.cleaned_data['publication_link']

    dataset.create_name()

    dataset.save()    # I don't think this save is working?

    subjects = form.cleaned_data['subject_type']
    dataset.subject_type = [x for x in subjects]

    for facility in form.cleaned_data['facility']
        dataset.collection_facility.add(facility)

    dataset.save()

    return dataset


def registration_submit(request):
    registration_form = RegistrationForm(request.POST)
    if registration_form.is_valid():
        registration = create_registration(registration_form)
.......

Solution

  • You forgot to call the original save() in the overriden Dataset.save() method.

    def save(self, *args, **kwargs):
        self.dataset_id = self.id
        super(Dataset, self).save(*args, **kwargs)