実現したいこと
Python Djangoで特定のテーブルのみ他のシステムと依存しているのでそこだけ分けて運用したい。
前提
Python Djangoでルーター機能を用いてデータベースを複数用意してマイグレートするとエラーが発生します。
Uploadモデルのみセカンダリーのデータベースに存在し定義されています。(すでに存在している)
syun1@syun1MacBook-Pro archive_system_django % python manage.py inspectdb --database secondary class Upload(models.Model): file_id = models.AutoField(primary_key=True) title = models.TextField() file_name = models.CharField(max_length=255) file_path = models.CharField(max_length=255) comment = models.TextField(blank=True, null=True) insert_at = models.DateTimeField() update_at = models.DateTimeField() delete_flag = models.IntegerField() user_id = models.IntegerField() published = models.IntegerField() class Meta: managed = False db_table = 'upload'
他のモデルはすべてデフォルトデータベースにマイグレーション時に作成します。
発生している問題・エラーメッセージ
syun1@syun1MacBook-Pro archive_system_django % python manage.py migrate ArchiveViewer Operations to perform: Apply all migrations: ArchiveViewer Running migrations: Applying ArchiveViewer.0001_initial...Traceback (most recent call last): MySQLdb.OperationalError: (1824, "Failed to open the referenced table 'upload'") The above exception was the direct cause of the following exception: django.db.utils.OperationalError: (1824, "Failed to open the referenced table 'upload'")
該当のソースコード
ArchiveViewer.models.py
Python
1from django.db import models 2from os.path import basename, splitext 3from ckeditor.fields import RichTextField 4from django.utils import timezone 5# 記事用モデル 6class Report(models.Model): 7 title = models.CharField(max_length=100, verbose_name="タイトル") 8 description = RichTextField(verbose_name="説明") 9 is_public = models.BooleanField(default=False, verbose_name="公開フラグ") 10 is_recommend = models.BooleanField(default=False, verbose_name="おすすめフラグ") 11 category = models.ForeignKey("ReportCategory", on_delete=models.CASCADE, verbose_name="カテゴリー", null=True) 12 created_at = models.DateTimeField(auto_now_add=True) 13 updated_at = models.DateTimeField(auto_now=True) 14 created_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="created_reports") 15 updated_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="updated_reports") 16 deleted_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="deleted_reports", null=True) 17 is_deleted = models.BooleanField(default=False) 18 19# 記事のカテゴリー用モデル 20class ReportCategory(models.Model): 21 name = models.CharField(max_length=100, verbose_name="カテゴリー名") 22 description = models.TextField(verbose_name="カテゴリーの説明") 23 created_at = models.DateTimeField(auto_now_add=True) 24 updated_at = models.DateTimeField(auto_now=True) 25 created_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="created_categories") 26 updated_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="updated_categories") 27 deleted_by = models.ForeignKey("accounts.User", on_delete=models.CASCADE, related_name="deleted_categories", null=True) 28 is_deleted = models.BooleanField(default=False) 29 def save(self, *args, **kwargs): 30 # 削除フラグが立っている場合 31 if self.is_deleted: 32 # このカテゴリーに関連する Report オブジェクトの category フィールドを null に設定 33 Report.objects.filter(category=self).update(category=None) 34 35 super().save(*args, **kwargs) 36 37# 履歴とお気に入りの抽象モデル 38class HistoryFavoriteBase(models.Model): 39 user = models.ForeignKey("accounts.User", on_delete=models.CASCADE) 40 created_at = models.DateTimeField(auto_now_add=True) 41 42 class Meta: 43 # 抽象モデルとして扱うのでTrue 44 abstract = True 45 46# ユーザーが閲覧したアーカイブコンテンツを保存するテーブル 47class UploadHistory(HistoryFavoriteBase): 48 upload = models.ForeignKey("Upload", on_delete=models.CASCADE) 49 class Meta: 50 # 作成日時の昇順で並べる 51 ordering = ['created_at'] 52 # ユーザーが閲覧したアーカイブコンテンツの履歴を100件まで保存する 53 def clean_history(self): 54 history_count = UploadHistory.objects.filter(user=self.user).count() 55 if history_count >= 100: 56 oldest_history = UploadHistory.objects.filter(user=self.user).order_by('created_at').first() 57 oldest_history.delete() 58 def save (self, *args, **kwargs): 59 self.clean_history() 60 super().save(*args, **kwargs) 61 62# ユーザーが閲覧した記事を保存するテーブル 63class ReportHistory(HistoryFavoriteBase): 64 report = models.ForeignKey("Report", on_delete=models.CASCADE) 65 66 class Meta: 67 ordering = ['created_at'] 68 69 def clean_history(self): 70 history_count = ReportHistory.objects.filter(user=self.user).count() 71 if history_count >= 100: 72 oldest_history = ReportHistory.objects.filter(user=self.user).order_by('created_at').first() 73 oldest_history.delete() 74 def save (self, *args, **kwargs): 75 self.clean_history() 76 super().save(*args, **kwargs) 77 78# ユーザーのお気に入り記事を保存するテーブル 79class ReportFavorite(HistoryFavoriteBase): 80 report = models.ForeignKey("Report", on_delete=models.CASCADE) 81 82 # 重複のないようにする 83 def save(self, *args, **kwargs): 84 if ReportFavorite.objects.filter(user=self.user, report=self.report).exists(): 85 return 86 super().save(*args, **kwargs) 87 88# ユーザーのお気に入りアーカイブを保存するテーブル 89class UploadFavorite(HistoryFavoriteBase): 90 upload = models.ForeignKey("Upload", on_delete=models.CASCADE) 91 92 # 重複のないようにする 93 def save(self, *args, **kwargs): 94 if UploadFavorite.objects.filter(user=self.user, upload=self.upload).exists(): 95 return 96 super().save(*args, **kwargs) 97 98 99#このモデルはアーカイブ管理システムのグループが作成したテーブルで、セカンダリーのデータベースに保存されている。 100# アーカイブコンテンツ用モデル 101class Upload(models.Model): 102 file_id = models.AutoField(primary_key=True) 103 title = models.TextField() 104 file_name = models.CharField(max_length=255) 105 file_path = models.CharField(max_length=255) 106 comment = models.TextField(blank=True, null=True) 107 insert_at = models.DateTimeField(auto_now_add=True) 108 update_at = models.DateTimeField(auto_now=True) 109 delete_flag = models.BooleanField(default=False) 110 user_id = models.IntegerField() 111 published = models.BooleanField(default=False) 112 113 class Meta: 114 managed = False 115 db_table = 'upload' 116
settings.py
Python
1DATABASES = { 2 "default": { 3 "ENGINE": "django.db.backends.mysql", 4 "NAME": "archive_system", 5 "USER": "***********", 6 "PASSWORD": "***************", 7 "HOST": "localhost", 8 "PORT": "3306", 9 }, 10 "secondary": { 11 "ENGINE": "django.db.backends.mysql", 12 "NAME": "archive_system_upload", 13 "USER": "*******", 14 "PASSWORD": "***********", 15 "HOST": "localhost", 16 "PORT": "3306", 17 } 18} 19# DATABASE_ROUTERSの設定 20DATABASE_ROUTERS = ['archive_system.dbrouter.ArchiveSystemRouter']
dbrouter.py
Python
1class ArchiveSystemRouter: 2 """ 3 A router to control all database operations on models in the 4 Archive System application. 5 """ 6 7 def db_for_read(self, model, **hints): 8 """ 9 Attempts to read upload models go to secondary. 10 """ 11 if model._meta.app_label == 'ArchiveViewer' and model._meta.model_name == 'upload': 12 return 'secondary' 13 elif model._meta.app_label == 'accounts': 14 return 'default' 15 return 'default' 16 17 def db_for_write(self, model, **hints): 18 """ 19 Attempts to write upload models go to secondary. 20 """ 21 if model._meta.app_label == 'ArchiveViewer' and model._meta.model_name == 'upload': 22 return 'secondary' 23 elif model._meta.app_label == 'accounts': 24 return 'default' 25 return 'default' 26 27 def allow_relation(self, obj1, obj2, **hints): 28 """ 29 Allow relations if a model in the ArchiveViewer or accounts app is involved. 30 """ 31 if obj1._meta.app_label in ['ArchiveViewer', 'accounts'] or \ 32 obj2._meta.app_label in ['ArchiveViewer', 'accounts']: 33 return True 34 return None 35 36 def allow_migrate(self, db, app_label, model_name=None, **hints): 37 """ 38 Make sure the upload model only appears in the 'secondary' 39 database. 40 """ 41 if app_label == 'ArchiveViewer' and model_name == 'upload': 42 return db == 'secondary' 43 elif app_label == 'accounts': 44 return db == 'default' 45 return db == 'default'
補足情報(FW/ツールのバージョンなど)
Mac OS Apple Silicon
Python 3.11
Django 4.2.5
mysql Ver 8.0.33 for macos13.3 on arm64 (Homebrew)

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。