Django multidbを使用すると、マスター/スレーブインフラストラクチャを実行するルーターを簡単に作成できます。しかし、複数のデータベースに書き込むルーターを作成することは可能ですか?私のユースケースは、すべて同じドメインで実行されているプロジェクトのコレクションです。contrib.auth
ユーザーがすべてのサイトで登録/ログインするのを防ぐために、テーブルとテーブルを同期させたいと思いcontrib.sessions
ます。それはDjangomultidbで可能ですか、それともデータベースシステム(私の場合はMySQL)のレプリケーション機能を調べる必要がありますか?
4 に答える
SSOまたはOAuthサービスをより適切に実装できると思います
ただし、2つのデータベース間でテーブルユーザーを同期する場合、および独自のUserModelを使用している場合は、次のようにすることができます。
class MyUser(models.Model):
name = models.CharField(max_length=100)
user = models.ForeignKey(User, unique=True)
def save(self, ...): # ALL the signature
super(MyUser, self).save(using='database_1')
super(MyUser, self).save(using='database_2')
このようなデコレータを使用して配置することもできます。このように、他のテーブルの同期にも使用できます。
def save_multi_db(model_class):
def save_wrapper(save_func):
def new_save(self, *args, **kws):
super(model_class, self).save(using='database_1')
super(model_class, self).save(using='database_1')
return new_save
func = getattr(model_class, 'save')
setattr(model_class, 'save', save_wrapper(func))
return save_wrapper
# and use it like this:
@save_multi_db
class MyUser(models.Model):
....
これがお役に立てば幸いです:)
現在、Django シャーディング スキーマに取り組んでいます。
私は Django ルーターを見ましたが、自分でロールバックすることにしました。
あなたの問題に関するいくつかの考え:
- 1 つのアイデアは、1 つのデータベースを使用し、保存後に Django シグナルを使用して適切なデータをコピーすることです。
何かのようなもの -
import settings.databases as dbs_list
def post_save_function(UserModel):
for db in dbs_list:
UserModel.save(using=db,force_insert=True)
ユーザーオブジェクトを(少なくとも単一DBモデルで)保存すると、django.contrib内で発生するさまざまな魔法を介して、セッション、認証などのデータがフードの下に保存されるようです。これらすべてのデータベース テーブルの名前とタイプ。
この動作の可能性を支持するために、私は最近どこか (おそらく Alex Gaynor のブログ投稿の 1 つ) で、オブジェクトに外部キーがある場合、Django はオブジェクトが存在する同じ DB を使用しようとすることを読んだことを誓いますDjango の通常の動作方法に照らして)。
- 別のアイデア:
参照した Django multiDB ページの例から、次のようなものが機能するかどうか疑問に思います。
サンプルコード:
def allow_syncdb(self, db, model):
"Explicitly put all models on all databases."
return True
可能な変更:
def allow_syncdb (自己、データベース、モデル):
if isinstance(model,User):
return True
elif isinstance(model,Session):
return True
else:
''' something appropriate --
whatever your sharding schema is for other objects '''
もう一度見てみると、このコードはおそらく「db_for_write」関数としてより役立つでしょう。しかし、あなたはその考えを理解します。
これを機能させるために追加する必要がある他のタイプのモデルは間違いありません(すべての認証関連のもので、これは広範囲にわたるものです)。
幸運を!これが何らかの形で役立つことを願っています。
私はあなたの調査結果とコメントに興味があります!
JB
まず、この記事のように、もっと SSO フレームワークが必要だと思います
私はmouadの答えを試しましたが、クラスデコレータを動作させることができませんでした...そして、この解決策ではモデルにカスタムのsave()を持たせることができないようです。
私のニーズにより適したものとして、カスタム ジェネリック クラスを定義し、単に save() 関数をオーバーライドしました。
class MultiDbModel(models.Model):
class Meta:
abstract = True
def save(self, *args, **kwargs):
for dbname in settings.DATABASES:
super(MultiDbModel, self).save(using=dbname)
その後:
class MyObject(MultiDbModel):
[...]
def save(self, *args, **kwargs):
[custom save]
super(MyObject, self).save(args, kwargs)
これは、外部キーも処理しているように見える私の multidb_model.py です。バグがある場合は更新しますが、Stepahne の回答に従ってこのクラスから継承すると、外部キーの保存が処理されます。
import logging
from django.db import models
DEFAULT_DB = 'default' # main postgres host
MIRROR_COPY_DB = 'pg_mirror' # a copy original db, i.e. if you want to move your data and keep it in sync
class MultiPgDbModel(models.Model):
class Meta:
abstract = True
def save(self, *args, **kwarg):
super(MultiPgDbModel, self).save(using=DEFAULT_DB)
try:
fields = [field for field in self._meta.fields if field.get_internal_type() == 'ForeignKey']
for field in fields:
getattr(self, field.name).save(using=MIRROR_COPY_DB)
super(MultiPgDbModel, self).save(using=MIRROR_COPY_DB)
except Exception as e:
logging.exception(f"MultiPgDbModel.save unexpected error when saving to pg_mirror, object id "
f"{self.pk} of model {self._meta.model}. {e}")