diff --git a/django/db/models/query.py b/django/db/models/query.py
index 9f245b02ca..48c73c78e6 100644
--- a/django/db/models/query.py
+++ b/django/db/models/query.py
@@ -674,15 +674,26 @@ class QuerySet(AltersData):
     acreate.alters_data = True
 
     def _prepare_for_bulk_create(self, objs):
+        opts = self.model._meta
         objs_with_pk, objs_without_pk = [], []
+        pk = opts.pk
+        pk_fields = list(getattr(pk, "fields", (pk,)))
+
+        def _pk_is_complete(obj):
+            for f in pk_fields:
+                v = getattr(obj, f.attname)
+                if v is None or isinstance(v, DatabaseDefault):
+                    return False
+            return True
+
         for obj in objs:
             if isinstance(obj.pk, DatabaseDefault):
                 objs_without_pk.append(obj)
-            elif obj._is_pk_set():
+            elif _pk_is_complete(obj):
                 objs_with_pk.append(obj)
             else:
-                obj.pk = obj._meta.pk.get_pk_value_on_save(obj)
-                if obj._is_pk_set():
+                obj.pk = opts.pk.get_pk_value_on_save(obj)
+                if _pk_is_complete(obj):
                     objs_with_pk.append(obj)
                 else:
                     objs_without_pk.append(obj)
@@ -839,6 +850,8 @@ class QuerySet(AltersData):
                 if (
                     connection.features.can_return_rows_from_bulk_insert
                     and on_conflict is None
+                    and opts.db_returning_fields
+                    and objs_without_pk
                 ):
                     assert len(returned_columns) == len(objs_without_pk)
                 for obj_without_pk, results in zip(objs_without_pk, returned_columns):
diff --git a/tests/composite_pk/test_create.py b/tests/composite_pk/test_create.py
index 38ad9690fb..7ace973d8f 100644
--- a/tests/composite_pk/test_create.py
+++ b/tests/composite_pk/test_create.py
@@ -1,7 +1,7 @@
 from django.db import IntegrityError
 from django.test import TestCase, skipUnlessDBFeature
 
-from .models import Post, Tenant, User
+from .models import Post, Tenant, User, TimeStamped
 
 
 class CompositePKCreateTests(TestCase):
@@ -78,6 +78,16 @@ class CompositePKCreateTests(TestCase):
         self.assertEqual(obj_3.pk, (obj_3.tenant_id, obj_3.id))
         self.assertEqual(obj_3.email, "user8214@example.com")
 
+    def test_bulk_create_auto_now_add_primary_key(self):
+        objs = [TimeStamped(id=1), TimeStamped(id=2), TimeStamped(id=3)]
+        created = TimeStamped.objects.bulk_create(objs)
+        self.assertEqual(len(created), 3)
+        self.assertEqual(TimeStamped.objects.count(), 3)
+        for db_obj in TimeStamped.objects.all():
+            self.assertIsNotNone(db_obj.pk)
+        for obj in created:
+            self.assertIsNotNone(obj.pk)
+
     @skipUnlessDBFeature(
         "supports_update_conflicts",
         "supports_update_conflicts_with_target",
