Django- व्यवस्थापक: TextArea के रूप में CharField


87

मेरे पास है

class Cab(models.Model):
    name  = models.CharField( max_length=20 )
    descr = models.CharField( max_length=2000 )

class Cab_Admin(admin.ModelAdmin):
    ordering     = ('name',)
    list_display = ('name','descr', )
    # what to write here to make descr using TextArea?

admin.site.register( Cab, Cab_Admin )

कैसे व्यवस्थापक इंटरफ़ेस में 'उतर' क्षेत्र के लिए TextArea विजेट असाइन करने के लिए?

upd:
में व्यवस्थापक इंटरफ़ेस केवल!

ModelForm का उपयोग करने के लिए अच्छा विचार है।


3
स्वीकृत उत्तर केवल एक क्षेत्र में परिवर्तन के उद्देश्य के लिए भारी ओवरकिल है! लोगों की
क्षमता के

जवाबों:


99

आपको एक forms.ModelFormऐसा बनाना होगा जो यह वर्णन करेगा कि आप कैसे descrफ़ील्ड प्रदर्शित करना चाहते हैं , और फिर admin.ModelAdminउस फ़ॉर्म का उपयोग करने के लिए कहें । उदाहरण के लिए:

from django import forms
class CabModelForm( forms.ModelForm ):
    descr = forms.CharField( widget=forms.Textarea )
    class Meta:
        model = Cab

class Cab_Admin( admin.ModelAdmin ):
    form = CabModelForm

की formविशेषता admin.ModelAdminआधिकारिक Django प्रलेखन में प्रलेखित है। यहाँ एक जगह देखने लायक है


6
केवल एक फ़ॉर्म विजेट को बदलने के लिए, आपको अपना संपूर्ण फ़ॉर्म नहीं बनाना होगा। आप बस formfield_for_dbfieldअपने पर ओवरराइड कर सकते हैं ModelAdmin, नीचे मेरा जवाब देखें।
कार्ल मेयर

1
यह देता हैdjango.core.exceptions.ImproperlyConfigured: Creating a ModelForm without either the 'fields' attribute or the 'exclude' attribute is prohibited
जॉन वू

4
Django 1.7 से शुरू करके आपको इसके fields = '__all__'तहत भी जोड़ना होगा class Meta:
स्कोल

2
आपको स्वयं फॉर्म बनाने की आवश्यकता नहीं है, आप get_formविधि को ओवरराइड कर सकते हैं । मेरा जवाब देखिए ।
x- यूरी

बेटर एप्रोच का उपयोग मेटा क्लास मेटा: मॉडल = मैसेज विजेट्स = {'टेक्स्ट': फॉर्म्स.टेक्तेरिया (अटार्स = {'कॉल्स': 80, 'रॉल्स': 20}),}
अमूल्य आचार्य

58

इस मामले के लिए, सबसे अच्छा विकल्प शायद आपके मॉडल में चारफिल्ड के बजाय एक टेक्स्टफिल्ड का उपयोग करना है। आप formfield_for_dbfieldअपनी ModelAdminकक्षा की विधि को भी ओवरराइड कर सकते हैं :

class CabAdmin(admin.ModelAdmin):
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(CabAdmin, self).formfield_for_dbfield(db_field, **kwargs)
        if db_field.name == 'descr':
            formfield.widget = forms.Textarea(attrs=formfield.widget.attrs)
        return formfield

क्या चयनित उत्तर की तुलना में इसमें कोई गिरावट है? इसे लागू करने के लिए क्लीनर दिखता है क्योंकि हमें एक नया ModelForm बनाने की आवश्यकता नहीं है ...
पिना

3
TextField के लिए स्वचालित रूप से उत्पन्न सभी विशेषताओं को रखने के लिए प्रतिस्थापित formfield.widget = forms.Textarea()किया formfield.widget = forms.Textarea(attrs=formfield.widget.attrs)गया, धन्यवाद!
फिल्पा पिना

2
मुझे नहीं पता कि इस पर दूसरा जवाब क्यों स्वीकार किया जाता है; मुझे लगता है कि अगर आप सब कर रहे हैं एक विजेट की जगह यह आसान है। लेकिन या तो ठीक काम करेगा।
कार्ल मेयर

यह पूरी तरह से काम किया, धन्यवाद। सुपर () आह्वान थोड़ा सा क्रियात्मक लगता है, हालांकि, क्या यह करने का एक सरल तरीका है?
rjh

2
@rjh py3 में आप पार्न्स के अंदर सब कुछ खत्म कर सकते हैं और बस उपयोग कर सकते हैं super()। नहीं तो नहीं।
कार्ल मेयर

32

थोड़े से बदलाव (!) को छोड़कर अयाज़ के पास बहुत ज्यादा जगह है।

class MessageAdminForm(forms.ModelForm):
    class Meta:
        model = Message
        widgets = {
            'text': forms.Textarea(attrs={'cols': 80, 'rows': 20}),
        }

class MessageAdmin(admin.ModelAdmin):
    form = MessageAdminForm
admin.site.register(Message, MessageAdmin)

इसलिए, आपको विजेट को बदलने के लिए मॉडलफ़ॉर्म में एक फ़ील्ड को फिर से परिभाषित करने की आवश्यकता नहीं है, बस मेटा में विगेट्स को निर्धारित करें।


