PostgreSQL
 sql >> Cơ Sở Dữ Liệu >  >> RDS >> PostgreSQL

Django:IntegrityError trong Many To Many add ()

Có thể tái tạo lỗi không?

Có, hãy để chúng tôi sử dụng Publication nổi tiếng và Article mô hình từ tài liệu Django . Sau đó, hãy tạo một vài chuỗi.

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()

Bạn chắc chắn thấy các vi phạm ràng buộc khóa duy nhất của loại được báo cáo trong báo cáo lỗi . Nếu bạn không thấy chúng, hãy thử tăng số lượng chuỗi hoặc số lần lặp lại.

Có công việc xung quanh không?

Đúng. Sử dụng through mô hình và get_or_create . Đây là mô hình.py được điều chỉnh từ ví dụ trong tài liệu django.

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')

Đây là lớp luồng mới là một sửa đổi của lớp ở trên.

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

Bạn sẽ thấy rằng ngoại lệ không còn hiển thị nữa. Hãy thoải mái tăng số lần lặp lại. Tôi chỉ đạt đến 1000 với get_or_create nó không ném ra ngoại lệ. Tuy nhiên add() thường đưa ra một ngoại lệ với 20 lần lặp lại.

Tại sao điều này hoạt động?

Bởi vì get_or_create là nguyên tử.

Cập nhật: Cảm ơn @louis đã chỉ ra rằng mô hình thông qua thực tế có thể bị loại bỏ. Bỏ get_or_create trong MyThread2 có thể được thay đổi thành.

ap , c = article.publications.through.objects.get_or_create(
            article=article, publication=pub)


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Hibernate UUID với PostgreSQL và SQL Server

  2. Đặt giá trị trả về mặc định cho hàm Postgres

  3. Chèn một mảng bằng cách sử dụng Sequel gem trong PostgreSQL

  4. Nhiều INSERTS vào một bảng và nhiều INSERTS vào một bảng

  5. Các quy tắc của PostgreSQL và vấn đề nextval () / serial (rất đặc trưng cho PostgreSQL)