8

複数の MS SQL データベース インスタンスに接続している Django アプリケーションがあります。各データベースへのプロセスのルーティングを処理する各アプリの router.py があります。

複数のデータベース アクセスを設定するのはこれが初めてです。

Django 組み込みアプリは、次の router.py を介してデフォルト データベースにルーティングされます。

class DjangoRouter(object):
"""
A router to control all database operations on models in the
auth application.
"""

def db_for_read(self, model, **hints):
    """
    Attempts to read auth models go to auth.
    """
    app_list = ('auth', 'admin', 'contenttypes', 'sessions',)

    if model._meta.app_label in app_list:
        return 'default'
    return None

def db_for_write(self, model, **hints):
    """
    Attempts to write auth models go to auth.
    """
    app_list = ('auth', 'admin', 'contenttypes', 'sessions',)
    if model._meta.app_label in app_list:
        return 'default'
    return None

def allow_relation(self, obj1, obj2, **hints):
    """
    Allow relations if a model in the auth app is involved.
    """
    app_list = ('auth', 'admin', 'contenttypes', 'sessions',)
    if obj1._meta.app_label in app_list and obj2._meta.app_label in app_list:
        return True
    return None

def allow_migrate(self, db, app_label, model=None, **hints):
    """
    Make sure the auth app only appears in the 'auth'
    database.
    """
    app_list = ('auth', 'admin', 'contenttypes', 'sessions',)

    if app_label in app_list:
        return db == 'default'
    return None

LDAP 認証と Django の組み込み認証を使用しています。これは、イントラネット ユーザーが AD サーバーに対して認証できるという考え方です。外部ユーザーが登録でき、Django の認証で認証されます。

デフォルトのデータベースを次のように設定した場合:

'default': {
    'ENGINE': 'sql_server.pyodbc',
    'NAME': 'Django',
    'USER': '',
    'PASSWORD': '',
    'HOST': 'sqlbeta',
    'PORT': '',
},

LDAP は機能しますが、Django の認証にユーザーを追加できません。管理者は「成功」メッセージを表示しますが、ユーザーはデータベースに追加されません。

デフォルトのデータベースを SQLLite に戻すと、AD に対して認証を行い、Django ユーザーを追加できます。

したがって、routers.py ファイルの問題ではないと思います。「sql_server.pyodbc」エンジンに問題があるのではないかと心配しています。

編集:リクエストごとに、データベース設定は次のとおりです。

DATABASES = {
    # 'default': {
    #    'ENGINE': 'django.db.backends.sqlite3',
    #    'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
    # },
    'default': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'Django',
        'USER': '',
        'PASSWORD': '',
        'HOST': 'sqlbeta',
        'PORT': '',
    },
    'master': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'master',
        'USER': '',
        'PASSWORD': '',
        'HOST': 'sqlbeta',
        'PORT': '',
    },
    'databaseone': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'databaseone',
        'USER': '',
        'PASSWORD': '',
        'HOST': 'sqlbeta',
        'PORT': '',
    },
    'databasetwo': {
        'ENGINE': 'sql_server.pyodbc',
        'NAME': 'databasetwo',
        'USER': '',
        'PASSWORD': '',
        'HOST': 'sqlbeta',
        'PORT': '',
    },
}

注: これは、Django が新しいユーザーを保存する方法に関係していると思われます。そこを見に行く。両方の認証バックエンドが配置されている間に、createsuperuser コマンドを使用してスーパーユーザーを追加できます。確認しましたが、シェル経由で通常のユーザーを作成できますが、管理者経由では作成できません。

補足メモ: まだ管理者に問題の原因を突き止めていませんが、フォームからユーザーを追加できることがわかりました。問題は管理者のバグに違いないと思います。

編集:

@AndrewSmiley のリクエストによると:

Django 管理者のユーザー ビューの追加

class UserCreationForm(forms.ModelForm):
    """
    A form that creates a user, with no privileges, from the given username and
    password.
    """
    error_messages = {
        'password_mismatch': _("The two password fields didn't match."),
    }
    password1 = forms.CharField(label=_("Password"),
        widget=forms.PasswordInput)
    password2 = forms.CharField(label=_("Password confirmation"),
        widget=forms.PasswordInput,
        help_text=_("Enter the same password as above, for verification."))

    class Meta:
        model = User
        fields = ("username",)

    def clean_password2(self):
        password1 = self.cleaned_data.get("password1")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(
                self.error_messages['password_mismatch'],
                code='password_mismatch',
            )
        return password2

    def save(self, commit=True):
        user = super(UserCreationForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password1"])
        if commit:
            user.save()
        return user

アップデート:

@ user1797792 の提案に従って、カスタム UserCreationForm を作成してdate_joined値を設定しましたが、Django Admin を介してユーザーを追加することはまだできません。

関連する forms.py および admin.py エントリは以下のとおりです。

class CustomUserCreationForm(UserCreationForm):
    now = timezone.now()

    class Meta:
        model = User
        fields = ('username',)

    def save(self, commit=True):
        user = super(CustomUserCreationForm, self).save(commit=False)
        user.date_joined = self.now
        if commit:
            user.save()
        return user

class CustomUserAdmin(UserAdmin):
    add_form = CustomUserCreationForm

admin.site.unregister(User)
admin.site.register(User, CustomUserAdmin)
4

2 に答える 2

0

null 許容フィールドに問題があり、UserCreationForm にバグがあると思います。MSSQL サーバーを持っていないため、この問題を再現できません。

https://github.com/django/django/blob/1.8.6/django/contrib/auth/models.py#L185

この機能は、管理コマンドで使用されます。プロパティの timezone.now() を生成しdate_joinedますが、adminpanel の Form はオブジェクト自体で save() 関数を使用するだけで、これは行われません。

date_joined管理パネルでユーザーを作成すると、NULLのままになるようです。この列が MSSQL データベースで既定値を持っているかどうかを確認できますか? そしてNULLABLEです。そうでなく、null 許容でない場合。次に、彼らはあなたの問題を抱えています。

次に、UserCreationForm を編集する必要があります。これを行う方法を示すStackOverflow エントリを次に示します。

于 2015-11-17T10:39:53.600 に答える