2 Stimmen

Python/Django BooleanField-Modell mit RadioSelect-Formular, das standardmäßig leer ist

Ich verwende eine Django ModelForm, wo mein Modell ein BooleanField enthält und das Formular-Widget, das mit diesem BooleanField verbunden ist, ist ein RadioSelect-Widget. Ich möchte das RadioSelect-Widget, das gerendert, um keine Optionen ausgewählt haben, so dass der Benutzer explizit eine Auswahl zu treffen, aber die Formularvalidierung fehlschlagen, wenn Sie keine Auswahl treffen. Gibt es eine Möglichkeit, dies zu tun?

models.py

myboolean = models.BooleanField(choices=YES_NO)

formulare.py

class myModelForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(myModelForm, self).__init__(*args, **kwargs)
        self.fields['myboolean'].widget = forms.RadioSelect(choices=YES_NO)

6voto

Andrey Fedoseev Punkte 4892

Ihr Code tut tatsächlich, was Sie brauchen. Er rendert die Optionsfelder ohne ausgewählte Optionen und erzeugt die Fehlermeldung, wenn nichts ausgewählt ist.

Eine kleine Anmerkung zu Ihrem Formularcode. Ich würde es so machen:

class myModelForm(forms.ModelForm):

    myboolean = forms.BooleanField(widget=forms.RadioSelect(choices=YES_NO))

    class Meta:
        model = MyModel

0 Stimmen

Vielen Dank, Andrey. Nachdem ich deine Lösung gesehen habe, habe ich meine Situation noch einmal überprüft und festgestellt, dass mein vereinfachtes Beispiel eine wichtige Information auslässt. Eine ModelField-Überschreibung, die vorhanden war, hat den Standardwert beeinträchtigt. Aus diesem Problem habe ich gelernt, dass bei RadioSelect-Feldern default=None gesetzt zu sein scheint. Die Überschreibung, die ich vorgenommen hatte, setzte den Standardwert auf False. (Übrigens habe ich die init Funktion, weil ich keine vom Modell festgelegten Standardwerte, wie z. B. label, übertrumpfen wollte).

0 Stimmen

Ich danke Ihnen nochmals für Ihre Hilfe und entschuldige mich für das schlechte Beispiel. Ich habe versucht, das Problem auf seinen Kern zu reduzieren, habe aber einige Informationen übersehen.

2voto

KeithL Punkte 1130

Leider ist dies weniger ein Django-Problem als eine HTML-Frage. Die HTML-Spezifikation (RFC1866) sagt:

At all times, exactly one of the radio buttons in a set is checked. Wenn keines der <INPUT>-Elemente eines Satzes von Optionsfeldern die Angabe `CHECKED' enthält, muss der User Agent zunächst das erste Optionsfeld des Satzes prüfen.

In der Vergangenheit haben die Browser dies jedoch ignoriert und die Optionsfelder auf unterschiedliche Weise implementiert.

HTML macht dies auch deshalb schwierig, weil das "checked"-Attribut des <INPUT>-Tags keinen Parameter akzeptiert, so dass Sie kein angepasstes Django-Widget verwenden können, das dieses Attribut auf False oder No setzt.

Eine mögliche Abhilfe besteht darin, ein kleines Javascript einzufügen, das als Teil des onLoad-Ereignisses des Dokuments ausgeführt wird und alle Optionsschaltflächen auf der Seite findet und das Attribut "checked" auf false setzt (z. B. mit JQuery).

0 Stimmen

Mir gefällt die Lösung mit dem Javascript, um die angekreuzten Werte zu löschen. Meine einzige Befürchtung ist, dass Django sich nicht über die leeren Radio-Button-Boxen beschweren wird und sie als false auswertet. Ich würde lieber einen Validierungsfehler werfen.

0 Stimmen

Wie Andrey weiter unten erwähnt, sollte Django einen Validierungsfehler ausgeben, wenn ein Optionsfeld nicht ausgewählt ist, da "required" standardmäßig auf True gesetzt ist.

0 Stimmen

Das ist gut zu wissen. Ich war mir nicht sicher, wie sich ein BooleanField auf das RadioSelect-Widget auswirken würde, da es scheint, dass viele Beispiele, die ich gefunden habe, ein IntegerField verwenden. Vielen Dank für Ihren Beitrag.

1voto

Mehran Punkte 1841

0voto

eri Punkte 2807

Ich erstelle ein benutzerdefiniertes Feld mit einem Standard-Widget.

Ausschnitt aus meiner models.py:

class Order(models.Model):
    ...
    # transport =  models.CharField(choices=transport.choices,max_length=25,null=True)
    transport = SelectField(choices=transport.choices,max_length=25,null=True)
    ...

Definition des Feldes:

from django.db import models
from django.forms import widgets

class SelectField(models.CharField):
    def formfield(self, **kwargs):
        if self._choices:
            defaults = {'widget': widgets.RadioSelect}
        defaults.update(kwargs)
        return super(SelectField, self).formfield(**defaults)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X