কোনও ফর্মের পরিষ্কার () পদ্ধতিতে আমি কীভাবে অনুরোধ অবজেক্ট বা অন্য কোনও ভেরিয়েবল অ্যাক্সেস করব?


99

আমি একটি ফর্মের পরিষ্কার পদ্ধতিটির জন্য অনুরোধ.ইউসারটির চেষ্টা করছি, তবে আমি কীভাবে অনুরোধের অবজেক্টটি অ্যাক্সেস করতে পারি? ভেরিয়েবল ইনপুটটিকে অনুমতি দেওয়ার জন্য কি আমি পরিষ্কার পদ্ধতিটি পরিবর্তন করতে পারি?

উত্তর:


158

থ্রিডোকলসে স্টোর করা - বারের উত্তরটি খুব খারাপ ধারণা। এইভাবে এটি করার কোনও কারণ নেই।

__init__অতিরিক্ত কিওয়ার্ড আর্গুমেন্ট গ্রহণের জন্য ফর্মের পদ্ধতিটিকে ওভাররাইড করা একটি আরও ভাল উপায় request। এটি অনুরোধটি ফর্মটিতে সঞ্চয় করে , যেখানে এটি প্রয়োজন হয় এবং কোথা থেকে আপনি আপনার পরিষ্কার পদ্ধতিতে এটি অ্যাক্সেস করতে পারেন।

class MyForm(forms.Form):

    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(MyForm, self).__init__(*args, **kwargs)


    def clean(self):
        ... access the request object via self.request ...

এবং আপনার দৃষ্টিতে:

myform = MyForm(request.POST, request=request)

4
আপনি এই ক্ষেত্রে ঠিক আছেন। তবে এটিতে এটি রূপান্তরিত ফর্ম / দর্শন পছন্দ করতে পারে না। এছাড়াও, থ্রেড লোকাল স্টোরের জন্য এমন ব্যবহারের ক্ষেত্রে রয়েছে যেখানে পদ্ধতি পরামিতিগুলি বা উদাহরণের ভেরিয়েবলগুলি যুক্ত করা অসম্ভব। অনুরোধ ডেটাতে অ্যাক্সেস প্রয়োজন এমন একটি ক্যোয়ারী ফিল্টারে কলযোগ্য যুক্তিটি সম্পর্কে ভাবুন। আপনি কলটিতে কোনও প্যারামিটার যোগ করতে পারবেন না, বা রেফারেন্সের কোনও উদাহরণ নেই।
বের

4
আপনি যখন প্রশাসক ফর্মটি প্রসারিত করেন তখন এটি কার্যকর হয় না, কারণ আপনি অনুরোধটি বৈধ করে আপনার ফর্মটি শুরু করতে পারেন। কোন ধারণা?
মোরডি

14
আপনি কেন বলেন যে থ্রেড-লোকাল স্টোরেজ ব্যবহার করা খুব খারাপ ধারণা? এটি সর্বত্র সর্বত্র অনুরোধটি পাস করার জন্য কোডটি ফেলে দেওয়া এড়ায়।
মাইকেল মায়ার

9
আমি অনুরোধটি নিজেই ফর্মটিতে পৌঁছে দেবো না, বরং অনুরোধের ক্ষেত্রগুলি যা আপনার প্রয়োজন (যেমন ব্যবহারকারী), অন্যথায় আপনি আপনার ফর্ম যুক্তিকে অনুরোধ / প্রতিক্রিয়া চক্রের সাথে বেঁধে রাখেন যা পরীক্ষা আরও শক্ত করে তোলে।
অ্যান্ড্রু ইঙ্গ্রাম

4
অ্যাডমিনে ফর্মগুলি নিয়ে কাজ করার জন্য ক্রিস প্র্যাটের একটি ভাল সমাধানও রয়েছে od মোডেলএডমিন
র‌্যাডটেক 8:25 '

35

আপডেট 10/25/2011 : আমি এখন পদ্ধতির পরিবর্তে গতিশীলভাবে তৈরি ক্লাসের সাথে এটি ব্যবহার করছি, কারণ জ্যাঙ্গো ১.৩ অন্যথায় কিছুটা অদ্ভুততা প্রদর্শন করে।

class MyModelAdmin(admin.ModelAdmin):
    form = MyCustomForm
    def get_form(self, request, obj=None, **kwargs):
        ModelForm = super(MyModelAdmin, self).get_form(request, obj, **kwargs)
        class ModelFormWithRequest(ModelForm):
            def __new__(cls, *args, **kwargs):
                kwargs['request'] = request
                return ModelForm(*args, **kwargs)
        return ModelFormWithRequest

