Wednesday, March 28, 2012

Re: De-serialization of ManyToManyField

Hi,

I finally worked out where the problem was!

I am posting the answer in case that someone else has a similar issue
and stumbles upon this.

So I have reverted to the original model, as defined in the first
email here. The problem was with my definition of the natural keys, my
function was not retruning a tuple.

The solution was to add a comma to the return value of the natural_key
methods:

---------------------------------------------------------------------------
from django.db import models
class TestManager(models.Manager):
def get_by_natural_key(self, name):
return self.get(name=name,)


class Test(models.Model):
name = models.CharField(max_length = 100, unique = True)
date = models.DateField()


def __unicode__(self):
return self.name


def natural_key(self):
return (self.name,)


class InstanceManager(models.Manager):
def get_by_natural_key(self, name):
return self.get(name=name,)


class Instance(models.Model):
name = models.CharField(max_length = 100, unique = True)
test = models.ManyToManyField(Test)
date = models.DateField()


def __unicode__(self):
return self.name


def natural_key(self):
return (self.name,)

I realise this is a pretty basic Python 'gotcha' and one I would hope
I would normally spot! In this case I was just not sure where the
problem was.

I hope this helps someone else with the same problem, at some point!

regards
Stephen

On Mar 27, 11:02 am, sk <6b656...@gmail.com> wrote:
> Hi,
>
> So a brief update. I changed the way I was building this model and
> explicitly created a 'joining' table and added a through clause to the
> ManyToManyField definition as well as allowing null values. This meant
> I was able to populate the joining table using YAML after building the
> test/instance tables using the natural keys for each of 'test' and
> 'instance'.
>
> However when I view the table in the admin interface there is no
> multiple selector for 'test' when I edit the instance in the admin
> interface. I have added the joining table to the list of admin tables
> (if this makes a difference).
>
> Can anyone explain to me whether this is another error on my part, or
> if it is expected that if you explicitly define a joining table then
> Django suppresses the management of the relationship outside of the
> joining table itself?
>
> Obviously if it were possible to use the built in manytomany
> management and be able to import the YAML defining this that I
> included in the initial question that would be favourable.
>
> For context this is a simplified example of a reasonably large
> database that I am trying to port to a Django model so manually
> building the contents of the joining table is not a reasonable
> solution. I can generate the YAML, or similar, fairly trivially and so
> it is best for me to build the fixtures to get the initial DB set up
> and import them after the initial syndb.
>
> Any guidance on this would be much appreciated - I am really enjoying
> the elegance of Django but little issues caused by my (lack of)
> understanding are definitely holding me up!
>
> Regards
> Stephen
>
> On Mar 26, 12:01 pm, sk <6b656...@gmail.com> wrote:
>
>
>
> > Hi,
>
> > I have searched high and low to an answer to this, but have been
> > unable too turn anything up. Apologies if I have overlooked an answer
> > or explanation elsewhere.
>
> > I have set up a very simple model as follows:
> > ---------------------------------------------------------------------------
> > from django.db import models
> > class TestManager(models.Manager):
> >     def get_by_natural_key(self, name):
> >         return self.get(name=name,)
>
> > class Test(models.Model):
> >     name = models.CharField(max_length = 100, unique = True)
> >     date = models.DateField()
>
> >     def __unicode__(self):
> >         return self.name
>
> >     def natural_key(self):
> >         return (self.name)
>
> > class InstanceManager(models.Manager):
> >     def get_by_natural_key(self, name):
> >         return self.get(name=name,)
>
> > class Instance(models.Model):
> >     name = models.CharField(max_length = 100, unique = True)
> >     test = models.ManyToManyField(Test)
> >     date = models.DateField()
>
> >     def __unicode__(self):
> >         return self.name
>
> >     def natural_key(self):
> >         return (self.name)
> > ---------------------------------------------------------------
>
> > looking at the admin interface I am able to add a couple of
> > 'tests' (test 1 and test 2). I am then able to add an instance which
> > is linked to both test 1 and test 2. If I dump the data to YAML format
> > then I get the following (for the two tables in question):
>
> > ---------------------------------------------------------------
> > - fields: {date: 2012-03-26, name: test 1}
> >   model: TempDB.test
> >   pk: 1
> > - fields: {date: 2012-03-26, name: test 2}
> >   model: TempDB.test
> >   pk: 2
> > - fields:
> >     date: 2012-03-26
> >     name: Instance 1
> >     test: [test 1, test 2]
> >   model: TempDB.instance
> >   pk: 1
> > ---------------------------------------------------------------
>
> > This is roughly what I would expect to see, although the documentation
> > does not explicitly state that a manytomany serialization will be a
> > multi-element list, it seems to be a reasonable assumption.
>
> > When I try to perform a loaddata with this output (and after manually
> > deleting the tables from the admin interface, to be sure). I get the
> > following error:
>
> > Problem installing fixture '/home/XXXX/workspace/THMDB/THMDB/TempDB/
> > fixtures/test.yaml': Traceback (most recent call last):
> >   File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/
> > django/core/management/commands/loaddata.py", line 190, in handle
> >     for obj in objects:
> >   File "/usr/local/lib/python2.7/dist-packages/Django-1.4-py2.7.egg/
> > django/core/serializers/pyyaml.py", line 62, in Deserializer
> >     raise DeserializationError(e)
> > DeserializationError: [u"'test 1' value must be an integer."]
>
> > What exactly have I done wrong? I suspect I have made an error in
> > defining the managers. I have defined two as I planned to link too
> > instances from another table. I left in the definition in case it is
> > the cause of the error. However it still does the same thing if I
> > comment it out.
>
> > I am running Django 1.4 on python 2.7 under Ubuntu 11.10.
>
> > Many thanks for your help.
>
> > Stephen- Hide quoted text -
>
> - Show quoted text -

--
You received this message because you are subscribed to the Google Groups "Django users" group.
To post to this group, send email to django-users@googlegroups.com.
To unsubscribe from this group, send email to django-users+unsubscribe@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/django-users?hl=en.

No comments:

Post a Comment