জ্যাঙ্গো ফর্মে, আমি কীভাবে কোনও ক্ষেত্রকে পঠনযোগ্য (বা অক্ষম) করব যাতে এটি সম্পাদনা করা যায় না?


430

জ্যাঙ্গো ফর্মে, আমি কীভাবে কেবল ক্ষেত্রকে পঠনযোগ্য (বা অক্ষম) করব?

ফর্মটি যখন নতুন এন্ট্রি তৈরি করতে ব্যবহৃত হচ্ছে তখন সমস্ত ক্ষেত্র সক্ষম করা উচিত - তবে যখন রেকর্ডটি আপডেট মোডে থাকে তখন কিছু ক্ষেত্র কেবল পঠনযোগ্য হওয়া দরকার।

উদাহরণস্বরূপ, একটি নতুন Itemমডেল তৈরি করার সময় , সমস্ত ক্ষেত্র অবশ্যই সম্পাদনযোগ্য হতে হবে, তবে রেকর্ডটি আপডেট করার সময়, skuক্ষেত্রটি অক্ষম করার কোনও উপায় আছে যাতে এটি দৃশ্যমান হয় তবে সম্পাদনা করা যায় না?

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

ক্লাস ItemFormআবার ব্যবহার করা যাবে? কী পরিবর্তন প্রয়োজন হবে ItemFormবা Itemমডেল বর্গ? ItemUpdateFormআইটেমটি আপডেট করার জন্য আমার কি অন্য ক্লাস, " " লেখার দরকার আছে ?

def update_item_view(request):
    if request.method == 'POST':
        form = ItemUpdateForm(request.POST)
        # Validate and save
    else:
        form = ItemUpdateForm()

এছাড়াও প্রশ্নটি দেখুন: জাজানোতে কেবল পঠনযোগ্য ক্ষেত্রগুলি কেন খারাপ ধারণা? @ স্ট্যাকওভারফ্লো.com / প্রশ্নগুলি / ২৯৯০২০২৪ , স্বীকৃত উত্তর (ড্যানিয়েল নবাব দ্বারা) দূষিত পোষ্ট হ্যাকদের যত্ন নিয়েছে।
এক্স 10

উত্তর:


421

এই উত্তরে নির্দেশিত হিসাবে , জ্যাঙ্গো ১.৯ ফিল্ড.ডিজিলযুক্ত বৈশিষ্ট্য যুক্ত করেছে :

অক্ষম বুলিয়ান আর্গুমেন্ট, সত্য হিসাবে সেট করা থাকলে, অক্ষম এইচটিএমএল বৈশিষ্ট্যটি ব্যবহার করে একটি ফর্ম ক্ষেত্র অক্ষম করে যাতে এটি ব্যবহারকারীদের দ্বারা সম্পাদনাযোগ্য হয় না। এমনকি যদি কোনও ব্যবহারকারী সার্ভারের কাছে জমা দেওয়া ক্ষেত্রের মানটি নিয়ে টেম্পার করে তবে তা ফর্মের প্রাথমিক তথ্য থেকে মানটির পক্ষে অগ্রাহ্য করা হবে।

জ্যাঙ্গো ১.৮ এবং তার আগে, উইজেটে প্রবেশ নিষ্ক্রিয় করতে এবং দূষিত পোষ্ট হ্যাকগুলি রোধ করতে আপনাকে readonlyফর্ম ক্ষেত্রে বৈশিষ্ট্য নির্ধারণের পাশাপাশি ইনপুটটি স্ক্রাব করতে হবে :

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']

বা, if instance and instance.pkআপনি সম্পাদনা করছেন তা নির্দেশ করে এমন একটি শর্তের সাথে প্রতিস্থাপন করুন । আপনি disabledপরিবর্তে ইনপুট ক্ষেত্রেও এট্রিবিউট সেট করতে পারেনreadonly

clean_skuফাংশন নিশ্চিত করবে যে readonlyমান একটি দ্বারা অধিলিখিত হবে নাPOST

