Django erforderliches Feld in Modellform

72

Ich habe ein Formular, in dem einige Felder nach Bedarf angezeigt werden, wenn ich sie auch nicht möchte. Hier ist das Formular von models.py

class CircuitForm(ModelForm):
    class Meta:
        model = Circuit
        exclude = ('lastPaged',)
    def __init__(self, *args, **kwargs):
        super(CircuitForm, self).__init__(*args, **kwargs)
        self.fields['begin'].widget = widgets.AdminSplitDateTime()
        self.fields['end'].widget = widgets.AdminSplitDateTime()

Im tatsächlichen Schaltungsmodell sind die Felder wie folgt definiert:

begin = models.DateTimeField('Start Time', null=True, blank=True)
end = models.DateTimeField('Stop Time', null=True, blank=True)

Meine views.py dafür ist hier:

def addCircuitForm(request):
    if request.method == 'POST':
        form = CircuitForm(request.POST)
        if form.is_valid():
            form.save()
            return HttpResponseRedirect('/sla/all')
    form = CircuitForm()    
    return render_to_response('sla/add.html', {'form': form})

Was kann ich tun, damit die beiden Felder nicht benötigt werden?

Ryan
quelle
1
Es gibt keine Möglichkeit, dass diese Felder durch Ändern der Widgets benötigt werden. Wenn models (null = True, blank = True) hat, rendert modelForm es wie erforderlich = False.
simplyharsh
Sieht so aus, als hättest du recht. Die Felder selbst sind nicht erforderlich, aber die Felder Datum und Uhrzeit im Widget sind erforderlich.
Ryan

Antworten:

113

Wenn Sie die Leereinstellungen für Ihre Felder in Modellen nicht ändern möchten (dies führt zu einer Unterbrechung der normalen Validierung auf der Administrationssite), können Sie in Ihrer Formularklasse Folgendes tun:

def __init__(self, *args, **kwargs):
    super(CircuitForm, self).__init__(*args, **kwargs)

    for key in self.fields:
        self.fields[key].required = False 

Der neu definierte Konstruktor beeinträchtigt keine Funktionalität.

DataGreed
quelle
17

Wenn das Modellfeld leer = True ist, wird im Formularfeld "Erforderlich" auf "Falsch" gesetzt. Andernfalls erforderlich = True

Sagt so hier: http://docs.djangoproject.com/de/dev/topics/forms/modelforms/

Sieht so aus, als ob Sie alles richtig machen. Sie können den Wert von überprüfen self.fields['end'].required.

stefanw
quelle
Beachten Sie, dass einige Felder (z. B. BooleanField) in ihrem Konstruktor leer = True fest codiert sind ( docs.djangoproject.com/de/dev/_modules/django/db/models/fields/… ). Wenn Sie also leer = Falsch setzen, schlägt dies stillschweigend fehl. Sie müssen self.fields[…].required = Trueim Konstruktor des Formulars verwenden, um das erforderliche Verhalten für diese Felder zu erzwingen. Siehe auch code.djangoproject.com/ticket/22282 .
Edward D'Souza
8

Als Erweiterung der Antwort von DataGreed habe ich ein Mixin erstellt, mit dem Sie eine fields_requiredVariable für die MetaKlasse wie folgt angeben können:

class MyForm(RequiredFieldsMixin, ModelForm):

    class Meta:
        model = MyModel
        fields = ['field1', 'field2']
        fields_required = ['field1']

Hier ist es:

class RequiredFieldsMixin():

    def __init__(self, *args, **kwargs):

        super().__init__(*args, **kwargs)

        fields_required = getattr(self.Meta, 'fields_required', None)

        if fields_required:
            for key in self.fields:
                if key not in fields_required:
                    self.fields[key].required = False
Gitaarik
quelle
Was passiert, wenn der Benutzer dieses Mixins ebenfalls überschreibt __init__? Wird das Mixin noch funktionieren? Wie wird die Mehrfachvererbung aufgelöst?
user3599803
@ user3599803 Wenn Sie überschreiben __init__, sollten Sie immer anrufen super(), wie es in meinem Snippet gemacht wird.
Gitaarik
Wenn ich das verstehe, erstelle ich ein Formular und eine Unterklasse von MyForm. Ich rufe super von init () auf, was das mixin init aufruft, aber wann wird djangl form init aufgerufen?
user3599803
Ja, es gibt andere Ressourcen, die dies diskutieren. Sie können auch eine neue Frage erstellen, wenn Sie möchten. Bitte behalten Sie die Kommentare hier zum Thema dieser speziellen Frage bei.
Gitaarik
3

Es ist keine Antwort, aber für alle anderen, die dies über Google finden, noch ein Datenelement: Dies passiert mir auf einem Modellformular mit einem DateField. Es muss auf False gesetzt sein, das Modell hat "null = True, blank = True" und das Feld im Formular zeigt "required = False" an, wenn ich es während der clean () -Methode betrachte, aber es heißt immer noch, dass ich ein gültiges Datum benötige Format. Ich verwende kein spezielles Widget und erhalte die Meldung "Geben Sie ein gültiges Datum ein", auch wenn ich explizit input_formats = ['% Y-% m-% d', '% m /% d /% Y', 'gesetzt habe. % m /% d /% y ',' '] im Formularfeld.

EDIT: Ich weiß nicht, ob es jemand anderem helfen wird, aber ich habe das Problem gelöst, das ich hatte. Unser Formular enthält einen Standardtext im Feld (in diesem Fall ist das Wort "bis", um das Feld anzugeben, das Enddatum; das Feld heißt "end_time"). Ich habe speziell nach dem Wort "to" in der clean () -Methode des Formulars gesucht (ich hatte auch die clean_end_time () -Methode ausprobiert, aber sie wurde nie aufgerufen) und den Wert der clean_data-Variablen auf None gesetzt, wie in diesem Django vorgeschlagen Ticket . Nichts davon war jedoch von Bedeutung, da (ich denke) die Validierung des Modells bereits auf das ungültige Datumsformat "bis" gekotzt hatte, ohne mir die Möglichkeit zu geben, es abzufangen.

Tom
quelle
0

Aus dem Modellfeld Dokumentation ,

Wenn Sie ein Modell wie unten gezeigt haben,

class Article(models.Model):
    headline = models.CharField(
        max_length=200,
        null=True,
        blank=True,
        help_text='Use puns liberally',
    )
    content = models.TextField()

Sie können die Formularvalidierung der Überschrift in required=Trueanstelle der blank=Falsedes Modells ändern, indem Sie das Feld wie unten gezeigt definieren.

class ArticleForm(ModelForm):
    headline = MyFormField(
        max_length=200,
        required=False,
        help_text='Use puns liberally',
    )

    class Meta:
        model = Article
        fields = ['headline', 'content']

Also beantworte die Frage,

class CircuitForm(ModelForm):
    begin = forms.DateTimeField(required=False)
    end = forms.DateTimeField(required=False)
        class Meta:
            model = Circuit
            exclude = ('lastPaged',)

das macht beginund endzurequired=False

Alles ist gut
quelle