তারপরে MyCustomForm.__init__নিম্নরূপে ওভাররাইড করুন :

class MyCustomForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        self.request = kwargs.pop('request', None)
        super(MyCustomForm, self).__init__(*args, **kwargs)

এর পরে আপনি কোন পদ্ধতি থেকে অনুরোধ বস্তুর অ্যাক্সেস করতে পারেন ModelFormসঙ্গে self.request


4
ক্রিস, "ডিএফ __init __ (স্ব, অনুরোধ = কিছুই নয়, * আরগস, ** কোয়ার্গস)" খারাপ, কারণ এটি প্রথম অবস্থানগত আরগ এবং কাওয়ার্গে উভয়ের অনুরোধের সাথে শেষ হবে। আমি এটিকে "ডিএফ __init __ (স্ব, * আরগস, ** কোয়ার্গস)" এ পরিবর্তন করেছি এবং এটি কার্যকর।
ডিসি

4
ওফফফ। এটা আমার পক্ষ থেকে একটি ভুল ছিল। আমি অন্যান্য আপডেট করার সময় আমি কোডটির সেই অংশটি আপডেট করতে অবহেলা করেছি। ধরার জন্য ধন্যবাদ আপডেট হয়েছে।
ক্রিস প্র্যাট

4
এটি কি আসলে একটি মেটাক্লাস? আমি মনে করি এটি কেবল স্বাভাবিক ওভাররাইডিং, আপনি __new__'ক্লার্গ্স'কে অনুরোধ যোগ করেছেন যা পরে শ্রেণীর __init__পদ্ধতিতে পাস করা হবে । ক্লাসের নামকরণের চেয়ে ModelFormWithRequestআমি এর থেকে অর্থ আরও স্পষ্ট মনে করি ModelFormMetaClass
k4ML

4
এটি কোনও মেটাগ্লাস নয়! দেখুন stackoverflow.com/questions/100003/...
frnhr

32

এটি মূল্যবান কিসের জন্য, যদি আপনি ফাংশন ভিত্তিক ভিউগুলির পরিবর্তে শ্রেণিভিত্তিক দর্শনগুলি ব্যবহার get_form_kwargsকরেন তবে আপনার সম্পাদনা দৃশ্যে ওভাররাইড করুন । একটি কাস্টম ক্রিয়েভ ভিউয়ের উদাহরণ কোড :

from braces.views import LoginRequiredMixin

class MyModelCreateView(LoginRequiredMixin, CreateView):
    template_name = 'example/create.html'
    model = MyModel
    form_class = MyModelForm
    success_message = "%(my_object)s added to your site."

    def get_form_kwargs(self):
        kw = super(MyModelCreateView, self).get_form_kwargs()
        kw['request'] = self.request # the trick!
        return kw

    def form_valid(self):
        # do something

উপরের ভিউ কোডটি requestফর্মটির __init__নির্মাণকারীর কার্যত কীওয়ার্ড আর্গুমেন্টগুলির মধ্যে একটি হিসাবে উপলব্ধ করবে । সুতরাং আপনার ModelFormকাজ:

class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def __init__(self, *args, **kwargs):
        # important to "pop" added kwarg before call to parent's constructor
        self.request = kwargs.pop('request')
        super(MyModelForm, self).__init__(*args, **kwargs)

4
এটি আমার পক্ষে কাজ করেছে। আমি নোটটি তৈরি করেছি কারণ জটিল উইজার্ডফর্ম যুক্তির কারণে আমি যাইহোক get_for_kwargs ব্যবহার করছিলাম। উইজার্ডফর্মের জন্য আমি দেখেছি এমন কোনও উত্তর নেই।
ডেটাকিড

4
আমার ছাড়াও কেউ কি মনে করেন যে এটি ওয়েব ফ্রেমওয়ার্কের জন্য বেশ অদ্ভুত কিছু করার জন্য কেবল একটি বড় জগাখিচুড়ি? জ্যাঙ্গো দুর্দান্ত তবে এটি আমাকে কখনও সিবিভি ব্যবহার করতে চায় না।
trpt4 Him 15

4
আইএমএইচওভুক্ত সিবিভিগুলির সুবিধাগুলি এতদূর এফবিভিগুলির ত্রুটিগুলি ছাড়িয়ে যায়, বিশেষত যদি আপনি 25+ ডিভস রাইটিং কোড সহ একটি বড় প্রকল্পে কাজ করেন যা 100% ইউনিট পরীক্ষার কভারেজের জন্য লক্ষ্য করে। নিশ্চিত নয় যে জ্যাঙ্গোর নতুন সংস্করণগুলি স্বয়ংক্রিয়ভাবে এর requestমধ্যে বস্তুটি রাখে cater get_form_kwargs
জোসেফ ভিক্টর জমিট

