2016-07-15 12 views
1

In der Admin-Site habe ich ein benutzerdefiniertes Formular. Ich möchte jedoch die Speichermethode überschreiben, so dass, wenn ein bestimmtes Schlüsselwort eingegeben wird, ich es nicht in der Datenbank speichern werde. Ist das möglich?Django Admin-Site ändern speichern

class MyCustomForm (forms.ModelForm): 

    def save(self, commit=True): 
     input_name = self.cleaned_data.get('input_name', None) 
     if input_name == "MyKeyword": 
      //Do not save 
     else: 
      return super(MyCustomForm, self).save(commit=commit) 

aber dies gibt den Fehler:

AttributeError 'NoneType' object has no attribute 'save' 

bearbeiten Danach: Overriding the save method in Django ModelForm

Ich habe versucht:

def save(self, force_insert=False, force_update=False, commit=True): 
    m = super(MyCustomCategoryForm, self).save(commit=False) 
    input_name = self.cleaned_data.get('input_name', None) 
    if input_name != "MyKeyword": 
     m.save() 
    return m  

Aber die Admin-Seite schafft noch eine neue Eingabe wenn die Eingabe _name ist "MyKeyword"

+0

Also, was ist falsch mit diesem Code? Sie können es vereinfachen, indem Sie die Bedingung in 'if input_name! =" MyKeyword "ändern: super (MyCustomForm, self) .save (commit = commit)', aber ansonsten sollte es so funktionieren, wie Sie es geschrieben haben. – xbello

+0

Ich habe das versucht, aber der Fehler ist: AttributError 'NoneType' Objekt hat kein Attribut 'Speichern' – Rueen1963

+0

Dann gibt Ihr ModelForm möglicherweise nicht das Objekt, das gespeichert wird: es gibt "None" zurück. Lesen Sie diese Antwort http://stackoverflow.com/a/817364/1688590. – xbello

Antwort

1

Die Methode save() soll das Objekt zurückgeben, ob gespeichert oder nicht. Es sollte eher wie folgt aussehen:

def save(self, commit=True): 
    input_name = self.cleaned_data.get('input_name') 
    if input_name == "MyKeyword": 
     commit = False 
    return super().save(commit=commit) 

Doch wie Sie here und here sehen können, wird das Formular bereits genannt mit commit=False und das Objekt wird später durch die save_model() Methode Ihrer ModelAdmin gespeichert. Dies ist der Grund, warum Sie AttributeError 'NoneType' object has no attribute 'save' bekommen haben. Wenn Sie die Rückverfolgung der Ausnahme überprüfen, bin ich ziemlich sicher, dass der Fehler von this line kommt.

So sollten Sie, aber auch außer Kraft setzen Ihre ModelAdmin ‚s save_model() Methode:

def save_model(self, request, obj, form, change): 
    if form.cleaned_data.get('input_name') == 'MyKeyword': 
     return # Don't save in this case 
    super().save_model(request, obj, form, change) 

# And you'll also have to override the `ModelAdmin`'s `save_related()` method 
# in the same flavor: 

def save_related(self, request, form, formsets, change): 
    if form.cleaned_data.get('input_name') == 'MyKeyword': 
     return # Don't save in this case 
    super().save_related(request, form, formsets, change) 

Gegeben Ihren Kommentar in dieser Antwort

It is working now but I just have one related question. The admin site will still display a green banner at the top saying "The model was added successfully". Can I override some method so that it is red and says "The model already exists"?

Es sieht aus, dass, was Sie wollen zu tun ist nicht überschreiben die Speichermethode aber controlling form validation. Was ist ganz anders. Sie müssen nur die clean-Methode Ihres Formulars überschreiben.

from django import forms 

def clean(self): 
    """ 
    super().clean() 
    if self.cleaned_data.get('input_name') == 'MyKeyword': 
     raise forms.ValidationError("The model already exists") 

Oder, noch besser, da es, wie Sie wollen clean a single field aussieht: Ich denke, input_name ist auch ein Feld des Modells

from django import form 

def clean_input_name(self): 
    data = self.cleaned_data['input_name'] 
    if data == 'MyKeyWord': 
     raise forms.ValidationError("The model already exists") 

jedoch und Sie nicht wollen, dies zu erheben Fehler nur auf einem Formular, aber über Ihr gesamtes Projekt hinweg. In diesem Fall, was Sie suchen, sind Model validators:

from django.core.exceptions import ValidationError 

def validate_input_name(value): 
    if value == 'MyKeyword': 
     raise ValidationError("The model already exists") 
+0

Es funktioniert jetzt, aber ich habe nur eine verwandte Frage. Die Admin-Site zeigt oben immer noch ein grünes Banner an: "Das Modell wurde erfolgreich hinzugefügt".Kann ich eine Methode überschreiben, so dass sie rot ist und "Das Modell existiert bereits" sagt? – Rueen1963

+0

Sicher kannst du. Aber es sieht wirklich so aus, als ob das nicht wirklich das ist, was du machen willst. Warum haben Sie nicht von Anfang an gesagt, dass Sie die Formularvalidierung kontrollieren wollen? Bitte sehen Sie [was ist das XY-Problem] (http://meta.stackexchange.com/questions/66377/what-is-the-xy-problem) und das Update in meiner Antwort. Willst du wirklich einen Fehler auslösen, wenn 'input_name' auf ** ein Schlüsselwort ** gesetzt ist? Oder ist ** Variable? ** Vielleicht eine ** Liste von Schlüsselwörtern? ** Vielleicht ein Daten ** aus der Datenbank abgerufen? ** Vielleicht möchten Sie nur dieses Feld ** einzigartig? ** Wenn ja, warum bist du Bemühen Sie sich, wichtige Informationen zu Ihrem Problem zu verstecken? –