क्या त्रुटि पुन:उत्पन्न की जा सकती है?
हाँ, आइए हम प्रसिद्ध Publication
. का उपयोग करें और Article
Django डॉक्स
के मॉडल . फिर, आइए कुछ सूत्र बनाते हैं।
import threading
import random
def populate():
for i in range(100):
Article.objects.create(headline = 'headline{0}'.format(i))
Publication.objects.create(title = 'title{0}'.format(i))
print 'created objects'
class MyThread(threading.Thread):
def run(self):
for q in range(1,100):
for i in range(1,5):
pub = Publication.objects.all()[random.randint(1,2)]
for j in range(1,5):
article = Article.objects.all()[random.randint(1,15)]
pub.article_set.add(article)
print self.name
Article.objects.all().delete()
Publication.objects.all().delete()
populate()
thrd1 = MyThread()
thrd2 = MyThread()
thrd3 = MyThread()
thrd1.start()
thrd2.start()
thrd3.start()
आप निश्चित रूप से बग रिपोर्ट में रिपोर्ट किए गए प्रकार के अद्वितीय कुंजी बाधा उल्लंघन देख सकते हैं। . यदि आप उन्हें नहीं देखते हैं, तो थ्रेड्स या पुनरावृत्तियों की संख्या बढ़ाने का प्रयास करें।
क्या कोई समाधान है?
हाँ। through
का उपयोग करें मॉडल और get_or_create
. django डॉक्स में उदाहरण से अनुकूलित model.py यहां दिया गया है।
class Publication(models.Model):
title = models.CharField(max_length=30)
def __str__(self): # __unicode__ on Python 2
return self.title
class Meta:
ordering = ('title',)
class Article(models.Model):
headline = models.CharField(max_length=100)
publications = models.ManyToManyField(Publication, through='ArticlePublication')
def __str__(self): # __unicode__ on Python 2
return self.headline
class Meta:
ordering = ('headline',)
class ArticlePublication(models.Model):
article = models.ForeignKey('Article', on_delete=models.CASCADE)
publication = models.ForeignKey('Publication', on_delete=models.CASCADE)
class Meta:
unique_together = ('article','publication')
यहाँ नया थ्रेडिंग वर्ग है जो ऊपर वाले का एक संशोधन है।
class MyThread2(threading.Thread):
def run(self):
for q in range(1,100):
for i in range(1,5):
pub = Publication.objects.all()[random.randint(1,2)]
for j in range(1,5):
article = Article.objects.all()[random.randint(1,15)]
ap , c = ArticlePublication.objects.get_or_create(article=article, publication=pub)
print 'Get or create', self.name
आप पाएंगे कि अपवाद अब दिखाई नहीं देता है। पुनरावृत्तियों की संख्या बढ़ाने के लिए स्वतंत्र महसूस करें। मैं केवल get_or_create
. के साथ 1000 तक गया इसने अपवाद नहीं फेंका। हालांकि add()
आमतौर पर 20 पुनरावृत्तियों के साथ एक अपवाद फेंक दिया।
यह क्यों काम करता है?
क्योंकि get_or_create परमाणु है।
अपडेट करें: धन्यवाद @louis यह इंगित करने के लिए कि मॉडल के माध्यम से वास्तव में समाप्त किया जा सकता है। इस प्रकार get_or_create
MyThread2
. में के रूप में बदला जा सकता है।
ap , c = article.publications.through.objects.get_or_create(
article=article, publication=pub)