#31539: Add support for bulk operations on reverse many-to-one manager
-------------------------------------+-------------------------------------
               Reporter:  Baptiste   |          Owner:  nobody
  Mispelon                           |
                   Type:  New        |         Status:  new
  feature                            |
              Component:  Database   |        Version:  master
  layer (models, ORM)                |
               Severity:  Normal     |       Keywords:
           Triage Stage:             |      Has patch:  0
  Unreviewed                         |
    Needs documentation:  0          |    Needs tests:  0
Patch needs improvement:  0          |  Easy pickings:  0
                  UI/UX:  0          |
-------------------------------------+-------------------------------------
 Using the `Book` and `Author` models from the docs:
 {{{#!python
 class Author(models.Model):
     name = models.CharField(max_length=100)

 class Book(models.Model):
     author = models.ForeignKey(Author, on_delete=models.CASCADE,
 related_name='books')
     title = models.CharField(max_length=200)
 }}}

 This works and creates two books linked to their author correctly:
 {{{#!python
 toni = Author.objects.create(name="Toni Morrison")

 toni.books.create(title="The Bluest Eye")
 toni.books.create(title="Beloved")
 }}}

 But if you try to use `bulk_create` to achieve the same, you get an error:
 {{{#!python
 toni = Author.objects.create(name="Toni Morrison")

 toni.books.bulk_create([
     Book(title="The Bluest Eye"),
     Book(title="Beloved"),
 ])
 }}}

 This fails with an `IntegrityError` because `bulk_create` doesn't
 automatically fill in the value of `Book.author` (the way it does it for
 `create()`).


 The documentation for `RelatedManager` [1] doesn't mention `bulk_create()`
 but it's not clear to me if that means the operation is unsupported or not
 (other methods like `count()` or `filter()` are not listed either but are
 clearly supported). Because of this I wasn't sure whether to mark this
 ticket as a bug or as a new feature.

 Looking at the code [2], I can't find an explanation of why `bulk_create`
 or `bulk_update` are not implemented either.
 I've come up with the following implementation which seems to work (I
 haven't tested it extensively):

 {{{#!python
 def bulk_create(self, objs, **kwargs):
     def set_field_to_instance(instance):
         setattr(instance, self.field.name, self.instance)
         return instance

     objs = map(set_field_to_instance, objs)
     db = router.db_for_write(self.model, instance=self.instance)
     return super(RelatedManager, self.db_manager(db)).bulk_create(objs,
 **kwargs)
 }}}

 [1]
 
https://docs.djangoproject.com/en/dev/ref/models/relations/#django.db.models.fields.related.RelatedManager
 [2]
 
https://github.com/django/django/blob/aff7a58aef0264e5b2740e5df07894ecc0d7a580/django/db/models/fields/related_descriptors.py#L559

-- 
Ticket URL: <https://code.djangoproject.com/ticket/31539>
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 view this discussion on the web visit 
https://groups.google.com/d/msgid/django-updates/052.2b01cd5d3563e9c162547181a311789a%40djangoproject.com.

Reply via email to