W formie Django, jak zrobić pole tylko do odczytu (lub wyłączone), aby nie mogło być edytowane?

W formie Django, jak zrobić pole tylko do odczytu (lub wyłączone)?

Gdy formularz jest używany do tworzenia nowego wpisu, wszystkie pola powinny być włączone - ale gdy rekord jest w trybie aktualizacji, niektóre pola muszą być tylko do odczytu.

Na przykład, podczas tworzenia nowego modelu Item wszystkie pola muszą być edytowalne, ale podczas aktualizacji rekordu, czy istnieje sposób, aby wyłączyć pole sku tak, aby było widoczne, ale nie może być edytowane?

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

Czy klasa ItemForm może być ponownie użyta? Co? zmiany byłyby wymagane w klasie modelu ItemForm lub Item? Czy muszę napisać inną klasę, " ItemUpdateForm", do aktualizacji elementu?

def update_item_view(request):
    if request.method == 'POST':
        form = ItemUpdateForm(request.POST)
        # Validate and save
    else:
        form = ItemUpdateForm()
Author: phoenix, 2008-11-27

26 answers

Jak wskazano w tej odpowiedzi , Django 1.9 dodał pole .disabled atrybut:

Wyłączony argument logiczny, gdy jest ustawiony na True, wyłącza pole formularza używając wyłączonego atrybutu HTML, aby nie było edytowalne przez użytkowników. Nawet jeśli użytkownik manipuluje wartością pola przekazaną do serwera, zostanie ona zignorowana na rzecz wartości z początkowych danych formularza.

Z Django 1.8 i wcześniejszymi, aby wyłączyć wpis w widżecie i zapobieganie złośliwym hakerom musisz wyczyścić dane wejściowe oprócz ustawienia atrybutu readonly w polu formularza:

class ItemForm(ModelForm):
    def __init__(self, *args, **kwargs):
        super(ItemForm, self).__init__(*args, **kwargs)
        instance = getattr(self, 'instance', None)
        if instance and instance.pk:
            self.fields['sku'].widget.attrs['readonly'] = True

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

Lub zastąp if instance and instance.pk innym warunkiem wskazującym, że edytujesz. Możesz również ustawić atrybut disabled w polu wprowadzania, zamiast readonly.

Funkcja clean_sku zapewni, że wartość readonly nie zostanie nadpisana przez POST.

W Przeciwnym Razie, nie ma wbudowanego pola formularza Django, które wyrenderuje wartość podczas odrzucania powiązanych danych wejściowych. Jeśli tego pragniesz, powinieneś zamiast tego utworzyć oddzielną ModelForm, która wyklucza nieedytowalne pola i po prostu wydrukować je wewnątrz szablonu.

 360
Author: Daniel Naab,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:42

Django 1.9 dodało pole.atrybut wyłączony: https://docs.djangoproject.com/en/1.9/ref/forms/fields/#disabled

Wyłączony argument logiczny, gdy jest ustawiony na True, wyłącza pole formularza przy użyciu wyłączonego atrybutu HTML, aby nie było edytowalne przez użytkowników. Nawet jeśli użytkownik manipuluje wartością pola przekazaną do serwera, zostanie ona zignorowana na rzecz wartości z początkowych danych formularza.

 147
Author: Mike Mahmud,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-31 18:05:34

Ustawienie READONLY na widżecie powoduje, że wejście w przeglądarce jest tylko do odczytu. Dodanie clean_sku, które zwraca instancję.sku zapewnia, że wartość pola nie zmieni się na poziomie formularza.

def clean_sku(self):
    if self.instance: 
        return self.instance.sku
    else: 
        return self.fields['sku']

W ten sposób można użyć modelu (niezmodyfikowany zapis) i aviod uzyskanie pola wymaganego błędu.

 91
Author: muhuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-09 17:58:10

Odpowiedź Awalkera bardzo mi pomogła!

Zmieniłem jego przykład do pracy z Django 1.3, używając get_readonly_fields.

Zazwyczaj powinieneś zadeklarować coś takiego w app/admin.py:

class ItemAdmin(admin.ModelAdmin):
    ...
    readonly_fields = ('url',)

Zaadaptowałem się w ten sposób:

# In the admin.py file
class ItemAdmin(admin.ModelAdmin):
    ...
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return ['url']
        else:
            return []
I działa dobrze. Jeśli dodasz element, pole url jest odczyt-zapis, ale po zmianie staje się tylko do odczytu.
 60
Author: chirale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:47:36

Aby to działało dla pola ForeignKey, należy wprowadzić kilka zmian. Po pierwsze, znacznik HTML SELECT nie ma atrybutu readonly. Zamiast tego musimy użyć disabled= "disabled". Jednak wtedy przeglądarka nie wysyła żadnych danych formularza z powrotem dla tego pola. Musimy więc ustawić to pole tak, aby nie było wymagane, aby pole walidowało się poprawnie. Następnie musimy zresetować wartość z powrotem do tego, co było kiedyś, więc nie jest ustawiona na puste.

Więc dla kluczy obcych trzeba będzie zrobić coś w stylu:

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'].required = False
            self.fields['sku'].widget.attrs['disabled'] = 'disabled'

    def clean_sku(self):
        # As shown in the above answer.
        instance = getattr(self, 'instance', None)
        if instance:
            return instance.sku
        else:
            return self.cleaned_data.get('sku', None)

W ten sposób przeglądarka nie pozwoli użytkownikowi zmienić pola i zawsze będzie publikować, ponieważ zostało pozostawione puste. Następnie nadpisujemy metodę clean, aby ustawić wartość pola na taką, jaka była pierwotnie w instancji.

 49
Author: Humphrey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-05 16:56:17

Dla Django 1.2+, możesz nadpisać pole w następujący sposób:

sku = forms.CharField(widget = forms.TextInput(attrs={'readonly':'readonly'}))
 22
Author: StefanNch,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:26:02

Stworzyłem klasę MixIn, którą możesz dziedziczyć, aby móc dodać pole read_only iterowalne, które wyłączy i zabezpieczy pola w nie - pierwszej edycji:

(na podstawie odpowiedzi Daniela i Muhuka)

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')
 16
Author: christophe31,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:30:27

Właśnie stworzyłem najprostszy możliwy widget dla pola readonly - nie bardzo rozumiem, dlaczego formularze nie mają tego już:

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

W formie:

my_read_only = CharField(widget=ReadOnlyWidget())

Bardzo proste - i daje mi tylko wyjście. Przydatne w zestawie formularzy z kilkoma wartościami tylko do odczytu. Oczywiście - możesz też być trochę bardziej sprytny i dać mu div z attrami, abyś mógł dołączyć do niego klasy.

 10
Author: Danny Staple,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-28 11:46:27

Natknąłem się na podobny problem. Wygląda na to, że udało mi się go rozwiązać definiując metodę "get_readonly_fields" w mojej klasie ModelAdmin.

Coś takiego:

# In the admin.py file

class ItemAdmin(admin.ModelAdmin):

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

Fajną rzeczą jest to, że obj będzie Brak, gdy dodajesz nowy element, lub będzie to edytowany Obiekt, gdy zmieniasz istniejący element.

Get_readonly_display jest udokumentowany tutaj: http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#modeladmin-methods

 9
Author: awalker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-08 20:51:34

Jako przydatny dodatek do postu , miałem pewne problemy z django-reversion, ponieważ wciąż zarejestrowało wyłączone pola jako 'changed'. Poniższy kod rozwiązuje problem.

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'].required = False
            self.fields['sku'].widget.attrs['disabled'] = 'disabled'

    def clean_sku(self):
        # As shown in the above answer.
        instance = getattr(self, 'instance', None)
        if instance:
            try:
                self.changed_data.remove('sku')
            except ValueError, e:
                pass
            return instance.sku
        else:
            return self.cleaned_data.get('sku', None)
 5
Author: Evan Brumley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:19

Ponieważ nie mogę jeszcze skomentować (rozwiązanie muhuka ), odpowiem jako osobna odpowiedź. Jest to kompletny przykład kodu, który zadziałał dla mnie:

