Django Admin'de alanları yeniden boyutlandırma


109

Django, yönetici üzerinde girişler eklerken veya düzenlerken yatay alanı doldurma eğilimindedir, ancak bazı durumlarda, örneğin bir tarih alanını, 8 karakter genişliğini veya bir CharField'ı 6 veya 8 düzenlerken gerçek bir alan israfıdır. karakter genişliğinde ve ardından düzenleme kutusu 15 veya 20 karaktere kadar çıkar.

Yöneticiye bir metin kutusunun ne kadar geniş olması gerektiğini veya bir TextField düzenleme kutusunun yüksekliğini nasıl söyleyebilirim?


9
Açıkçası, bu durumda bunu yapmayı unutmuşsunuz. İki yıldan fazla bir süre sonra. =)
casperOne

Proje terk edildi ve bir süre kodu görmedim. Önümüzdeki ay yeni bir projeye başlayabilirim, bu yüzden belki bunu tekrar görebilirim: D
Andor

Yanıtlar:


211

ModelAdmin.formfield_overrides kullanmalısınız .

Oldukça kolaydır - admin.pyiçeride, tanımlayın:

from django.forms import TextInput, Textarea
from django.db import models

class YourModelAdmin(admin.ModelAdmin):
    formfield_overrides = {
        models.CharField: {'widget': TextInput(attrs={'size':'20'})},
        models.TextField: {'widget': Textarea(attrs={'rows':4, 'cols':40})},
    }

admin.site.register(YourModel, YourModelAdmin)

1
Bazı saçma şablon özelleştirmeleri yapmak zorunda kalmadan tam olarak aradığım şey buydu. Teşekkürler!
Chris

2
YourModelAdmin'deki ilgili alanlar için ayarlanmışsa filter_horizontalveya filter_verticalayarlanmışsa bunun çalışmayacağını unutmayın. Bunu çözmek için biraz zaman harcadım.
Dennis Golomazov

Buna bir biçimde herhangi bir gariplik var mı? Tüm Textareas için attrs özniteliğini ayarlamanın bir yolunu bulamadım.
Julian

1
Sadece kullandım models.TextField: {'widget': Textarea(attrs={'rows':4})}ama genişlik de küçüldü.
Smit Johnth

Görünüşe göre aynı boyutta olmaları zor.
Sören

45

Bir widget'ın "attrs" özelliğini kullanarak rastgele HTML nitelikleri ayarlayabilirsiniz .

Bunu Django yöneticisinde formfield_for_dbfield kullanarak yapabilirsiniz:

class MyModelAdmin(admin.ModelAdmin):
  def formfield_for_dbfield(self, db_field, **kwargs):
    field = super(ContentAdmin, self).formfield_for_dbfield(db_field, **kwargs)
    if db_field.name == 'somefield':
      field.widget.attrs['class'] = 'someclass ' + field.widget.attrs.get('class', '')
    return field

veya özel bir Widget alt sınıfı ve formfield_overrides sözlüğü ile :

class DifferentlySizedTextarea(forms.Textarea):
  def __init__(self, *args, **kwargs):
    attrs = kwargs.setdefault('attrs', {})
    attrs.setdefault('cols', 80)
    attrs.setdefault('rows', 5)
    super(DifferentlySizedTextarea, self).__init__(*args, **kwargs)

class MyModelAdmin(admin.ModelAdmin):
  formfield_overrides = { models.TextField: {'widget': DifferentlySizedTextarea}}

30

Belirli bir alanın genişliğini değiştirmek için.

ModelAdmin.get_form ile yapılmıştır :

class YourModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['myfield'].widget.attrs['style'] = 'width: 45em;'
        return form

Kanımca bu en iyi cevap, çünkü yeni bir form oluşturmak zorunda kalmadan bireysel alanları değiştirmeye izin veriyor.
rbennell

21

Hızlı ve kirli bir seçenek, söz konusu model için basitçe özel bir şablon sağlamaktır.

Adlandırılmış bir şablon oluşturursanız admin/<app label>/<class name>/change_form.html, yönetici varsayılan yerine bu şablonu kullanacaktır. Yani, adlı Personbir uygulamada adlandırılmış bir modeliniz varsa, adlı peoplebir şablon oluşturursunuz admin/people/person/change_form.html.