অন্যথায়, অন্তর্নির্মিত জ্যাঙ্গো ফর্ম ক্ষেত্র নেই যা সীমাবদ্ধ ইনপুট ডেটা প্রত্যাখ্যান করার সময় একটি মান প্রদান করবে। যদি আপনি যা চান এটি যদি হয় তবে আপনার পরিবর্তে একটি পৃথক তৈরি করা উচিত ModelFormযা অখাদ্য ক্ষেত্র (গুলি) বাদ দেয় এবং কেবলমাত্র সেগুলি আপনার টেমপ্লেটের ভিতরে মুদ্রণ করবে।


3
ড্যানিয়েল, একটি উত্তর পোস্ট করার জন্য ধন্যবাদ। এই কোডটি কীভাবে ব্যবহার করবেন তা আমার কাছে পরিষ্কার নয়? এই কোডটি নতুন হিসাবে পাশাপাশি আপডেট মোডের জন্যও কাজ করবে না? নতুন এবং আপডেট ফর্মগুলির জন্য কীভাবে এটি ব্যবহার করবেন তার উদাহরণ দেওয়ার জন্য আপনি নিজের উত্তরটি সম্পাদনা করতে পারেন? ধন্যবাদ।
এক্স 10

8
ড্যানিয়েলের উদাহরণের মূল চাবিকাঠি .id ক্ষেত্রটি পরীক্ষা করা। নতুনভাবে নির্মিত বস্তুর আইডি == কোনওটিই থাকবে না। যাইহোক, প্রাচীনতম উন্মুক্ত জ্যাঙ্গোর টিকিটের মধ্যে একটি এই সমস্যাটি। Code.djangoproject.com/ticket/342 দেখুন ।
পিটার রোয়েল

2
@ মোদীদীপ clean_descriptionফর্ম শ্রেণিতে একটি পদ্ধতি যুক্ত করুন ।
ড্যানিয়েল নাব

3
লিনাক্সে (উবুন্টু 15) / ক্রোম ভি 45, কেবলমাত্র পয়েন্টারটিকে একটি "অক্ষম হাত" এ পরিবর্তিত করে তবে ক্ষেত্রটি তখন ক্লিকযোগ্য। অক্ষম দ্বারা এটি প্রত্যাশার সাথে কাজ করে
সিমোন চিত্তাদিনি

7
এই উত্তরটি আপডেট করা দরকার। disabledজ্যাঙ্গো ১.৯- এ একটি নতুন ক্ষেত্র যুক্তি যুক্ত করা হয়েছে। যদি Field.disabledসেট করা থাকে True, তবে তার জন্য POST মান Fieldউপেক্ষা করা হবে। সুতরাং আপনি যদি 1.9 ব্যবহার করছেন তবে ওভাররাইড করার দরকার নেই clean, কেবল সেট করুন disabled = Trueএই উত্তরটি পরীক্ষা করুন ।
নরেন্দ্র-চৌধুরী

174

জাজানো ১.৯ ফিল্ড.ডিজিয়েবল বৈশিষ্ট্য যুক্ত করেছে: https://docs.djangoproject.com/en/stable/ref/forms/fields/#d अक्षम

অক্ষম বুলিয়ান আর্গুমেন্ট, সত্য হিসাবে সেট করা থাকলে, অক্ষম এইচটিএমএল বৈশিষ্ট্যটি ব্যবহার করে একটি ফর্ম ক্ষেত্র অক্ষম করে যাতে এটি ব্যবহারকারীদের দ্বারা সম্পাদনাযোগ্য হয় না। এমনকি যদি কোনও ব্যবহারকারী সার্ভারের কাছে জমা দেওয়া ক্ষেত্রের মানটি নিয়ে টেম্পার করে তবে তা ফর্মের প্রাথমিক তথ্য থেকে মানটির পক্ষে অগ্রাহ্য করা হবে।


1.8 এলটিএসের জন্য কিছুই নেই?
dnit13

9
কোনও আপডেট আমরা কীভাবে এটি আপডেটভিউতে ব্যবহার করতে পারি? যেমন এটি মডেল থেকে ক্ষেত্রগুলি উত্পন্ন করে ...
বিসিএস 18

