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()
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.
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.
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.
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.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.
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'}))
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')
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.
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
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)
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']
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')
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.
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)
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
.
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',)
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
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
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')
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)
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!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.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
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',)
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.
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
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