"Spass mit Newforms-Admin - Read-Only Felder"超絶意訳

続きが出たので今回も超絶意訳をやって行きたいと思います。
前提として、
models.pyは前回使っていたものを使います。
新しく作る場合は、Metaクラス部分はなくても大丈夫です。

from django.db import models
from django.contrib.auth.models import User

# Create your models here.

class Entry(models.Model):
    title = models.CharField(max_length=255)
    content = models.TextField()
    author = models.ForeignKey(User)
    
    class Meta:
        permissions = (
            ('can_view_all', 'Can view all Entries'),
        )
        
    def __unicode__(self):
        return self.title

では、Spass mit Newforms-Admin - Read-Only Felder超絶意訳スタートです。


Admin Interfaceを使っていて不満なところってありませんか?
モデルフィールドのオプション"editable"を"False"にするとAdmin Interfaceに表示されなくなります。
これをどうにかしたいと思いませんか?
admin.pyをカスタマイズすることで可能になります。


admin.pyを以下のように作成してください。

from django.contrib import admin
from myproject.weblog.models import Entry

class EntryAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(EntryAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        
        if db_field.name == "title":
            field.widget.attrs = {'disabled': 'disabled'}
        return field

admin.site.register(Entry, EntryAdmin)

次にAdmin Interfaceにアクセスし、entryの追加もしくは変更をしてみて下さい。
以下のように"Title"の部分が入力・変更が出来なくなっていると思います。
read-only1
read-only posted by (C)常山


これでもいいのですが、融通が利いてませんよね。
もう少し変更してみましょう。

from django.contrib import admin
from myproject.weblog.models import Entry

class EntryAdmin(admin.ModelAdmin):
    def add_view(self, request, *args, **kwargs):
        self._is_change_mode = False
        return super(EntryAdmin, self).add_view(request, *args, **kwargs)
    
    def change_view(self, request, object_id, *args, **kwargs):
        self._is_change_mode = True
        return super(EntryAdmin, self).change_view(request, object_id, *args, **kwargs)
    
    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(EntryAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        
        if db_field.name == "title" and self._is_change_mode:
            field.widget.attrs = {'disabled': 'disabled'}
        return field

admin.site.register(Entry, EntryAdmin)

どうでしょうか?
追加の場合、以下のように"Title"が入力できるようになり
read-only2
read-only2 posted by (C)常山

変更の場合は、"Title"が入力不可となっています。
read-only3
read-only3 posted by (C)常山


ここまでこだわってくるともう少し見栄えを良くしたいと思いませんか?
もう少し頑張ってコーディングしてみましょう。

from django.contrib import admin
from myproject.weblog.models import Entry
from django.utils.safestring import mark_safe
from django import forms

class ReadOnlyWidget(forms.HiddenInput):
    def __init__(self, append_text, *args, **kwargs):
        self.append_text = append_text
        super(ReadOnlyWidget, self).__init__()
    
    def render(self, *args, **kwargs):
        field_value = super(ReadOnlyWidget, self).render(*args, **kwargs)
        return mark_safe("%s <strong>%s</strong>" % (field_value, self.append_text))
        
class EntryAdmin(admin.ModelAdmin):
    def add_view(self, request, *args, **kwargs):
        self._is_change_mode = False
        return super(EntryAdmin, self).add_view(request, *args, **kwargs)
    
    def change_view(self, request, object_id, *args, **kwargs):
        self._is_change_mode = True
        self._obj = Entry.objects.get(pk = object_id)
        return super(EntryAdmin, self).change_view(request, object_id, *args, **kwargs)
    
    def formfield_for_dbfield(self, db_field, **kwargs):
        field = super(EntryAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        
        if db_field.name == "title" and self._is_change_mode:
            #field.widget.attrs = {'disabled': 'disabled'}
            field.widget = ReadOnlyWidget(append_text=self._obj.title)
        return field

admin.site.register(Entry, EntryAdmin)

read-only4
read-only4 posted by (C)常山
このようにすると、"Title"が違和感なく表示されます。


Spass mit Newforms-Admin - Rowlevel-Permissionsの内容と併せると面白い方法が出来るのではないでしょうか:-)