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

41voto

StefanNch Punkte 2449

Für Django 1.2+ können Sie das Feld wie folgt überschreiben:

sku = forms.CharField(widget = forms.TextInput(attrs={'readonly':'readonly'}))

6 Stimmen

Dadurch kann das Feld auch nicht zum Zeitpunkt des Hinzufügens bearbeitet werden, worum es in der ursprünglichen Frage ging.

0 Stimmen

Das ist die Antwort, nach der ich suche. Field disabled tut nicht das, was ich will, weil es das Feld deaktiviert, aber auch die Beschriftung entfernt/unsichtbar macht.

18voto

christophe31 Punkte 5977

Ich habe eine MixIn-Klasse erstellt, die Sie erben können, um ein read_only iterable-Feld hinzuzufügen, das Felder bei der nicht ersten Bearbeitung deaktiviert und sichert:

(Basierend auf Daniels und Muhuks Antworten)

from django import forms
from django.db.models.manager import Manager

# I used this instead of lambda expression after scope problems
def _get_cleaner(form, field):
    def clean_field():
         value = getattr(form.instance, field, None)
         if issubclass(type(value), Manager):
             value = value.all()
         return value
    return clean_field

class ROFormMixin(forms.BaseForm):
    def __init__(self, *args, **kwargs):
        super(ROFormMixin, self).__init__(*args, **kwargs)
        if hasattr(self, "read_only"):
            if self.instance and self.instance.pk:
                for field in self.read_only:
                    self.fields[field].widget.attrs['readonly'] = "readonly"
                    setattr(self, "clean_" + field, _get_cleaner(self, field))

# Basic usage
class TestForm(AModelForm, ROFormMixin):
    read_only = ('sku', 'an_other_field')

14voto

awalker Punkte 121

Ich bin auf ein ähnliches Problem gestoßen. Es sieht so aus, als könnte ich es lösen, indem ich eine get_readonly_fields Methode in meinem ModelAdmin Klasse.

Etwa so:

# In the admin.py file

class ItemAdmin(admin.ModelAdmin):

    def get_readonly_display(self, request, obj=None):
        if obj:
            return ['sku']
        else:
            return []

Das Schöne daran ist, dass obj ist None, wenn Sie einen neuen Artikel hinzufügen, oder es ist das zu bearbeitende Objekt, wenn Sie einen bestehenden Artikel ändern.

get_readonly_display ist dokumentiert aquí .

0 Stimmen

Ich denke get_readonly_display sollte jetzt sein get_readonly_fields ...

13voto

Danny Staple Punkte 6667

Ich habe gerade das einfachste mögliche Widget für ein schreibgeschütztes Feld erstellt - ich verstehe nicht wirklich, warum Formulare dies nicht bereits haben:

class ReadOnlyWidget(widgets.Widget):
    """Some of these values are read only - just a bit of text..."""
    def render(self, _, value, attrs=None):
        return value

In der Form:

my_read_only = CharField(widget=ReadOnlyWidget())

Sehr einfach - und bringt mir genau die richtige Leistung. Praktisch in einem Formularsatz mit einer Reihe von nur lesbaren Werten. Natürlich - man könnte auch ein bisschen schlauer sein und geben Sie es ein div mit den attrs, so dass Sie Klassen zu ihm anhängen können.

2 Stimmen

Sieht sexy aus, aber wie geht man mit Fremdschlüsseln um?

0 Stimmen

Machen Sie das unicode(value) in der Rückgabe stattdessen vielleicht. Angenommen, der Unicode-Dunder ist vernünftig, dann würden Sie das bekommen.

0 Stimmen

Für Fremdschlüssel müssen Sie ein Attribut "model" hinzufügen und "get(value)" verwenden. Prüfen Sie was ich sagen will

12voto

Ajinkya Bhosale Punkte 323

Für django 1.9+
Sie können das Argument Felder deaktiviert verwenden, um das Feld zu deaktivieren. Im folgenden Codeschnipsel aus der Datei forms.py habe ich z. B. das Feld employee_code deaktiviert

class EmployeeForm(forms.ModelForm):
    employee_code = forms.CharField(disabled=True)
    class Meta:
        model = Employee
        fields = ('employee_code', 'designation', 'salary')

Referenz https://docs.djangoproject.com/en/dev/ref/forms/fields/#disabled

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