def clean_sku(self):
  if self.instance and self.instance.pk:
    return self.instance.sku
  else:
    return self.cleaned_data['sku']
 5
Author: Madis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:59

Miałem ten sam problem, więc stworzyłem Mixin, który wydaje się działać dla moich przypadków użycia.

class ReadOnlyFieldsMixin(object):
    readonly_fields =()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        for field in (field for name, field in self.fields.iteritems() if name in self.readonly_fields):
            field.widget.attrs['disabled'] = 'true'
            field.required = False

    def clean(self):
        cleaned_data = super(ReadOnlyFieldsMixin,self).clean()
        for field in self.readonly_fields:
           cleaned_data[field] = getattr(self.instance, field)

        return cleaned_data

Użycie, Po prostu określ, które z nich muszą być tylko do odczytu:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')
 4
Author: Michael,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-09 03:02:45

Po raz kolejny mam zamiar zaproponować jeszcze jedno rozwiązanie :) używałem kodu Humphreya, więc to jest oparte na tym.

Jednak napotkałem problemy z polem jako ModelChoiceField. Wszystko będzie działać na pierwsze życzenie. Jeśli jednak zestaw formularzy próbował dodać nowy element i nie udało się go zatwierdzić, coś poszło nie tak z" istniejącymi " formularzami, w których wybrana opcja była resetowana do wartości domyślnej "---------".

W każdym razie, nie mogłem wymyślić, jak naprawić to. Więc zamiast tego (i myślę, że jest to w rzeczywistości czystsze w formie), zrobiłem pola HiddenInputField (). Oznacza to po prostu, że musisz wykonać trochę więcej pracy w szablonie.

Więc poprawką dla mnie było uproszczenie formularza:

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()

A następnie w szablonie musisz wykonać ręczne zapętlenie zestawu formularzy .

Więc w tym przypadku zrobiłbyś coś takiego w szablonie:

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

To działało trochę lepiej dla mnie i z mniejszą formą manipulacja.

 4
Author: JamesD,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:54

Jeszcze dwa (podobne) podejścia z jednym uogólnionym przykładem:

1) pierwsze podejście-usunięcie pola w metodzie save (), np. (nie testowane ;)):

def save(self, *args, **kwargs):
    for fname in self.readonly_fields:
        if fname in self.cleaned_data:
            del self.cleaned_data[fname]
    return super(<form-name>, self).save(*args,**kwargs)

2) drugie podejście - Resetowanie pola do wartości początkowej w metodzie clean:

def clean_<fieldname>(self):
    return self.initial[<fieldname>] # or getattr(self.instance, fieldname)

Bazując na drugim podejściu uogólniłem to tak:

from functools                 import partial

class <Form-name>(...):

    def __init__(self, ...):
        ...
        super(<Form-name>, self).__init__(*args, **kwargs)
        ...
        for i, (fname, field) in enumerate(self.fields.iteritems()):
            if fname in self.readonly_fields:
                field.widget.attrs['readonly'] = "readonly"
                field.required = False
                # set clean method to reset value back
                clean_method_name = "clean_%s" % fname
                assert clean_method_name not in dir(self)
                setattr(self, clean_method_name, partial(self._clean_for_readonly_field, fname=fname))

    def _clean_for_readonly_field(self, fname):
        """ will reset value to initial - nothing will be changed 
            needs to be added dynamically - partial, see init_fields
        """
        return self.initial[fname] # or getattr(self.instance, fieldname)
 3
Author: Robert Lujo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-27 21:38:51

Jedną z prostych opcji jest wpisanie form.instance.fieldName w szablonie zamiast form.fieldName.

 3
Author: alzclarke,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:28:11

Jeśli potrzebujesz wielu pól tylko do odczytu.możesz użyć dowolnej z metod podanych poniżej

Metoda 1

class ItemForm(ModelForm):
    readonly = ('sku',)

    def __init__(self, *arg, **kwrg):
        super(ItemForm, self).__init__(*arg, **kwrg)
        for x in self.readonly:
            self.fields[x].widget.attrs['disabled'] = 'disabled'

    def clean(self):
        data = super(ItemForm, self).clean()
        for x in self.readonly:
            data[x] = getattr(self.instance, x)
        return data

