2015-10-29 9 views
8

複数のMS SQLデータベースインスタンスに接続しているDjangoアプリケーションがあります。各アプリケーションには、各データベースへのプロセスのルーティングを処理するrouter.pyがあります。複数のデータベースとアプリケーション固有のルータを持つDjangoは、MSSQLのユーザを追加できません

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

Djangoの組み込みのアプリケーションは、このrouter.pyを経由して、デフォルトのデータベースにルーティングされています。私たちは、LDAP認証を使用し、Djangoの認証ビルトインされている

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 

。アイデアは、イントラネットユーザーがADサーバーに対して認証できるということです。外部ユーザーは登録でき、Djangoの認証で認証されます。

私が設定されているデフォルトのデータベースがあります。

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

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

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

私はrouterers.pyファイルの問題ではないと思います。私はそれが 'sql_server.pyodbc'エンジンの問題かもしれないと心配しています。

EDIT:要求ごと 、ここでは、データベースの設定は次のとおりです。

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の要求パー

:UPDATE Django Admin Add User View

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 @パー

、私はdate_joined値を設定するためのカスタムUserCreationFormを作成したが、私たちはまだDjango管理者経由でユーザーを追加することはできません。

関連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) 
+0

私はそれが助けになるとは確信していませんが、データベース全体の設定を投稿できますか? –

+0

@TitusP、データベース全体の設定を追加しました。私はあなたと一緒にいますが、それが助けになるかどうかわかりません。 –

+0

あなたは同じ 'app_list'を複数回定義していますが、それをクラスで定義してみませんか?あなたは管理者コードを持っていますか、またはDjangoのデフォルトの管理者を使用していますか? – Uri

答えて

0

コメントと回答を介して提出されたすべての提案に従った後。この問題は、django-pyodbc-azureライブラリの文書化されていないバグだと認識しました。

PostgreSQLデータベースをスピンアップしてDjangoアプリに接続した後、このバグを再現できませんでした。また、FreeTDS/ODBCドライバを使用してMSSQLデータベースと対話し、再作成できませんでした。

0

私はNULL可能フィールドを持つ問題、およびUserCreationFormにバグがあると思います。私はMSSQLサーバを持っていないので、この問題を再現することはできません。

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

この機能は、管理コマンドによって使用されています。 date_joinedプロパティのtimezone.now()を生成しますが、adminパネルのFormはオブジェクト自体に対してsave()関数を使用しますが、これはこれを行いません。

date_joinedは、管理パネルでユーザーを作成するとNULLのままになっているようです。この列にMSSQLデータベースのデフォルト値があるかどうか確認できますか?そしてNULLABLEです。 そうでなければ、それはヌル可能ではありません。それで彼らはあなたの問題を抱きます。

次に、UserCreationFormを編集する必要があります。 Here is a StackOverflow entryこれを行う方法を示しています。

+0

あなたは正しいです。 in MSSQL date_joinedはNULL可能ではなく、デフォルト値がありません。 UserCreationFormを編集して更新を投稿します。 –

関連する問題