অনুরূপ শিরাতে, get_for_kwargs এ অবজেক্টের আইডেন্সের আইডি অ্যাক্সেস করার কোনও উপায় আছে কি?
হাসান বৈগ

4
@ হাসানবাগ সম্ভবত ব্যবহার করছেন self.get_object? CreateViewপ্রসারিত SingleObjectMixin। তবে এটি কার্যকর হয় বা একটি ব্যতিক্রম উত্থাপন করে কিনা আপনি কোনও নতুন অবজেক্ট তৈরি করছেন বা বিদ্যমানটিকে আপডেট করছেন কিনা তার উপর নির্ভর করে; যেমন উভয় ক্ষেত্রে পরীক্ষা (এবং অবশ্যই মুছে ফেলা)।
জোসেফ ভিক্টর জম্মিত 22'18

17

সাধারণ অ্যাপ্রোচ হ'ল একটি মিডওয়্যার ব্যবহার করে অনুরোধ অবজেক্টটি থ্রেড-লোকাল রেফারেন্সে সঞ্চয় করা। তারপরে আপনি form.clean () পদ্ধতি সহ আপনার অ্যাপের যে কোনও জায়গা থেকে এটিকে অ্যাক্সেস করতে পারবেন can

ফর্ম.ক্লিয়েন () পদ্ধতির স্বাক্ষর পরিবর্তন করার অর্থ আপনার নিজের জ্যাঙ্গোর পরিবর্তিত সংস্করণ রয়েছে যা আপনি যা চান তা নাও হতে পারে।

মিডলওয়্যার গণনা ধন্যবাদ এই মত দেখতে কিছু:

import threading
_thread_locals = threading.local()

def get_current_request():
    return getattr(_thread_locals, 'request', None)

class ThreadLocals(object):
    """
    Middleware that gets various objects from the
    request object and saves them in thread local storage.
    """
    def process_request(self, request):
        _thread_locals.request = request

জ্যাঙ্গো ডক্সে বর্ণিত এই মিডওয়্যারটিকে নিবন্ধভুক্ত করুন


4
উপরের মতামত সত্ত্বেও, এই পদ্ধতিটি কাজ করে যেখানে অন্য পদ্ধতিটি করে না। ইন ডিমে ফর্ম অবজেক্টের একটি অ্যাট্রিবিউট সেট করা নির্ভরযোগ্যভাবে পরিষ্কার পদ্ধতিগুলিতে বহন করে না, থ্রেড লোকাল নির্ধারণ করা এই ডেটা বহন করতে দেয় does
rplevy

4
@Rplevy আপনি ফর্মের উদাহরণ তৈরি করার সময় আপনি কি আসলে অনুরোধের বস্তুটি পাস করেছেন? আপনি যদি খেয়াল করেন নি যে এটি কীওয়ার্ড আর্গুমেন্ট ব্যবহার করে **kwargs, যার অর্থ আপনাকে অনুরোধের অবজেক্টটি পাস করতে হবে MyForm(request.POST, request=request)
আনোড করুন

13

জাজানো অ্যাডমিনের জন্য, জ্যাঙ্গো ১.৮ এ

class MyModelAdmin(admin.ModelAdmin):
    ...
    form = RedirectForm

    def get_form(self, request, obj=None, **kwargs):
        form = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
        form.request = request
        return form

4
উপরে উপরে রেট করা পদ্ধতিটি প্রকৃতপক্ষে জ্যাঙ্গো 1.6 এবং 1.9 এর মধ্যে কোথাও কাজ করা বন্ধ করে দিয়েছে বলে মনে হচ্ছে। এই এক কাজ করে এবং অনেক খাটো। ধন্যবাদ!
রায়ক

9

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

যেহেতু আমি অনুরোধটি ফর্মটির পক্ষে যুক্ত করার জন্য দৃষ্টিভঙ্গিটি পরিবর্তন করতে চাইনি, তাই আমি যা করেছি তা নিম্নলিখিত:

class MyCustomForm(forms.ModelForm):
    class Meta:
        model = MyModel

    def clean(self):
        # make use of self.request here