6
সঠিক উত্তর. আমার সমাধান শ্রেণি মাইচেঞ্জফর্ম (ফর্মস.মোডেলফর্ম): Def __init __ (স্ব, * আরগস, ** কাওয়ার্গস): সুপার (মাইচ্যাঞ্জফর্ম, স্ব) সত্য
বিজয় কাঠাম

8
এটি একটি সমস্যাযুক্ত উত্তর - সেটিংস disabled=Trueবৈধতা ত্রুটিযুক্ত ব্যবহারকারীর কাছে মডেলটিকে ফিরিয়ে আনবে।
বেন

1
ভয়ঙ্কর হবে যদি আপনি একটি উদাহরণ অন্তর্ভুক্ত হতে পারে
geoidesic

95

readonlyএকটি উইজেট সেট করা কেবল ব্রাউজারে কেবলমাত্র পঠনযোগ্য ইনপুট তৈরি করে। একটি যোগ করার পদ্ধতি clean_skuযা আয় instance.skuনিশ্চিত ক্ষেত্রের মান ফর্ম স্তরের উপর পরিবর্তন করবে না।

def clean_sku(self):
    if self.instance: 
        return self.instance.sku
    else: 
        return self.fields['sku']

এইভাবে আপনি মডেলগুলির (অশোধিত সংরক্ষণ) ব্যবহার করতে পারেন এবং ক্ষেত্রের প্রয়োজনীয় ত্রুটি পাওয়া এড়াতে পারেন avoid


15
+1 আরও জটিল সংরক্ষণ () ওভাররাইড এড়ানোর একটি দুর্দান্ত উপায়। তবে, আপনি রিটার্নের আগে একটি উদাহরণ পরীক্ষা করতে চান (নিউলাইন-কম কমেন্ট মোডে): "যদি সেলফিনস্ট্যান্স: রিটার্ন সেলফিলিস্ট্যান্স.স্কু; অন্যথায়: সেলফ.ফিল্ডস ['স্কু']"
ড্যানিয়েল নাব

2
শেষ লাইনের জন্য, return self.cleaned_data['sku']ভাল বা ভাল হতে হবে ? ডক্স ব্যবহার করার সুপারিশ বলে মনে হচ্ছে cleaned_data: "এই পদ্ধতির ফেরত মান বিদ্যমান মান প্রতিস্থাপন cleaned_data, তাই এটি থেকে ক্ষেত্রের মান হওয়া আবশ্যক cleaned_dataঅথবা (এমনকি যদি এই পদ্ধতি এটি পরিবর্তন করা হয়নি) একটি নতুন পরিষ্কার মান।"
পিয়ানোজেমস

67

আওকারের উত্তর আমাকে অনেক সাহায্য করেছে!

আমি get_readonly_fields ব্যবহার করে জাজানো ১.৩ নিয়ে কাজ করার জন্য তার উদাহরণ পরিবর্তন করেছি ।

সাধারণত আপনার এইরকম কিছু ঘোষণা করা উচিত app/admin.py:

class ItemAdmin(admin.ModelAdmin):
    ...
    readonly_fields = ('url',)

আমি এইভাবে মানিয়ে নিয়েছি:

# In the admin.py file
class ItemAdmin(admin.ModelAdmin):
    ...
    def get_readonly_fields(self, request, obj=None):
        if obj:
            return ['url']
        else:
            return []

এবং এটি সূক্ষ্ম কাজ করে। এখন আপনি যদি কোনও আইটেম যুক্ত করেন তবে urlক্ষেত্রটি পঠনযোগ্য, তবে পরিবর্তিত অবস্থায় এটি কেবল পঠনযোগ্য হয়ে যায়।


55

