django - form - বাংলায় জ্যাঙ্গো




একটি Django ফর্মের মধ্যে, আমি কিভাবে একটি ক্ষেত্র পাঠ্য(অথবা অক্ষম) করতে পারি যাতে এটি সম্পাদনা করা যায় না? (18)

Django 1.2+ এর জন্য, আপনি ক্ষেত্রটিকে ওভাররাইড করতে পারেন:

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

একটি Django ফর্ম, আমি কিভাবে শুধুমাত্র ক্ষেত্র পড়তে (অথবা নিষ্ক্রিয়) করতে পারি?

যখন ফর্মটি একটি নতুন এন্ট্রি তৈরি করার জন্য ব্যবহার করা হচ্ছে, সমস্ত ক্ষেত্র সক্রিয় করা উচিত - কিন্তু যখন রেকর্ড আপডেট মোডে থাকে তখন কিছু ক্ষেত্র শুধুমাত্র-পড়তে হবে।

উদাহরণস্বরূপ, একটি নতুন 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 পুনঃব্যবহৃত করা যাবে? Item ItemForm বা Item মডেল ক্লাসে কি পরিবর্তন প্রয়োজন হবে? আইটেমটি হালনাগাদ করার জন্য আমাকে কি আরেকটি ক্লাস, " ItemUpdateForm " লিখতে হবে?

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

Django 1.9 Field.disabled বৈশিষ্ট্য যুক্ত করেছে: Field.disabled

নিষ্ক্রিয় বুলিয়ান যুক্তি, সত্যতে সেট করা থাকলে, নিষ্ক্রিয় HTML বৈশিষ্ট্য ব্যবহার করে একটি ফর্ম ক্ষেত্র অক্ষম করে যাতে এটি ব্যবহারকারীদের দ্বারা সম্পাদনাযোগ্য না হয়। এমনকি যদি সার্ভারে মাঠের মূল্যের সাথে যুক্ত ব্যবহারকারীর সঞ্চার হয় তবে ফর্মটির প্রাথমিক ডেটা থেকে মানটির পক্ষে এটি অগ্রাহ্য করা হবে।


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

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

আপনি Django অ্যাডমিন ব্যবহার করা হয়, এখানে সহজ সমাধান।

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

আমি Django 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

আমি এই মত এই সমস্যা সমাধান:

    class UploadFileForm(forms.ModelForm):
     class Meta:
      model = FileStorage
      fields = '__all__'
      widgets = {'patient': forms.HiddenInput()}

মতামত:

form = UploadFileForm(request.POST, request.FILES, instance=patient, initial={'patient': patient})

এটা সব।


আমি একটি অনুরূপ সমস্যা জুড়ে দৌড়ে। মনে হচ্ছে আমি আমার ModelAdmin ক্লাসে "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-methods


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

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

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

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

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

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


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

ফর্ম তথ্য সংগ্রহের জন্য, এটি প্রদর্শন করা হয় না। যে বলা হচ্ছে, একটি readonly উইজেট এবং স্ক্রব POST তথ্য প্রদর্শন করার অপশন জরিমানা সমাধান।


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

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)

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


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

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

যাইহোক, আমি কিভাবে ঠিক করতে হবে তা চিন্তা করতে পারিনি। সুতরাং পরিবর্তে, (এবং আমি মনে করি এটি আসলে ফর্মের মধ্যে ক্লিনার), আমি ক্ষেত্রগুলিকে HideInputField () তৈরি করেছি। এটি শুধু আপনাকে টেমপ্লেটে একটু বেশি কাজ করতে হবে।

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

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

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

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

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

এই আমার জন্য এবং কম ফর্ম ম্যানিপুলেশন সঙ্গে একটু ভাল কাজ।


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

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

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

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)

ইয়ামিকিপের উত্তরের উপর ভিত্তি করে, আমি একটি উন্নত এবং খুব সহজ সমাধান খুঁজে পেয়েছি যা 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')

এই উত্তর হিসাবে উল্লেখ করা হয়েছে, Django 1.9 Field.disabled বৈশিষ্ট্য যুক্ত করেছে:

নিষ্ক্রিয় বুলিয়ান যুক্তি, সত্যতে সেট করা থাকলে, নিষ্ক্রিয় HTML বৈশিষ্ট্য ব্যবহার করে একটি ফর্ম ক্ষেত্র অক্ষম করে যাতে এটি ব্যবহারকারীদের দ্বারা সম্পাদনাযোগ্য না হয়। এমনকি যদি সার্ভারে মাঠের মূল্যের সাথে যুক্ত ব্যবহারকারীর সঞ্চার হয় তবে ফর্মটির প্রাথমিক ডেটা থেকে মানটির পক্ষে এটি অগ্রাহ্য করা হবে।

Django 1.8 এবং এর আগে, উইজেটে এন্ট্রি নিষ্ক্রিয় করতে এবং দূষিত POST হ্যাকগুলি রোধ করতে আপনাকে অবশ্যই ফর্ম ক্ষেত্রটিতে 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 আপনি সম্পাদনা করছেন এমন অন্য শর্তের সাথে if instance and instance.pk প্রতিস্থাপন করুন। আপনি কেবল readonly পরিবর্তে ইনপুট ক্ষেত্রটিতে disabled বৈশিষ্ট্য সেট করতে পারেন।

clean_sku ফাংশন নিশ্চিত করবে যে clean_sku মানটি POST দ্বারা ওভাররাইড করা হবে না।

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


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 পদ্ধতিটি ওভাররাইড করে যা মূলত উদাহরণ হিসাবে ছিল।