#28385: deserialisers ignore natural keys when primary key has a default value
------------------------------------------------+------------------------
               Reporter:  Daniel Knell          |          Owner:  nobody
                   Type:  Bug                   |         Status:  new
              Component:  Core (Serialization)  |        Version:  1.11
               Severity:  Normal                |       Keywords:
           Triage Stage:  Unreviewed            |      Has patch:  0
    Needs documentation:  0                     |    Needs tests:  0
Patch needs improvement:  0                     |  Easy pickings:  1
                  UI/UX:  0                     |
------------------------------------------------+------------------------
 
https://github.com/django/django/blob/master/django/core/serializers/base.py#L223


 {{{
 def build_instance(Model, data, db):
     """
     Build a model instance.
     If the model instance doesn't have a primary key and the model
 supports
     natural keys, try to retrieve it from the database.
     """
     obj = Model(**data)
     if (obj.pk is None and hasattr(Model, 'natural_key') and
             hasattr(Model._default_manager, 'get_by_natural_key')):
         natural_key = obj.natural_key()
         try:
             obj.pk =
 Model._default_manager.db_manager(db).get_by_natural_key(*natural_key).pk
         except Model.DoesNotExist:
             pass
     return obj
 }}}


 this causes loaddata to fail on second attempt when using natural keys and
 uuid primary keys as pk is set.

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

 class Foo(DateTimeMixin, models.Model):
     id = models.UUIDField(primary_key=True, default=uuid.uuid4,
 editable=False)
     name = models.CharField(max_length=100, unique=True)

     objects = FooManager()

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


 checking the primary key was not actually set seems to fix things:

 {{{
 def build_instance(Model, data, db):
     obj = Model(**data)
     pk = data.get(Model._meta.pk.name, None)

     if (pk is None and hasattr(Model, 'natural_key') and
             hasattr(Model._default_manager, 'get_by_natural_key')):
         natural_key = obj.natural_key()
         try:
             obj.pk =
 Model._default_manager.db_manager(db).get_by_natural_key(*natural_key).pk
         except Model.DoesNotExist:
             pass
     return obj

 import django.core.serializers.base

 django.core.serializers.base.build_instance = build_instance
 }}}

-- 
Ticket URL: <https://code.djangoproject.com/ticket/28385>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

-- 
You received this message because you are subscribed to the Google Groups 
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/054.07206c2c1fa2bd89bb2d9cfe12c34590%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to