1
यह अयाज़ के उत्तर की तुलना में अधिक "स्वचालित" गुणों को बनाए रखता है, लेकिन साथ ही साथ क्षेत्र की लंबाई सत्यापन को कैसे रखा जाए इस पर कोई टिप?
फ़िलिप पिना

14

आप आवश्यक formfieldविधि के साथ अपने स्वयं के क्षेत्र को उपवर्ग कर सकते हैं :

class CharFieldWithTextarea(models.CharField):

    def formfield(self, **kwargs):
        kwargs.update({"widget": forms.Textarea})
        return super(CharFieldWithTextarea, self).formfield(**kwargs)

यह सभी उत्पन्न रूपों पर प्रभाव डालेगा।


9

आपको स्वयं फॉर्म क्लास बनाने की आवश्यकता नहीं है:

from django.contrib import admin
from django import forms

class MyModelAdmin(admin.ModelAdmin):
    def get_form(self, request, obj=None, **kwargs):
        kwargs['widgets'] = {'descr': forms.Textarea}
        return super().get_form(request, obj, **kwargs)

admin.site.register(MyModel, MyModelAdmin)

ModelAdmin.get_form देखें ।


7

यदि आप Textrea को admin.py पर बदलने की कोशिश कर रहे हैं, तो यह मेरे लिए काम करने वाला समाधान है:

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

from books.models import Book

class BookForm(forms.ModelForm):
    description = forms.CharField( widget=forms.Textarea(attrs={'rows': 5, 'cols': 100}))
    class Meta:
        model = Book

class BookAdmin(admin.ModelAdmin):
    form = BookForm

admin.site.register(Book, BookAdmin)

यदि आप एक MySQL DB का उपयोग कर रहे हैं, तो आमतौर पर आपकी कॉलम लंबाई 250 वर्णों की हो जाएगी, इसलिए आप MySQL DB में लंबाई बदलने के लिए ALTER TABLE चलाना चाहेंगे, ताकि आप नए बड़े Textarea का लाभ उठा सकें। आप में व्यवस्थापक Django साइट है।


6

एक के बजाय models.CharField, एक का उपयोग models.TextFieldकरने के लिए descr


4
दुर्भाग्य से, max_length = एक टेक्स्टफिल्ड पर Django द्वारा पूरी तरह से नजरअंदाज कर दिया गया है, इसलिए जब आपको फ़ील्ड लंबाई सत्यापन की आवश्यकता होती है (जैसे कि सचिवों को घटना के सारांश में प्रवेश करने की आवश्यकता होती है) तो इसे प्राप्त करने का एकमात्र तरीका एक CharField का उपयोग करना है। लेकिन एक CharField 300 चार्ट में टाइप करने के लिए कम करने के लिए रास्ता है। इसलिए ayaz समाधान।
शाकर

3
यह एक अच्छा जवाब नहीं है क्योंकि यह डेटाबेस को बदलता है। विजेट बदलने की बात यह है कि फ़ील्ड को कैसे प्रदर्शित किया जाए, डेटाबेस स्कीमा को बदलने के लिए नहीं

1
यह किसी के लिए एक महान जवाब है (मेरे जैसे) जो सीख रहा है कि कैसे Django का उपयोग करना है और अगर मैं बेहतर जानता हूं, तो पहली जगह में डेटाबेस को अलग तरीके से सेट किया जाएगा।
एंड्रयू स्विफ्ट

5

आप models.TextFieldइस उद्देश्य के लिए उपयोग कर सकते हैं :

class Sample(models.Model):
    field1 = models.CharField(max_length=128)
    field2 = models.TextField(max_length=1024*2)   # Will be rendered as textarea

3
यह DB संरचना को बदल देगा इसलिए
लापरवाह

3

कार्ल मेयर के जवाब पर विस्तार करना चाहता था, जो इस तिथि तक पूरी तरह से काम करता है।

मैं हमेशा (विकल्पों के साथ या बिना) TextFieldका उपयोग करता हूं CharFieldऔर DB स्तर पर यूआई / एपीआई की ओर से चरित्र सीमाएं लागू करता हूं । इस काम को गतिशील बनाने के लिए:

from django import forms
from django.contrib import admin


class BaseAdmin(admin.ModelAdmin):
    """
    Base admin capable of forcing widget conversion
    """
    def formfield_for_dbfield(self, db_field, **kwargs):
        formfield = super(BaseAdmin, self).formfield_for_dbfield(
            db_field, **kwargs)

        display_as_charfield = getattr(self, 'display_as_charfield', [])
        display_as_choicefield = getattr(self, 'display_as_choicefield', [])

        if db_field.name in display_as_charfield:
            formfield.widget = forms.TextInput(attrs=formfield.widget.attrs)
        elif db_field.name in display_as_choicefield:
            formfield.widget = forms.Select(choices=formfield.choices,
                                            attrs=formfield.widget.attrs)

        return formfield

मैं एक मॉडल का नाम है Postजहां title, slugऔर stateकर रहे हैं TextFieldऔर stateविकल्प नहीं है। व्यवस्थापक की परिभाषा इस प्रकार है:

@admin.register(Post)
class PostAdmin(BaseAdmin):
    list_display = ('pk', 'title', 'author', 'org', 'state', 'created',)
    search_fields = [
        'title',
        'author__username',
    ]
    display_as_charfield = ['title', 'slug']
    display_as_choicefield = ['state']

सोचा दूसरों को जवाब के लिए देख यह उपयोगी हो सकता है।


क्या यह formfield_for_dbfieldप्रलेखित है?
x- यूरी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.