/ / Validierung auf ManyToManyField vor dem Speichern in Models.py - Python, Django, Validierung, Admin

Validierung auf ManyToManyField vor dem Speichern in Models.py - python, django, validation, admin

Ich habe folgende Modelle:

class Application(models.Model):
users = models.ManyToManyField(User, through="Permission")
folder = models.ForeignKey(Folder)

class Folder(models.Model):
company = models.ManyToManyField(Compnay)

class UserProfile(models.Model):
user = models.OneToOneField(User, related_name="profile")
company = models.ManyToManyField(Company)

Was ich tun möchte, ist zu überprüfen, ob einer der Benutzer der Anwendung das gleiche Unternehmen wie die Anwendung (über Ordner) hat. Wenn dies der Fall ist, sollte die Anwendungsinstanz nicht gespeichert werden.

Das Problem besteht darin, dass die ManyToManyFields erst nach dem "post-save" -Signal aktualisiert werden.
Die einzige Option scheint das neue m2m_changed-Signal zu sein. Aber ich bin mir nicht sicher, wie ich dann die bereits erfolgte Sicherung wieder zurücknehme.
Eine andere Möglichkeit wäre, die Speicherfunktion neu zu schreiben (in models.py, weil ich hier über den Admin spreche), aber ich bin mir nicht sicher, wie ich auf den manyTomanyfield-Inhalt zugreifen könnte.
Schließlich habe ich etwas über das Neuschreiben der Speicherfunktion im admin des Modells in admin.py gelesen, aber ich würde immer noch nicht wissen, wie Sie auf den Inhalt von vielen Dateien zugreifen würden.

Ich habe überall danach gesucht, aber nichts, was mir begegnet, scheint für mich zu funktionieren.
Wenn etwas unklar ist, bitte sag es mir.

Danke für Ihre Hilfe!
Heleen

Antworten:

1 für die Antwort № 1

Da ich von Botondus keine Antwort bekommen habe, habe ich mich entschieden, eine neue Frage zu stellen Django Benutzer Google Group und bekam schließlich die Antwort von Jaymz.

Ich fand, dass Botondus Methode der richtige Weg warEs funktioniert einfach nicht. Der Grund, dass es in diesem Fall nicht funktioniert, ist, dass ich ein Through-Modell für das Feld verwende, für das ich die Validierung durchführen möchte. Aufgrund einiger früherer Rückmeldungen Bei einer zuvor geposteten Frage habe ich festgestellt, dass zuerst die Anwendungsinstanz gespeichert wird und dann die ManyToMany-Instanzen gespeichert werden (ich glaube, das ist richtig, aber korrigiere mich, wenn ich falsch liege). Also dachte ich, dass, wenn ich die Validierung für das ManyToMany-Feld im Through-Modell durchführen würde, dies nicht verhindern würde, dass die Anwendungsinstanz gespeichert wird. Aber in der Tat verhindert es das.

Wenn Sie also ein ManyToMany-Feld im Admin Ihres Modells inline haben und in diesem Feld eine Validierung durchführen möchten, geben Sie die clean-Funktion im through-Modell wie folgt an:

admin.py
class PermissionInline(admin.TabularInline):
form = PermissionForm
model = Permission
extra = 3

forms.py
class PermissionForm(forms.ModelForm):
class Meta:
model = Permission

def clean(self):
cleaned_data = self.cleaned_data
user = cleaned_data["user"]
role = cleaned_data["role"]
if role.id != 1:
folder = cleaned_data["application"].folder
if len(filter(lambda x:x in user.profile.company.all(),folder.company.all())) > 0: # this is an intersection
raise forms.ValidationError("One of the users of this Application works for one of the Repository"s organisations!")
return cleaned_data

Wenn die Überprüfung zu einem Fehler NOTHING führt (weder die Anwendungsinstanz noch die vielen Benutzer-Instanzen), wird die Möglichkeit zur Behebung des Fehlers angezeigt.


0 für die Antwort № 2

forms.py

class ApplicationForm(ModelForm):
class Meta:
model = Application

def clean(self):
cleaned_data = self.cleaned_data
users = cleaned_data["users"]
folder = cleaned_data["folder"]
if users.filter(profile__company__in=folder.company.all()).count() > 0:
raise forms.ValidationError("One of the users of this Application works in one of the Folder companies!")
return cleaned_data

admin.py

class ApplicationAdmin(ModelAdmin):
form = ApplicationForm

Bearbeiten: Das anfängliche (falsche) Modellvalidierungsbeispiel wurde durch Formularvalidierung ersetzt.