একটি ForeignKeyক্ষেত্রের জন্য এই কাজটি করার জন্য , কয়েকটি পরিবর্তন করা দরকার। প্রথমত, SELECT HTMLট্যাগটিতে কেবল পঠনযোগ্য বৈশিষ্ট্য নেই। আমাদের ব্যবহার করা দরকারdisabled="disabled"পরিবর্তে আমাদের করা উচিত। তবে, ব্রাউজার সেই ক্ষেত্রটির জন্য কোনও ফর্ম ডেটা ফেরত পাঠায় না। সুতরাং আমাদের সেই ক্ষেত্রটি প্রয়োজন হবে না যাতে ক্ষেত্রটি সঠিকভাবে কার্যকর হয়। তারপরে আমাদের মানটি যা ব্যবহৃত হত তা পুনরায় সেট করতে হবে যাতে এটি ফাঁকাতে সেট করা হয় না।

সুতরাং বিদেশী কীগুলির জন্য আপনাকে এমন কিছু করতে হবে:

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)

এইভাবে ব্রাউজারটি ব্যবহারকারীটিকে ক্ষেত্র পরিবর্তন করতে দেয় না, এবং সর্বদা POSTএটি ফাঁকা রেখে দেওয়া হবে। এরপরে cleanক্ষেত্রটির মানটি উদাহরণ হিসাবে যা ছিল তা সেটাকে সেট করার জন্য আমরা পদ্ধতিটি ওভাররাইড করি ।


আমি এটিকে ফর্ম হিসাবে ব্যবহারের চেষ্টা করেছি TabularInline, তবে ব্যর্থ attrsহয়েছিলাম কারণ widgetসদ্য যুক্ত হওয়া, কেবলমাত্র পঠিত রেন্ডার সহ প্রথম দফার সাথে সমস্ত ক্ষেত্রে ভাগ করা হয়েছিল ।
hillিল

একটি দুর্দান্ত (আপডেট) সমাধান! দুর্ভাগ্যক্রমে এই এবং বাকীগুলির মধ্যে সমস্যা রয়েছে যখন সমস্ত "অক্ষম" মান খালি হওয়ার সাথে সাথে ফর্ম ত্রুটি রয়েছে।
মাইকেল থম্পসন

28

জ্যাঙ্গো 1.2+ এর জন্য, আপনি ক্ষেত্রটি এমনভাবে ওভাররাইড করতে পারেন:

sku = forms.CharField(widget = forms.TextInput(attrs={'readonly':'readonly'}))

6
এটি যোগ করার সময় ক্ষেত্রটি সম্পাদনা করার অনুমতি দেয় না, যা মূল প্রশ্নটি।
ম্যাট এস

এটিই আমি উত্তর খুঁজছি। Field disabledআমি যা চাই তা করি না কারণ এটি ক্ষেত্রটি অক্ষম করে, তবে লেবেলও সরিয়ে দেয় / অদৃশ্য করে তোলে।
শিববধু

18

আমি একটি মিক্সআইন ক্লাস তৈরি করেছি যা আপনি পঠনযোগ্য কেবল পুনরাবৃত্ত ক্ষেত্র যোগ করতে সক্ষম হবেন যা অ-প্রথম সম্পাদনাতে ক্ষেত্রগুলি অক্ষম এবং সুরক্ষিত করবে:

(ড্যানিয়েলের এবং মুহুকের উত্তরের ভিত্তিতে)

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')

11

আমি কেবলমাত্র পঠনযোগ্য ক্ষেত্রের জন্য সর্বাধিক সহজ উইজেট তৈরি করেছি - ফর্মগুলিতে এটি ইতিমধ্যে কেন নেই তা আমি সত্যিই দেখতে পাই না:

class ReadOnlyWidget(widgets.Widget):
    """Some of these values are read only - just a bit of text..."""
    def render(self, _, value, attrs=None):
        return value

ওইরূপে থাকা:

my_read_only = CharField(widget=ReadOnlyWidget())

খুব সহজ - এবং আমাকে কেবল আউটপুট দেয়। কেবলমাত্র পঠনযোগ্য মানগুলির একটি গুচ্ছ সহ একটি ফর্মসেটে সহজ। অবশ্যই - আপনি কিছুটা বেশি চালাক হতে পারেন এবং এটির সাথে একটি ডিভ দিতে পারেন যাতে আপনি এতে ক্লাস যুক্ত করতে পারেন।


