96 votes

Comment obtenir les clés primaires des objets créés avec django bulk_create ?

Existe-t-il un moyen d'obtenir les clés primaires des éléments que vous avez créés en utilisant la fonction bulk_create dans django 1.4+ ?

1voto

Kevin Points 136
# datatime.py
# my datatime function
def getTimeStamp(needFormat=0, formatMS=True):
    if needFormat != 0:
        return datetime.datetime.now().strftime(f'%Y-%m-%d %H:%M:%S{r".%f" if formatMS else ""}')
    else:
        ft = time.time()
        return (ft if formatMS else int(ft))

def getTimeStampString():
    return str(getTimeStamp()).replace('.', '')

# model
    bulk_marker = models.CharField(max_length=32, blank=True, null=True, verbose_name='bulk_marker', help_text='ONLYFOR_bulkCreate')

# views
import .........getTimeStampString

data_list(
Category(title="title1", bulk_marker=getTimeStampString()),
...
)
# bulk_create
Category.objects.bulk_create(data_list)
# Get primary Key id
Category.objects.filter(bulk_marker=bulk_marker).values_list('id', flat=True)

1voto

Patrick Points 598

J'ai essayé de nombreuses stratégies pour contourner cette limitation de MariaDB/MySQL. La seule solution fiable que j'ai trouvée à la fin était de générer les clés primaires dans l'application. NE PAS générer INT AUTO_INCREMENT les champs PK vous-même, cela ne fonctionnera pas, pas même dans une transaction avec un niveau d'isolement serializable car le compteur PK de MariaDB n'est pas protégé par des verrous de transaction.

La solution consiste à ajouter des UUID aux modèles, génèrent leurs valeurs dans la classe de modèle, puis les utilisent comme identifiant. Lorsque vous enregistrez un groupe de modèles dans la base de données, vous ne récupérez toujours pas leur PK réel, mais ce n'est pas grave, car dans les requêtes ultérieures, vous pouvez les identifier de manière unique grâce à leur UUID.

0voto

MattWritesCode Points 2204

En documentation sur django actuellement les états sous les limitations :

Si la clé primaire du modèle est un définir l'attribut de la clé primaire, comme save() fait.

Mais, il y a de bonnes nouvelles. Il y a eu quelques billets parlant de bulk_create de mémoire. Le site billet indiqué ci-dessus est le plus susceptible d'avoir une solution qui sera bientôt mise en œuvre, mais il n'y a évidemment aucune garantie quant au moment où elle sera mise en œuvre ou si elle le sera un jour.

Il y a donc deux solutions possibles,

  1. Attendez et voyez si ce patch arrive en production. Vous pouvez y contribuer en testant la solution proposée et en faisant part de vos réflexions et de vos problèmes à la communauté django. https://code.djangoproject.com/attachment/ticket/19527/bulk_create_and_create_schema_django_v1.5.1.patch

  2. Remplacez / écrivez votre propre solution d'insertion en masse.

0voto

peper0 Points 848

La solution la plus simple consiste probablement à attribuer manuellement des clés primaires. Cela dépend du cas particulier, mais parfois il suffit de commencer avec max(id)+1 de la table et d'attribuer des nombres qui s'incrémentent pour chaque objet. Cependant, si plusieurs clients peuvent insérer des enregistrements simultanément, un verrouillage peut être nécessaire.

0voto

user3175220 Points 1

Cela ne fonctionne pas dans la version de base de Django, mais il existe une fonction patch dans le bug tracker de Django qui permet à bulk_create de définir les clés primaires des objets créés.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X