2011-07-17 13 views
10

Django bir TabularInline sınıfında get_readonly_fields kullanmaya çalışıyorum:Django'da bir TabularInline sınıfında get_readonly_fields?

Bu kod başka bir StackOverflow soru alınmış
class ItemInline(admin.TabularInline): 
    model = Item 
    extra = 5 

    def get_readonly_fields(self, request, obj=None): 
     if obj: 
      return ['name'] 

     return self.readonly_fields 

: Ancak Django admin site: prevent fields from being edited?

, bu yeni bir TabularInline sınıfında sokuyor nesne formları düzgün şekilde oluşturulmaz. Amaç, belirli alanların sadece yeni nesnelerde girilmesine izin verirken okunmasını sağlamaktır. Bir geçici çözüm veya farklı bir strateji için herhangi bir fikir?

+0

": Biz salt okunur bunu yapamaz beri

, burada bir formset ve temiz bir yöntem kullanılarak, bu form tarafından ayarlanamaz doğrulamak için benim çözüm Doğru şekilde oluşturma "? –

+0

Yeni nesne satırları için form alanları yok ve varolan nesneler için "name" sütunu tekrarlanıyor. – mpso

+0

aynı soruna sahip .. öyle görünüyor ki nesnenin ana nesnesi değil, satır içi nesne – Allanrbo

cevap

-2

Doğru yoldasınız. Self.readonly_fields öğelerini, salt okunur olarak ayarlamak istediğiniz alanların bir tuple'ı ile güncelleyin.

class ItemInline(admin.TabularInline): 
    model = Item 
    extra = 5 

    def get_readonly_fields(self, request, obj=None): 
     # add a tuple of readonly fields 
     self.readonly_fields += ('field_a', 'field_b') 
     return self.readonly_fields 
+0

değil Bu sorun değil. Onun sahip olduğu sorun, nesnenin satır içi nesnesini değil, üst nesneyi tutmasıdır.Sonunda, varolan bir satırda alanları salt okunur yapamaz, ancak alanın ekte düzenlenebilir olmasını sağlar. – kwakwa

14

Dikkatli - "obj" satır içi nesne değil, üst. Bu muhtemelen bir hata - bkz. Örneğin, this Django ticket

1

Bu durum, şu anda hala, nesne satır içi tarafından görüntülenen örnek olmayan ana model örneğidir.

Bunu çözmek için yaptığım şey, satır içi formdaki tüm alanları yalnızca okunması ve satır içi model için bir ChangeForm'a bir Add/Edit bağlantısı sağlamaktı. Bu

class ItemInline(ChangeFormLinkMixin, admin.StackedInline): 
    model = Item 
    extra = 5 
    readonly_fields = ['field1',...,'fieldN','change_form_link'] 

gibi

bu

class ChangeFormLinkMixin(object): 
    def change_form_link(self, instance): 
     url = reverse('admin:%s_%s_change' % (instance._meta.app_label, 
      instance._meta.module_name), args=(instance.id,)) 
     # Id == None implies and empty inline object 
     url = url.replace('None', 'add') 
     command = _('Add') if url.find('add') > -1 else _('Edit') 
     return format_html(u'<a href="{}">%s</a>' % command, url) 

gibi

Sonra satır içi I olacak bir şey Sonra ChangeForm I (ben istediğim gibi değişikliklerini denetlemek mümkün olacak Her biri bir dizi düzenlenebilir alanla ilişkili birkaç durumum var). Ben bir form ve benim Inline'a Widget ilişkilendirmiş bu konuya bir çözüm olarak

+0

Bunu bir çirkin bir hack olarak görüyorum, çünkü kullanıcı üst öğeyi alt öğede değiştirebilir, ancak daha sonra, yönetici sitesi "güvenilir" kullanıcılar tarafından kullanılıyormuş gibi davranıyor. – galileopy

1

:

admin.py: widget'larda

... 

class MasterCouponFileInline(admin.TabularInline): 
    model = MasterCouponFile 
    form = MasterCouponFileForm 
    extra = 0 

forms.py

.... 

class MasterCouponFileForm(forms.ModelForm): 
    class Meta: 
     model = MasterCouponFile  

    def __init__(self, *args, **kwargs): 
     super(MasterCouponFileForm, self).__init__(*args, **kwargs) 
     self.fields['range'].widget = DisablePopulatedText(self.instance) 
     self.fields['quantity'].widget = DisablePopulatedText(self.instance) 

. py

... 

from django import forms 
from django.forms.util import flatatt 
from django.utils.encoding import force_text 

class DisablePopulatedText(forms.TextInput): 
    def __init__(self, obj, attrs=None): 
     self.object = obj 
     super(DisablePopulatedText, self).__init__(attrs) 
    def render(self, name, value, attrs=None): 
     if value is None: 
      value = '' 
     final_attrs = self.build_attrs(attrs, type=self.input_type, name=name) 
     if value != '': 
      # Only add the 'value' attribute if a value is non-empty. 
      final_attrs['value'] = force_text(self._format_value(value)) 
     if "__prefix__" not in name and not value: 
      return format_html('<input{0} disabled />', flatatt(final_attrs)) 
     else: 
      return format_html('<input{0} />', flatatt(final_attrs)) 
+0

Bu cevap bana çok yardımcı oldu ve muhtemelen bunu yapmanın en iyi yolu. –

0

ers ekledik, bu django'da this Django ticket'da görüldüğü gibi bir tasarım hatası (teşekkürler Danny W). get_readonly_fields, üstteki nesneyi döndürür, burada istediğimiz şey bu değil. Eğer tam olarak ne demek istiyorsun

class ItemInline(admin.TabularInline): 
    model = Item 
    formset = ItemInlineFormset 

class ItemInlineFormset(forms.models.BaseInlineFormSet): 
    def clean(self): 
     super(ItemInlineFormset, self).clean() 
     for form in self.forms: 
      if form.instance.some_condition: 
       form.add_error('some_condition', 'Nope') 
İlgili konular