class MyModelAdmin(admin.ModelAdmin):
    form = MyCustomForm
    def get_form(self, request, obj=None, **kwargs):
        ModelForm = super(MyModelAdmin, self).get_form(request, obj=obj, **kwargs)
        def form_wrapper(*args, **kwargs):
            a = ModelForm(*args, **kwargs)
            a.request = request
            return a
    return form_wrapper

তার জন্য ধন্যবাদ. কুইক টাইপো: obj=objনা obj=Noneলাইন 11.
ফ্রাসোয়া স্থায়ী

সত্যিই দুর্দান্ত উত্তর, আমি এটি ভালবাসি!
লুক ডুপিন

জ্যাঙ্গো 1.9 সরবরাহ করে: 'function' object has no attribute 'base_fields'। তবে, সরল (বন্ধ না করে) @ ফরাসোয়াস উত্তরটি সহজেই কাজ করে।
রাত্রিটু

5

আপনি সর্বদা এই পদ্ধতিটি ব্যবহার করতে পারবেন না (এবং এটির সম্ভবত খারাপ অভ্যাস), তবে আপনি যদি কেবলমাত্র একটি ফর্মটিতে ফর্মটি ব্যবহার করেন তবে আপনি এটিকে ভিউ পদ্ধতির মধ্যেই সুযোগ দিতে পারেন।

def my_view(request):

    class ResetForm(forms.Form):
        password = forms.CharField(required=True, widget=forms.PasswordInput())

        def clean_password(self):
            data = self.cleaned_data['password']
            if not request.user.check_password(data):
                raise forms.ValidationError("The password entered does not match your account password.")
            return data

    if request.method == 'POST':
        form = ResetForm(request.POST, request.FILES)
        if form.is_valid():

            return HttpResponseRedirect("/")
    else:
        form = ResetForm()

    return render_to_response(request, "reset.html")

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

5

ড্যানিয়েল রোজম্যানের উত্তর এখনও সেরা। তবে আমি কয়েকটি কারণে কীওয়ার্ড আর্গুমেন্টের পরিবর্তে অনুরোধের জন্য প্রথম অবস্থানিক যুক্তিটি ব্যবহার করব:

  1. আপনি একই নামে কোনও কাওয়ার্গকে ওভাররাইড করার ঝুঁকিটি চালান না
  2. অনুরোধটি optionচ্ছিক যা সঠিক নয়। অনুরোধের বৈশিষ্ট্যটি এই প্রসঙ্গে কখনও হওয়া উচিত নয়।
  3. আপনি আরগস এবং কাওয়ার্গগুলিকে সংশোধন না করেই পরিষ্কারভাবে পেরেন্ট ক্লাসে দিতে পারেন।

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

class MyForm(forms.Form):

  def __init__(self, request, *args, **kwargs):
      self._my_request = request
      super(MyForm, self).__init__(*args, **kwargs)


  def clean(self):
      ... access the request object via self._my_request ...


3

আপনার প্রয়োজন অনুসারে এই প্রশ্নের উত্তর আমার কাছে আছে যা আপনি ফর্মের পরিষ্কার পদ্ধতিতে ব্যবহারকারীকে অ্যাক্সেস করতে চান। আপনি এটি চেষ্টা করতে পারেন। View.py

person=User.objects.get(id=person_id)
form=MyForm(request.POST,instance=person)

form.py

def __init__(self,*arg,**kwargs):
    self.instance=kwargs.get('instance',None)
    if kwargs['instance'] is not None:
        del kwargs['instance']
    super(Myform, self).__init__(*args, **kwargs)

এখন আপনি form.py এ যে কোনও পরিষ্কার পদ্ধতিতে সেলফিনস্ট্যান্স অ্যাক্সেস করতে পারবেন


0

আপনি যখন "প্রস্তুত" জ্যাঙ্গো শ্রেণীর দর্শনগুলির মাধ্যমে এটি অ্যাক্সেস করতে চান তখন CreateViewজানার মতো একটি ছোট কৌশল আছে (= অফিশিয়াল সমাধান বাক্সটি কার্যকর করে না)। আপনার নিজের মধ্যে CreateView আপনাকে এই জাতীয় কোড যুক্ত করতে হবে:

class MyCreateView(LoginRequiredMixin, CreateView):
    form_class = MyOwnForm
    template_name = 'my_sample_create.html'

    def get_form_kwargs(self):
        result = super().get_form_kwargs()
        result['request'] = self.request
        return result

= সংক্ষেপে এটি হ'ল requestজ্যাঙ্গোর তৈরি / আপডেট দেখুন সহ আপনার ফর্মটিতে যাওয়ার সমাধান ।

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