Metoda 2

Metoda dziedziczenia

class AdvancedModelForm(ModelForm):


    def __init__(self, *arg, **kwrg):
        super(AdvancedModelForm, self).__init__(*arg, **kwrg)
        if hasattr(self, 'readonly'):
            for x in self.readonly:
                self.fields[x].widget.attrs['disabled'] = 'disabled'

    def clean(self):
        data = super(AdvancedModelForm, self).clean()
        if hasattr(self, 'readonly'):
            for x in self.readonly:
                data[x] = getattr(self.instance, x)
        return data


class ItemForm(AdvancedModelForm):
    readonly = ('sku',)
 3
Author: Sarath Ak,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-19 10:13:11

Jak to robię z Django 1.11:

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
 3
Author: Lucas B,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-24 15:34:58

Dla wersji Admin, myślę, że jest to bardziej zwarty sposób, jeśli masz więcej niż jedno pole:

def get_readonly_fields(self, request, obj=None):
    skips = ('sku', 'other_field')
    fields = super(ItemAdmin, self).get_readonly_fields(request, obj)

    if not obj:
        return [field for field in fields if not field in skips]
    return fields
 2
Author: Hassek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:36:25

Na podstawie odpowiedzi yamikepa znalazłem lepsze i bardzo proste rozwiązanie, które obsługuje również pola ModelMultipleChoiceField.

Usunięcie pola z form.cleaned_data zapobiega zapisywaniu pól:

class ReadOnlyFieldsMixin(object):
    readonly_fields = ()

    def __init__(self, *args, **kwargs):
        super(ReadOnlyFieldsMixin, self).__init__(*args, **kwargs)
        for field in (field for name, field in self.fields.iteritems() if
                      name in self.readonly_fields):
            field.widget.attrs['disabled'] = 'true'
            field.required = False

    def clean(self):
        for f in self.readonly_fields:
            self.cleaned_data.pop(f, None)
        return super(ReadOnlyFieldsMixin, self).clean()

Użycie:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')
 2
Author: darklow,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:33

Oto nieco bardziej zaangażowana wersja, oparta na odpowiedzi christophe31 . Nie opiera się na atrybucie "readonly". To sprawia, że jego problemy, takie jak select boxes wciąż jest zmienny i datapickers wciąż pojawiają się, znikają.

Zamiast tego zawija widżet pól formularza w widżet readonly, co sprawia, że formularz nadal się sprawdza. Zawartość oryginalnego widżetu jest wyświetlana wewnątrz znaczników <span class="hidden"></span>. Jeśli widżet ma metodę render_readonly(), używa jej jako widocznego tekstu, w przeciwnym razie analizuje HTML oryginalnego widżetu i próbuje odgadnąć najlepszą reprezentację.

import django.forms.widgets as f
import xml.etree.ElementTree as etree
from django.utils.safestring import mark_safe

def make_readonly(form):
    """
    Makes all fields on the form readonly and prevents it from POST hacks.
    """

    def _get_cleaner(_form, field):
        def clean_field():
            return getattr(_form.instance, field, None)
        return clean_field

    for field_name in form.fields.keys():
        form.fields[field_name].widget = ReadOnlyWidget(
            initial_widget=form.fields[field_name].widget)
        setattr(form, "clean_" + field_name, 
                _get_cleaner(form, field_name))

    form.is_readonly = True