2
দেখতে সেক্সি লাগছে, তবে বিদেশী কী কীভাবে পরিচালনা করবেন?
andilabs

unicode(value)পরিবর্তে সম্ভবত এটি তৈরি করুন । ইউনিকোড ডান্ডারটি বোধগম্য বলে ধরে নিলে আপনি তা পেয়ে যাবেন।
ড্যানি স্ট্যাপল

বিদেশী কীগুলির জন্য, আপনাকে একটি "মডেল" বৈশিষ্ট্য যুক্ত করতে হবে এবং "গেট (মান)" ব্যবহার করতে হবে। পরীক্ষা করে দেখুন আমার সারকথা
দয়া

10

আমি একটি একই সমস্যা জুড়ে দৌড়ে। দেখে মনে হচ্ছে আমি আমার মডেলএডমিন ক্লাসে "get_readonly_fields" পদ্ধতিটি সংজ্ঞায়িত করে এটি সমাধান করতে সক্ষম হয়েছি।

এটার মতো কিছু:

# In the admin.py file

class ItemAdmin(admin.ModelAdmin):

    def get_readonly_display(self, request, obj=None):
        if obj:
            return ['sku']
        else:
            return []

সুন্দর জিনিসটি হ'ল objআপনি যখন কোনও নতুন আইটেম যুক্ত করবেন তখন কিছুই হবে না বা আপনি কোনও বিদ্যমান আইটেম পরিবর্তন করার সময় এটি সম্পাদিত হচ্ছে।

get_readonly_display এখানে নথিভুক্ত করা হয়েছে: http://docs.djangoproject.com/en/1.2/ref/contrib/admin/#modeladmin- পদ্ধতি


6

একটি সহজ বিকল্পটি কেবলমাত্র form.instance.fieldNameপরিবর্তে টেম্পলেটটিতে টাইপ করা form.fieldName


