2015-10-29 10 views
8

Wir haben eine Django-Anwendung, die eine Verbindung zu mehreren MS SQL-Datenbankinstanzen herstellt. Für jede App gibt es eine router.py, die die Prozesse an jede Datenbank weiterleitet.Django mit mehreren Datenbanken und appspezifischen Routern, kann keine Benutzer in MSSQL hinzufügen

Dies ist das erste Mal Einrichten mehrerer Datenbankzugriff.

Django integrierten Apps sind auf der Standarddatenbank über diese router.py geroutet:

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 

Wir verwenden LDAP-Authentifizierung und Djangos integrierte Authentifizierung. Die Idee ist, dass Intranet-Benutzer sich gegen unseren AD-Server authentifizieren können. Externe Benutzer können sich registrieren und werden mit Djangos Authentifizierung authentifiziert.

Wenn ich den Standard-Datenbank-Satz muß:

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

LDAP funktioniert, aber ich kann nicht vom Benutzer zu Djangos Authentifizierung hinzufügen. Der Administrator zeigt eine "Erfolg" -Nachricht an, der Benutzer wird jedoch nicht zur Datenbank hinzugefügt.

Wenn ich die Standarddatenbank zurück zu SQLLite verschiebe, kann ich mich gegen AD authentifizieren und Django-Benutzer hinzufügen.

Also, ich glaube nicht, dass es ein Problem mit der Datei routers.py ist. Ich befürchte, dass dies ein Problem mit der Engine 'sql_server.pyodbc' sein könnte.

EDIT: pro Anfrage, hier sind die Datenbankeinstellungen:

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': '', 
    }, 
} 

HINWEIS: ich denke, das könnte mit der Art und Weise zu tun hat Django neue Benutzer speichert. Ich werde dort nachsehen. Ich kann den Befehl createsuperuser verwenden, um weitere Superuser hinzuzufügen, während beide Authentifizierungs-Backends vorhanden sind. Bestätigt, kann ich normale Benutzer über die Shell erstellen, aber nicht über den Admin.

Follow-up Hinweis: Noch habe nicht das Problem mit dem Admin, aber ich fand, dass ich Benutzer über ein Formular hinzufügen konnte. Ich denke, das Problem muss ein Fehler im Admin sein.

Edit:

Pro @ AndrewSmiley Wunsch:

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 

UPDATE:

Per @ user1797792 Vorschläge, ich eine benutzerdefinierte UserCreationForm erstellt den date_joined Wert zu setzen, aber Wir können weiterhin keine Nutzer über den Django Admin hinzufügen.

Relevante forms.py & admin.py Einträge sind unten:

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

Ich bin mir nicht sicher, dass es helfen wird, aber können Sie Ihre gesamte Datenbank einstellen? –

+0

@TitusP, Ich habe die gesamte Datenbankkonfiguration hinzugefügt. Ich bin bei dir, nicht sicher, ob das irgendwas hilft. –

+0

Sie haben die gleiche 'app_list' mehrfach definiert, warum definieren Sie sie nicht in der Klasse? Und hast du Admin-Code oder benutzt du Djangos Standard-Admin? – Uri

Antwort

0

Nach der Befolgung aller Vorschläge, die über die Kommentare und Antworten eingereicht wurden. Wir stellten fest, dass das Problem ein undokumentierter Fehler in der Bibliothek django-pyodbc-azure ist.

Nachdem wir eine PostgreSQL-Datenbank gestartet und unsere Django-App verbunden hatten, konnten wir diesen Fehler nicht erneut erstellen. Wir haben auch FreeTDS/ODBC-Treiber verwendet, um mit der MSSQL-Datenbank zu kommunizieren, und konnten sie nicht neu erstellen.

0

Ich denke, ein Problem mit Nullable-Feldern gibt es, und ein Fehler in der UserCreationForm. Ich kann dieses Problem nicht replizieren, da ich keinen MSSQL-Server habe.

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

Diese Funktion wird durch den Verwaltungsbefehl verwendet. Es generiert eine timezone.now() für die Eigenschaft date_joined, während das Formular im Adminpanel nur die Funktion save() für das Objekt selbst verwendet, was dies nicht tut.

date_joined scheint NULL zu bleiben, wenn Sie einen Benutzer im Admin-Panel erstellen. Können Sie überprüfen, ob diese Spalte einen Standardwert in der MSSQL-Datenbank hat? Und ist NULLBAR. Wenn nicht, und es ist nicht nullfähig. Dann liegt ihr Problem.

Dann sollten Sie das UserCreationForm bearbeiten. Here is a StackOverflow entry zeigt Ihnen, wie Sie dies tun.

+0

Sie haben Recht. In MSSQL ist date_joined nicht nullfähig und es fehlt ein Standardwert. Bearbeitet das UserCreationForm und postet ein Update. –