class ReadOnlyWidget(f.Select):
    """
    Renders the content of the initial widget in a hidden <span>. If the
    initial widget has a ``render_readonly()`` method it uses that as display
    text, otherwise it tries to guess by parsing the html of the initial widget.
    """

    def __init__(self, initial_widget, *args, **kwargs):
        self.initial_widget = initial_widget
        super(ReadOnlyWidget, self).__init__(*args, **kwargs)

    def render(self, *args, **kwargs):
        def guess_readonly_text(original_content):
            root = etree.fromstring("<span>%s</span>" % original_content)

            for element in root:
                if element.tag == 'input':
                    return element.get('value')

                if element.tag == 'select':
                    for option in element:
                        if option.get('selected'):
                            return option.text

                if element.tag == 'textarea':
                    return element.text

            return "N/A"

        original_content = self.initial_widget.render(*args, **kwargs)
        try:
            readonly_text = self.initial_widget.render_readonly(*args, **kwargs)
        except AttributeError:
            readonly_text = guess_readonly_text(original_content)

        return mark_safe("""<span class="hidden">%s</span>%s""" % (
            original_content, readonly_text))

# Usage example 1.
self.fields['my_field'].widget = ReadOnlyWidget(self.fields['my_field'].widget)

# Usage example 2.
form = MyForm()
make_readonly(form)
 2
Author: Rune Kaagaard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 23:28:48

Czy to najprostszy sposób?

Prawo w kodzie widoku coś takiego:

def resume_edit(request, r_id):
    .....    
    r = Resume.get.object(pk=r_id)
    resume = ResumeModelForm(instance=r)
    .....
    resume.fields['email'].widget.attrs['readonly'] = True 
    .....
    return render(request, 'resumes/resume.html', context)
To działa dobrze!
 1
Author: fly_frog,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-11 21:17:06

Rozwiązałem ten problem tak:

    class UploadFileForm(forms.ModelForm):
     class Meta:
      model = FileStorage
      fields = '__all__'
      widgets = {'patient': forms.HiddenInput()}

W odsłonach:

form = UploadFileForm(request.POST, request.FILES, instance=patient, initial={'patient': patient})
To wszystko.
 1
Author: Pavel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-08 10:52:57

Dla django 1.9 +
Możesz użyć argumentu Fields disabled, aby wyłączyć pole. np. w poniższym fragmencie kodu z forms.py file, I have made employee_code field disabled

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

Odniesienie https://docs.djangoproject.com/en/2.0/ref/forms/fields/#disabled

 1
Author: Ajinkya Bhosale,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-26 08:15:13

Jeśli używasz Django admin, oto najprostsze rozwiązanie.

class ReadonlyFieldsMixin(object):
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return super(ReadonlyFieldsMixin, self).get_readonly_fields(request, obj)
        else:
            return tuple()

class MyAdmin(ReadonlyFieldsMixin, ModelAdmin):
    readonly_fields = ('sku',)
 0
Author: utapyngo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-24 06:37:40

Myślę, że najlepszym rozwiązaniem byłoby umieszczenie atrybutu readonly w szablonie renderowanym w <span> lub <p> zamiast umieszczać go w formularzu, jeśli jest to readonly.

Formularze służą do zbierania danych, a nie ich wyświetlania. Mając to na uwadze, opcje wyświetlania w widżecie readonly i szorowania danych postów są dobrymi rozwiązaniami.

 0
Author: austinheiman,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-15 18:40:27

Jeśli pracujesz z Django ver < 1.9 ({[2] } dodano atrybut Field.disabled) Możesz spróbować dodać następujący dekorator do formularza __init__ metoda:

def bound_data_readonly(_, initial):
    return initial


def to_python_readonly(field):
    native_to_python = field.to_python

    def to_python_filed(_):
        return native_to_python(field.initial)

    return to_python_filed


def disable_read_only_fields(init_method):

    def init_wrapper(*args, **kwargs):
        self = args[0]
        init_method(*args, **kwargs)
        for field in self.fields.values():
            if field.widget.attrs.get('readonly', None):
                field.widget.attrs['disabled'] = True
                setattr(field, 'bound_data', bound_data_readonly)
                setattr(field, 'to_python', to_python_readonly(field))

    return init_wrapper


class YourForm(forms.ModelForm):

    @disable_read_only_fields
    def __init__(self, *args, **kwargs):
        ...

Główną ideą jest to, że jeśli pole jest readonly, nie potrzebujesz żadnej innej wartości poza initial.

P. S: nie zapomnij ustawić yuor_form_field.widget.attrs['readonly'] = True

 0
Author: Yaroslav Varkhol,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 05:45:50