Tüm yönetici şablonlarında, bir extraheadşeyler yerleştirmek için geçersiz kılabileceğiniz bir blok vardır <head>ve bulmacanın son parçası, her alanın bir HTML kimliğine sahip olmasıdır id_<field-name>.

Böylece, şablonunuza aşağıdakine benzer bir şey koyabilirsiniz:

{% extends "admin/change_form.html" %}

{% block extrahead %}
  {{ block.super }}
  <style type="text/css">
    #id_my_field { width: 100px; }
  </style>
{% endblock %}

Teşekkürler! Bu ve alanjds tarafından verilen yanıt, yönetici arayüzündeki düzeni alan başına türden ziyade alan bazında değiştirmek için çok yararlıdır.
nealmcb

10

Alan başına örnekteki öznitelikleri değiştirmek istiyorsanız, "attrs" özelliğini doğrudan form girişlerinize ekleyebilirsiniz.

Örneğin:

class BlogPostForm(forms.ModelForm):
    title = forms.CharField(label='Title:', max_length=128)
    body = forms.CharField(label='Post:', max_length=2000, 
        widget=forms.Textarea(attrs={'rows':'5', 'cols': '5'}))

    class Meta:
        model = BlogPost
        fields = ('title', 'body')

"Attrs" özelliği, temel olarak form alanını ayarlayacak olan HTML biçimlendirmesinden geçer. Her giriş, geçersiz kılmak istediğiniz özniteliğin ve onu geçersiz kılmak istediğiniz değerin bir demetidir. Her bir grubu virgülle ayırdığınız sürece istediğiniz kadar özellik girebilirsiniz.


IMO, tüm TextInput widget'larını aynı anda değil, yalnızca tek bir alanı değiştirmenin en iyi yolu (kabul edilen yanıtın yaptığı gibi)
ascripter

7

Bulduğum en iyi yol şuna benzer:

class NotificationForm(forms.ModelForm):
    def __init__(self, *args, **kwargs): 
        super(NotificationForm, self).__init__(*args, **kwargs)
        self.fields['content'].widget.attrs['cols'] = 80
        self.fields['content'].widget.attrs['rows'] = 15
        self.fields['title'].widget.attrs['size'] = 50
    class Meta:
        model = Notification

Onun çok daha iyi ModelForm için korur gibi farklı aletler ile alanlarını ağır basan daha nameve help_textnitelikleri ve model alanların da ön değerler forma kopyalamak zorunda kalmamak.


7

TextField ile benzer bir sorun yaşadım. Django 1.0.2 kullanıyorum ve ilişkili metin alanında 'satırlar' için varsayılan değeri değiştirmek istedim. formfield_overrides bu sürümde mevcut değil. Formfield_for_dbfield'ı geçersiz kılmak işe yaradı, ancak bunu ModelAdmin alt sınıflarımın her biri için yapmak zorunda kaldım, yoksa bir özyineleme hatasıyla sonuçlanırdı. Sonunda, aşağıdaki kodu models.py'ye eklemenin işe yaradığını buldum:

from django.forms import Textarea

class MyTextField(models.TextField):
#A more reasonably sized textarea                                                                                                            
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": Textarea(attrs={'rows':2, 'cols':80})}
         )
         return super(MyTextField, self).formfield(**kwargs)

Ardından, modellerinizi tanımlarken TextField yerine MyTextField kullanın. Bu yanıttan benzer bir soruya uyarladım .


5

Django SSS'de iyi tanımlanmıştır :

S: Modelimdeki bir alandaki bir parçacığın özniteliklerini nasıl değiştirebilirim?

A: ModelAdmin / StackedInline / TabularInline sınıfındaki formfield_for_dbfield öğesini geçersiz kılın

class MyOtherModelInline(admin.StackedInline):
    model = MyOtherModel
    extra = 1

    def formfield_for_dbfield(self, db_field, **kwargs):
        # This method will turn all TextFields into giant TextFields
        if isinstance(db_field, models.TextField):
            return forms.CharField(widget=forms.Textarea(attrs={'cols': 130, 'rows':30, 'class': 'docx'}))
        return super(MyOtherModelInline, self).formfield_for_dbfield(db_field, **kwargs)

