2

Dear StackOverflow community. My question is related to the insertion of a new record to the table that contains a many2many fields field.

I spent the entire day trying to resolve this problem by myself, read the django documentation and surfing in stackoverflow.

My models.py :

from django.db import models
from django_extensions.db.models import TimeStampedModel


class clans(TimeStampedModel):
    rfam_acc = models.CharField(max_length=7)
    rfam_id = models.CharField(max_length=40)
    description = models.CharField(max_length=100)
    author = models.CharField(max_length=100)
    comment = models.CharField(max_length=2000, null=True)

    class Meta:
        ordering = ('rfam_id',)

    def __str__(self):
        return self.rfam_id


class families(TimeStampedModel):
    rfam_acc = models.CharField(max_length=7)
    rfam_id = models.CharField(max_length=40)
    description = models.CharField(max_length=75)
    author = models.CharField(max_length=100)
    clan = models.ManyToManyField(clans, null=True, blank=True)
    comment = models.CharField(max_length=2000, null=True)

my script for the data collection (from another database) and insertion in my DB: ( this is run from manage.py shell_plus ).

import mysql.connector
from browse.models import clans, families


def run():

    #... Query from another DB 

    # Query for clans using cursor. assign results to list of lists row_clans
    query_clans = ("SELECT c.clan_acc, c.id, c.description, c.author, c.comment FROM clan c")
    cursor_clans.execute(query_clans)
    row_clans = cursor_clans.fetchall()
# Creation of entry clans in the database.
    for clan in row_clans:
        clap = clans.objects.create(
                rfam_acc=clan[0],
                rfam_id=clan[1],
                description=clan[2],
                author=clan[3],
                comment=clan[4],
                )
# Query for families, that have clan = just created clan. Result in a list of lists row_family.
        query_families = ("SELECT f.rfam_acc, f.rfam_id, f.description, f.author, f.comment, c.id FROM clan_membership cm, family f, clan c WHERE f.rfam_acc = cm.rfam_acc AND cm.clan_acc = c.clan_acc AND c.id =")
        cursor_families.execute(query_families + "\"" + clan[1] + "\"")
        row_family = cursor_families.fetchall()
# Creation of entryes families in the database.
        for family in row_family:
            families.objects.create(
                    rfam_acc=family[0],
                    rfam_id=family[1],
                    description=family[2],
                    author=family[3],
                    comment=family[4],
                    clan=clan[1]
                    )
            print ("insert family ", family[1], " in ", clan[1])

# close the cursors and close the connection to the server
    cursor_clans.close()
    cursor_families.close()
    cnx.close()

And finally the error in the shell:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File         "/Users/work/Desktop/StructuRNA/website/scripts/SQLfromRfamIntoClansFamily.py", line 42, in run
clan=clan[1]
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/manager.py", line 85, in manager_method
return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/query.py", line 397, in create
obj = self.model(**kwargs)
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/base.py", line 550, in __init__
setattr(self, prop, kwargs[prop])
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 499, in __set__
    manager = self.__get__(instance)
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 476, in __get__
return self.related_manager_cls(instance)
  File "/Users/work/Desktop/StructuRNA/.VirEnvStructuRna/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 783, in      __init__
   (instance, self.source_field_name))
 ValueError: "<families: families object>" needs to have a value for field "families" before this many-to-many relationship can be used.

Any help? I can't understand what isn't working.

Another funny thing is that in my database I found an insertion of the first element ( repeated as many times as I tried to run the script). This element has also its correct value for the m2m fields.

Peter
  • 216
  • 1
  • 14

1 Answers1

1

You need to create the instance of the "families" object before you can add an entry to the ManyToManyField

family = families.objects.create(
    rfam_acc=family[0],
    rfam_id=family[1],
    description=family[2],
    author=family[3],
    comment=family[4]
)

family.clan.add(clan[1])

Also, you may be interested in bulk_create: https://docs.djangoproject.com/en/1.10/ref/models/querysets/#bulk-create

Chris
  • 298
  • 4
  • 8
  • Thanks very much. This resolved my problem. But I implemented this quite in a different way. : cl = clans(.....attributes assignation..) cl.save() fa = families(.......attributes assignation..) fa.save() fa.clan.add(cl) fa.save() Another important point is that when you add the many2many relation, in my case clan. The argument of .add() should be an object. – Peter Jan 18 '17 at 14:08