532 Stimmen

Wie kann ich in einem Django-Formular ein Feld schreibgeschützt (oder deaktiviert) machen, damit es nicht bearbeitet werden kann?

Wie kann ich in einem Django-Formular ein Feld schreibgeschützt (oder deaktiviert) machen?

Wenn das Formular zum Erstellen eines neuen Eintrags verwendet wird, sollten alle Felder aktiviert sein - wenn sich der Datensatz jedoch im Aktualisierungsmodus befindet, müssen einige Felder schreibgeschützt sein.

Wenn Sie zum Beispiel eine neue Item Modell müssen alle Felder bearbeitbar sein, aber gibt es eine Möglichkeit, während der Aktualisierung des Datensatzes die sku Feld, so dass es zwar sichtbar ist, aber nicht bearbeitet werden kann?

class Item(models.Model):
    sku = models.CharField(max_length=50)
    description = models.CharField(max_length=200)
    added_by = models.ForeignKey(User)

class ItemForm(ModelForm):
    class Meta:
        model = Item
        exclude = ('added_by')

def new_item_view(request):
    if request.method == 'POST':
        form = ItemForm(request.POST)
        # Validate and save
    else:
            form = ItemForm()
    # Render the view

Kann Klasse ItemForm wiederverwendet werden? Welche Änderungen wären erforderlich in der ItemForm o Item Modellklasse? Müsste ich eine weitere Klasse schreiben, " ItemUpdateForm ", um den Artikel zu aktualisieren?

def update_item_view(request):
    if request.method == 'POST':
        form = ItemUpdateForm(request.POST)
        # Validate and save
    else:
        form = ItemUpdateForm()

1 Stimmen

Siehe auch SO Frage: Warum sind schreibgeschützte Formularfelder in Django eine schlechte Idee? @ stackoverflow.com/questions/2902024 Die akzeptierte Antwort (von Daniel Naab) kümmert sich um bösartige POST-Hacks.

0 Stimmen

10voto

Lucas B Punkte 1848

Wie ich das mit Django 1.11 mache:

class ItemForm(ModelForm):
    disabled_fields = ('added_by',)

    class Meta:
        model = Item
        fields = '__all__'

    def __init__(self, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        for field in self.disabled_fields:
            self.fields[field].disabled = True

0 Stimmen

Dies wird nur von fronted blockiert. jeder kann es umgehen. dies wird ein sicherheitsproblem sein, wenn sie mit sensiblen daten arbeiten

2 Stimmen

Es ist sicher; es blockiert auch im Backend seit Django >= 1.10 docs.djangoproject.com/de/1.10/ref/forms/fields/

0 Stimmen

Vielen Dank, es hat viel Zeit gespart und hat auch eine Validierung im Backend!

6voto

JamesD Punkte 601

Ich werde noch eine weitere Lösung anbieten :) Ich benutzte Humphreys Code Das hier basiert also darauf.

Ich hatte jedoch Probleme damit, dass das Feld ein ModelChoiceField . Bei der ersten Anfrage funktionierte alles. Wenn der Formularsatz jedoch versuchte, ein neues Element hinzuzufügen und die Validierung fehlschlug, lief etwas mit den "vorhandenen" Formularen schief, in denen die SELECTED wurde auf den Standardwert zurückgesetzt --------- .

Wie auch immer, ich konnte nicht herausfinden, wie man das beheben kann. Also habe ich stattdessen (und ich denke, das ist tatsächlich sauberer in der Form), die Felder HiddenInputField() . Das bedeutet nur, dass Sie ein wenig mehr Arbeit in die Vorlage stecken müssen.

Die Lösung für mich bestand also darin, das Formular zu vereinfachen:

class ItemForm(ModelForm):

    def __init__(self, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.id:
            self.fields['sku'].widget=HiddenInput()

Und dann müssen Sie in der Vorlage einige manuelle Schleifenbildung des Formularsatzes .

In diesem Fall würden Sie in der Vorlage also etwa so vorgehen:

<div>
    {{ form.instance.sku }} <!-- This prints the value -->
    {{ form }} <!-- Prints form normally, and makes the hidden input -->
</div>

Das funktionierte bei mir etwas besser und mit weniger Formularmanipulation.

6voto

Sourabh SInha Punkte 1974

Sie können elegant readonly in das Widget einfügen:

class SurveyModaForm(forms.ModelForm):
    class Meta:
        model  = Survey
        fields = ['question_no']
        widgets = {
        'question_no':forms.NumberInput(attrs={'class':'form-control','readonly':True}),
        }

6voto

alzclarke Punkte 1677

Eine einfache Möglichkeit besteht darin, einfach Folgendes einzugeben form.instance.fieldName in der Vorlage anstelle von form.fieldName .

0 Stimmen

Und was ist mit der verbos_name o label des Feldes? Wie kann ich `Label in django Template anzeigen? @alzclarke

5voto

Madis Punkte 401

Da ich noch keinen Kommentar abgeben kann ( Muhuks Lösung ), werde ich in einer separaten Antwort antworten. Dies ist ein vollständiges Code-Beispiel, das bei mir funktioniert hat:

def clean_sku(self):
  if self.instance and self.instance.pk:
    return self.instance.sku
  else:
    return self.cleaned_data['sku']

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