Bu tekniği kullandığımda yardım metni görünmeyecek ve TabularInline ise sütun başlığı 'Yok' oluyor.
Steven T. Snyder

1
CharField'deki diğer tüm ayarları sildiğiniz için bu iyi bir yaklaşım değil. Örneğin, varsayılan olarak, form alanının gerekli olup olmayacağını akıllıca algılar, ancak bu kod bunu yok eder. Bunun yerine, parçacığı super () çağrınızın döndürdüğü değere ayarlamalısınız.
Cerin

5

Alan boyutlarınızı her zaman özel bir stil sayfasında ayarlayabilir ve Django'ya bunu ModelAdmin sınıfınız için kullanmasını söyleyebilirsiniz:

class MyModelAdmin(ModelAdmin):
    class Media:
        css = {"all": ("my_stylesheet.css",)}

en iyi cevap! form alanları ve niteliklerle (ve olası yan etkilerle) uğraşmak yok, sadece django yönetici formlarındaki mevcut kimlikler / sınıflarla - yalnızca bazı alanları veya hatta tüm alanları kolayca hedefleyebilen bir css dosyası. büyük!
benzkji

2

1.6 için, formları kullanarak charfield içindeki metin alanının özelliklerini belirtmem gerekiyordu:

test1 = forms.CharField(max_length=400, widget=forms.Textarea( attrs={'rows':'2', 'cols': '10'}),  initial='', help_text=helptexts.helptxt['test'])

1

Msdin ile aynı yanıt, ancak TextArea yerine TextInput ile:

from django.forms import TextInput

class ShortTextField(models.TextField):
    def formfield(self, **kwargs):
         kwargs.update(
            {"widget": TextInput(attrs={'size': 10})}
         )
         return super(ShortTextField, self).formfield(**kwargs)

1

İşte basit ama esnek bir çözüm. Bazı widget'ları geçersiz kılmak için özel bir form kullanın.

# models.py
class Elephant(models.Model):
    name = models.CharField(max_length=25)
    age = models.IntegerField()

# forms.py
class ElephantForm(forms.ModelForm):

    class Meta:
        widgets = {
            'age': forms.TextInput(attrs={'size': 3}),
        }

# admin.py
@admin.register(Elephant)
class ElephantAdmin(admin.ModelAdmin):
    form = ElephantForm

Verilen widget'lar ElephantFormvarsayılan olanların yerini alacaktır. Anahtar, alanın dize gösterimidir. Formda belirtilmeyen alanlar varsayılan widget'ı kullanacaktır.

Her ne kadar bu Not ageolan bir IntegerFieldkullanabileceğimiz TextInputfarklı olarak, çünkü widget'ı NumberInput, TextInputkabul sizeniteliğini.

Bu çözüm bu makalede anlatılmaktadır .


0

Seçenekler / seçenekler / bir açılır menü içeren bir ForeignKey alanıyla çalışıyorsanız formfield_for_foreignkey, Yönetici örneğinde geçersiz kılabilirsiniz :

class YourNewAdmin(admin.ModelAdmin):
    ...

    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == 'your_fk_field':
            """ For your FK field of choice, override the dropdown style """
            kwargs["widget"] = django.forms.widgets.Select(attrs={
                'style': 'width: 250px;'
            })

        return super().formfield_for_foreignkey(db_field, request, **kwargs)

Bu model hakkında daha fazla bilgi burada ve burada .


-1

Ve bir örnek daha:

class SecenekInline(admin.TabularInline):
   model = Secenek
   # classes = ['collapse']
   def formfield_for_dbfield(self, db_field, **kwargs):
       field = super(SecenekInline, self).formfield_for_dbfield(db_field, **kwargs)
       if db_field.name == 'harf':
           field.widget = TextInput(attrs={'size':2})
       return field
   formfield_overrides = {
       models.TextField: {'widget': Textarea(attrs={'rows':2})},
   }
   extra = 2

Yalnızca belirli bir alan boyutunu düzenlemek istiyorsanız, bunu kullanabilirsiniz.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.