এবং ক্ষেত্রের verbos_nameবা কিভাবে label? আমি কীভাবে জ্যাঙ্গো টেম্পলেটে `লেবেলটি প্রদর্শন করতে পারি? @ এলজক্লার্ক
তিমি 52Hz

6

আমি জাজানো 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

এটি কেবল ফ্রন্টযুক্ত থেকে অবরুদ্ধ হবে। যে কেউ বাইপাস করতে পারে। আপনি যদি সংবেদনশীল ডেটা ব্যবহার করেন এটি একটি সুরক্ষা সমস্যা তৈরি করবে
সারথ আক

এটা নিরাপদ; এটি ব্যাকএন্ড ব্লক যেহেতু জ্যাঙ্গো> = 1.10 docs.djangoproject.com/en/1.10/ref/forms/fields/...
timdiels

5

হামফ্রির পোস্টে দরকারী সংযোজন হিসাবে আমার জ্যাঙ্গো-রিভার্সন নিয়ে কিছু সমস্যা ছিল কারণ এটি এখনও অক্ষম ক্ষেত্রগুলিকে 'পরিবর্তিত' হিসাবে নিবন্ধিত করেছে। নিম্নলিখিত কোডটি সমস্যার সমাধান করে।

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)

5

যেহেতু আমি এখনও মন্তব্য করতে পারি না ( মুউহকের সমাধান ), আমি পৃথক উত্তর হিসাবে প্রতিক্রিয়া জানাব । এটি আমার পক্ষে কাজ করা একটি সম্পূর্ণ কোড উদাহরণ:

def clean_sku(self):
  if self.instance and self.instance.pk:
    return self.instance.sku
  else:
    return self.cleaned_data['sku']

5

তবুও আবার, আমি আরও একটি সমাধান সরবরাহ করতে যাচ্ছি :) আমি হামফ্রির কোডটি ব্যবহার করছিলাম , সুতরাং এটি এর ভিত্তিতে তৈরি।

যাইহোক, আমি ক্ষেত্রটি এক হিসাবে সমস্যা নিয়ে দৌড়েছি ModelChoiceField। প্রথম অনুরোধে সবকিছু কাজ করবে। তবে, যদি ফর্মसेटটি কোনও নতুন আইটেম যুক্ত করার চেষ্টা করে এবং বৈধতা ব্যর্থ হয়, তবে "বিদ্যমান" ফর্মগুলির সাথে কিছু ভুল হয়ে গিয়েছিল যেখানে SELECTEDবিকল্পটি ডিফল্টটিতে পুনরায় সেট করা হচ্ছে where---------

যাইহোক, আমি কীভাবে এটি ঠিক করতে পারি তা বুঝতে পারি না। সুতরাং পরিবর্তে, (এবং আমি মনে করি এটি ফর্মটি আসলে পরিষ্কার), আমি ক্ষেত্রগুলি তৈরি করেছি HiddenInputField()। এর অর্থ হ'ল টেমপ্লেটে আপনাকে আরও কিছু কাজ করতে হবে।

সুতরাং আমার জন্য সমাধানটি ফর্মটি সরল করা ছিল:

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()

এবং তারপরে টেমপ্লেটে আপনাকে ফর্মসেটটির কিছু ম্যানুয়াল লুপিং করতে হবে

সুতরাং, এই ক্ষেত্রে আপনি টেমপ্লেটে এই জাতীয় কিছু করতে হবে:

<div>
    {{ form.instance.sku }} <!-- This prints the value -->
    {{ form }} <!-- Prints form normally, and makes the hidden input -->
</div>

এটি আমার পক্ষে এবং ফর্ম হেরফেরের জন্য আরও কিছুটা ভাল কাজ করেছে।


4

আমি একই সমস্যার মধ্যে যাচ্ছি তাই আমি এমন একটি মিক্সিন তৈরি করেছি যা মনে হয় আমার ব্যবহারের ক্ষেত্রে কাজ করে।

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

ব্যবহার, কেবলমাত্র কোনটি পড়তে হবে তা কেবল নির্ধারণ করুন:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')

আমি মনে করি এটি আমার নিজের মেশিনের চেয়ে কিছুটা বেশি পঠনযোগ্য। এমনকি সম্ভবত আরও দক্ষ, কারণ এই ক্লিনগুলি বৈধতা ত্রুটি বাড়ায় না ...
ক্রাইস্টোফে

আমি একটি ত্রুটি 'collections.OrderedDict' object has no attribute 'iteritems'
পেয়েছি

4

আপনার যদি একাধিক পঠনযোগ্য কেবল ক্ষেত্রের প্রয়োজন হয় তবে আপনি নীচে প্রদত্ত যে কোনও পদ্ধতি ব্যবহার করতে পারেন

পদ্ধতি 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

পদ্ধতি 2

উত্তরাধিকার পদ্ধতি

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',)

3

একটি সাধারণ উদাহরণ সহ আরও দুটি (অনুরূপ) পদ্ধতির:

1) প্রথম পদ্ধতির - সংরক্ষণ () পদ্ধতিতে ক্ষেত্র অপসারণ, উদাহরণস্বরূপ (পরীক্ষিত নয়;)):

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) দ্বিতীয় পদ্ধতির - পরিষ্কার পদ্ধতিতে প্রাথমিক মানটিতে ক্ষেত্রটি পুনরায় সেট করুন:

def clean_<fieldname>(self):
    return self.initial[<fieldname>] # or getattr(self.instance, fieldname)

দ্বিতীয় পদ্ধতির উপর ভিত্তি করে আমি এটি এটিকে সাধারণকরণ করেছি:

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)

3

অ্যাডমিন সংস্করণটির জন্য, আমি মনে করি আপনার যদি একাধিক ক্ষেত্র থাকে তবে এটি একটি আরও কমপ্যাক্ট উপায়:

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

3

ইয়ামিকেপের উত্তরের ভিত্তিতে , আমি একটি আরও ভাল এবং খুব সহজ সমাধান পেয়েছি যা ModelMultipleChoiceFieldক্ষেত্রগুলিও পরিচালনা করে।

form.cleaned_dataক্ষেত্রগুলি থেকে ক্ষেত্র সরিয়ে ফেলা ক্ষেত্রগুলি সংরক্ষণ থেকে বাধা দেয়:

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()

ব্যবহার:

class MyFormWithReadOnlyFields(ReadOnlyFieldsMixin, MyForm):
    readonly_fields = ('field1', 'field2', 'fieldx')

2

খ্রিস্টোফের ৩১ এর উত্তরের ভিত্তিতে এখানে আরও কিছুটা জড়িত সংস্করণ । এটি "কেবলমাত্র পঠনযোগ্য" বৈশিষ্ট্যের উপর নির্ভর করে না। এটি এর সমস্যাগুলি তৈরি করে, যেমন নির্বাচন করা বাক্সগুলি এখনও পরিবর্তনযোগ্য এবং ডেটাপিকারগুলি এখনও পপ আপ করে চলে যায় go

পরিবর্তে, এটি ফর্ম ক্ষেত্রগুলি উইজেটকে কেবলমাত্র পঠনযোগ্য উইজেটে আবৃত করে, ফর্মটি এখনও বৈধ করে তোলা। মূল উইজেটের সামগ্রীটি <span class="hidden"></span>ট্যাগগুলির অভ্যন্তরে প্রদর্শিত হয় । যদি উইজেটের কোনও render_readonly()পদ্ধতি থাকে তবে তা এটি দৃশ্যমান পাঠ্য হিসাবে ব্যবহার করে, অন্যথায় এটি মূল উইজেটের এইচটিএমএলকে বিশ্লেষণ করে সেরা উপস্থাপনের অনুমান করার চেষ্টা করে।

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)

1

এটি কি সহজ উপায়?

ডানদিকের কোডটিতে ঠিক এরকম কিছু:

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)

এটা ঠিক কাজ করে!


1

জাঙ্গো 1.9+ এর জন্য
আপনি ক্ষেত্রকে অক্ষম করতে ফিল্ড অক্ষম যুক্তিটি ব্যবহার করতে পারেন। উদাহরণস্বরূপ form.py ফাইল থেকে কোড স্নিপেটে, আমি কর্মচারী_কোড ক্ষেত্রকে অক্ষম করে দিয়েছি

class EmployeeForm(forms.ModelForm):
    employee_code = forms.CharField(disabled=True)
    class Meta:
        model = Employee
        fields = ('employee_code', 'designation', 'salary')

রেফারেন্স https://docs.djangoproject.com/en/2.0/ref/forms/fields/#d अक्षम


1

আপনি যদি কাজ করে থাকেন Django ver < 1.9(এতে অ্যাট্রিবিউট 1.9যুক্ত Field.disabledহয়েছে) আপনি নিজের ফর্ম __init__পদ্ধতিতে নিম্নলিখিত ডেকরেটার যুক্ত করার চেষ্টা করতে পারেন :

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):
        ...

মূল ধারণাটি হ'ল যদি ক্ষেত্রটি থাকে তবে readonlyআপনার অন্য কোনও মানের প্রয়োজন নেই initial

PS: সেট করতে ভুলবেন না yuor_form_field.widget.attrs['readonly'] = True


0

আপনি যদি জ্যাঙ্গো অ্যাডমিন ব্যবহার করছেন তবে এখানে সহজ সমাধান রয়েছে।

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',)

0

আমি মনে করি আপনার সেরা বিকল্পটি কেবলমাত্র আপনার পাঠানো টেম্পলেটে কেবলমাত্র পাঠ্য গুণাবলী অন্তর্ভুক্ত করা <span>বা <p>এটি কেবলমাত্র পড়লে ফর্মটিতে অন্তর্ভুক্ত করার পরিবর্তে হবে।

ফর্মগুলি ডেটা সংগ্রহ করার জন্য, এটি প্রদর্শন না করে। বলা হচ্ছে, একটি readonlyউইজেট এবং স্ক্রব পোস্ট ডেটাতে প্রদর্শিত বিকল্পগুলি সূক্ষ্ম সমাধান are

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.