জ্যাঙ্গোর এক পৃষ্ঠায় একাধিক ফর্ম হ্যান্ডেল করার সঠিক উপায়


200

আমার দুটি ফর্ম প্রত্যাশার একটি টেমপ্লেট পৃষ্ঠা রয়েছে। আমি যদি কেবল একটি ফর্ম ব্যবহার করি তবে জিনিসগুলি এই আদর্শ উদাহরণ হিসাবে ঠিক আছে:

if request.method == 'POST':
    form = AuthorForm(request.POST,)
    if form.is_valid():
        form.save()
        # do something.
else:
    form = AuthorForm()

তবে আমি যদি একাধিক ফর্মের সাথে কাজ করতে চাই তবে আমি কীভাবে এই দর্শনটি জানাতে পারি যে আমি কেবল একটি ফর্ম জমা দিচ্ছি এবং অন্যটি নয় (যেমন এটি এখনও অনুরোধ। পোস্ট করুন তবে আমি কেবল যে ফর্মটি জমা দিচ্ছি তা প্রক্রিয়া করতে চাই ঘটেছিলো)?


এটি সেই উত্তরের ভিত্তিতে সমাধান যেখানে প্রত্যাশিত ফ্রেজ এবং নিষিদ্ধফ্রেজ হ'ল বিভিন্ন ফর্মের জন্য জমা দেওয়া বোতামগুলির নাম এবং প্রত্যাশিত ফ্রেসফর্ম এবং নিষিদ্ধফ্রেসফর্মগুলি ফর্ম।

if request.method == 'POST':
    if 'bannedphrase' in request.POST:
        bannedphraseform = BannedPhraseForm(request.POST, prefix='banned')
        if bannedphraseform.is_valid():
            bannedphraseform.save()
        expectedphraseform = ExpectedPhraseForm(prefix='expected')
    elif 'expectedphrase' in request.POST:
        expectedphraseform = ExpectedPhraseForm(request.POST, prefix='expected')
        if expectedphraseform.is_valid():
            expectedphraseform.save() 
        bannedphraseform = BannedPhraseForm(prefix='banned')
else:
    bannedphraseform = BannedPhraseForm(prefix='banned')
    expectedphraseform = ExpectedPhraseForm(prefix='expected')

2
আপনার সমাধানে কোনও যৌক্তিক ত্রুটি নেই? আপনি যদি 'নিষিদ্ধফ্রেজ' পোস্ট করেন তবে প্রত্যাশিত ফ্রেসফর্মটি জনবহুল হবে না।
Ztyx

2
এটি একসাথে কেবল একটি ফর্ম হ্যান্ডেল করবে, প্রশ্ন একই সাথে একাধিক ফর্মগুলি পরিচালনা করার বিষয়ে
জ্বলজ্বল করছে

উত্তর:


140

আপনার স্বল্প কিছু সু্যোগ আছে:

  1. দুটি ফর্মের জন্য ক্রিয়ায় বিভিন্ন ইউআরএল রাখুন। তারপরে দুটি ভিন্ন রূপের সাথে ডিল করার জন্য আপনার দুটি ভিন্ন ভিউ ফাংশন থাকবে।

  2. পোস্ট ডেটা থেকে জমা বোতামের মানগুলি পড়ুন। আপনি বলতে পারবেন কোন সাবমিট বাটন ক্লিক করা হয়েছিল: আমি কীভাবে একাধিক জমা বোতাম জঞ্জো ফর্ম তৈরি করতে পারি?


5
3) পোষ্ট ডেটাতে ক্ষেত্রের নামগুলি থেকে কোন ফর্ম জমা দেওয়া হয়েছে তা নির্ধারণ করুন। আপনার বাচ্চাদের সমস্ত সম্ভাব্য মান খালি না থাকার সাথে অনন্য ক্ষেত্র না থাকলে কিছু লুকানো ইনপুট অন্তর্ভুক্ত করুন।
ডেনিস ওটকিডাচ

13
৪) ফর্মটি সনাক্ত করে একটি লুকানো ক্ষেত্র যুক্ত করুন এবং আপনার দৃষ্টিতে এই ক্ষেত্রের মান চেক করুন।
সোভিয়েট

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

6
# 1 সত্যিই এখানে আপনার সেরা বাজি। আপনি লুকানো ক্ষেত্রগুলি সহ আপনার পোষ্টকে দূষিত করতে চান না এবং আপনি আপনার টেমপ্লেট এবং / অথবা ফর্মটিতে নিজের দৃষ্টিভঙ্গিটি আঁকতে চান না।
মেটিওরেইনার

5
@ মেট্যোরাইনার যদি আপনি এক নম্বর ব্যবহার করেন তবে পিতামাতার ভিউগুলিতে ফর্মগুলিতে ফিরে যাওয়ার কোনও উপায় আছে যা বার্তাগুলির কাঠামো বা কোয়েরি স্ট্রিংগুলি ব্যবহার না করে এগুলি ইনস্ট্যান্ট করে? এই উত্তর নিকটতম মনে হয়, কিন্তু এখানে এটি এখনও মাত্র এক উভয় ফর্ম হ্যান্ডলিং ভিউ এর stackoverflow.com/a/21271659/2532070
YPCrumble

45

ভবিষ্যতের রেফারেন্সের জন্য একটি পদ্ধতি হ'ল কিছু। নিষিদ্ধফ্রেসফর্মটি প্রথম ফর্ম এবং প্রত্যাশিত ফ্রেসফর্মটি দ্বিতীয়। প্রথমটিকে আঘাত করা হলে, দ্বিতীয়টি এড়িয়ে যায় (যা এই ক্ষেত্রে যুক্তিসঙ্গত অনুমান):

if request.method == 'POST':
    bannedphraseform = BannedPhraseForm(request.POST, prefix='banned')
    if bannedphraseform.is_valid():
        bannedphraseform.save()
else:
    bannedphraseform = BannedPhraseForm(prefix='banned')

if request.method == 'POST' and not bannedphraseform.is_valid():
    expectedphraseform = ExpectedPhraseForm(request.POST, prefix='expected')
    bannedphraseform = BannedPhraseForm(prefix='banned')
    if expectedphraseform.is_valid():
        expectedphraseform.save()

else:
    expectedphraseform = ExpectedPhraseForm(prefix='expected')

7
উপসর্গ = ব্যবহার করা প্রকৃতপক্ষে 'সঠিক উপায়'
ধনী

উপসর্গ-কাওয়ার্গ কাজটি করেছেন, দুর্দান্ত!
স্টিফান হোয়ের

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

তিন ধরণের ক্ষেত্রে এই প্যাটার্নটি প্রসারিত করা কি আকিদা হবে না? মত, প্রথম ফর্মটি থেকে is_ अवैध () যাচাই করে, তারপরে প্রথম দুটি, ইত্যাদি ... সম্ভবত একটি সামঞ্জস্যপূর্ণ ফর্ম পাওয়া গেলে handled = Falseআপডেট হয়ে Trueযায়?
বিনকি

14

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

জ্যাঙ্গোর জেনেরিক ভিউগুলি ব্যবহার করে একই টার্গেট অ্যাকশন ইউআরএল সহ একাধিক ফর্মগুলি পরিচালনা করার এক উপায় হ'ল নীচে প্রদর্শিত হিসাবে 'টেমপ্লেটভিউ' প্রসারিত করা; আমি এই পদ্ধতির প্রায়শই যথেষ্ট ব্যবহার করি যে আমি এটিকে একটি Elpipse IDE টেমপ্লেটে পরিণত করেছি।

class NegotiationGroupMultifacetedView(TemplateView):
    ### TemplateResponseMixin
    template_name = 'offers/offer_detail.html'

    ### ContextMixin 
    def get_context_data(self, **kwargs):
        """ Adds extra content to our template """
        context = super(NegotiationGroupDetailView, self).get_context_data(**kwargs)

        ...

        context['negotiation_bid_form'] = NegotiationBidForm(
            prefix='NegotiationBidForm', 
            ...
            # Multiple 'submit' button paths should be handled in form's .save()/clean()
            data = self.request.POST if bool(set(['NegotiationBidForm-submit-counter-bid',
                                              'NegotiationBidForm-submit-approve-bid',
                                              'NegotiationBidForm-submit-decline-further-bids']).intersection(
                                                    self.request.POST)) else None,
            )
        context['offer_attachment_form'] = NegotiationAttachmentForm(
            prefix='NegotiationAttachment', 
            ...
            data = self.request.POST if 'NegotiationAttachment-submit' in self.request.POST else None,
            files = self.request.FILES if 'NegotiationAttachment-submit' in self.request.POST else None
            )
        context['offer_contact_form'] = NegotiationContactForm()
        return context

    ### NegotiationGroupDetailView 
    def post(self, request, *args, **kwargs):
        context = self.get_context_data(**kwargs)

        if context['negotiation_bid_form'].is_valid():
            instance = context['negotiation_bid_form'].save()
            messages.success(request, 'Your offer bid #{0} has been submitted.'.format(instance.pk))
        elif context['offer_attachment_form'].is_valid():
            instance = context['offer_attachment_form'].save()
            messages.success(request, 'Your offer attachment #{0} has been submitted.'.format(instance.pk))
                # advise of any errors

        else 
            messages.error('Error(s) encountered during form processing, please review below and re-submit')

        return self.render_to_response(context)

এইচটিএমএল টেমপ্লেটটি নিম্নলিখিত প্রভাবটিতে রয়েছে:

...

<form id='offer_negotiation_form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
    {% csrf_token %}
    {{ negotiation_bid_form.as_p }}
    ...
    <input type="submit" name="{{ negotiation_bid_form.prefix }}-submit-counter-bid" 
    title="Submit a counter bid"
    value="Counter Bid" />
</form>

...

<form id='offer-attachment-form' class="content-form" action='./' enctype="multipart/form-data" method="post" accept-charset="utf-8">
    {% csrf_token %}
    {{ offer_attachment_form.as_p }}

    <input name="{{ offer_attachment_form.prefix }}-submit" type="submit" value="Submit" />
</form>

...

1
আমি এই একই সমস্যার সাথে লড়াই করছি এবং প্রতিটি পোস্টকে আলাদা ফর্ম দৃষ্টিতে প্রক্রিয়া করার একটি উপায় সন্ধান করার চেষ্টা করছিলাম এবং তারপরে একটি সাধারণ টেম্পলেট ভিউতে পুনর্নির্দেশ করব। বিষয়টি হ'ল টেমপ্লেটটি দর্শন প্রাপ্তির জন্য দায়বদ্ধ করা এবং সংরক্ষণের জন্য ফর্ম দর্শন। বৈধতা যদিও একটি সমস্যা। সেশনে ফর্মগুলি সংরক্ষণ করা আমার মন অতিক্রম করেছে ... এখনও একটি পরিষ্কার সমাধানের সন্ধান করছে।
ড্যানিয়েল বার্নার্ডিনী

14

আমার একাধিক ফর্মের প্রয়োজন ছিল যা একই পৃষ্ঠায় স্বতন্ত্রভাবে বৈধ হয়ে আছে। আমি যে মূল ধারণাগুলি অনুপস্থিত ছিল সেগুলি হ'ল 1) জমা বোতামের নামের জন্য ফর্ম উপসর্গ এবং 2) আনবাউন্ডেড ফর্মটি বৈধতাটিকে ট্রিগার করে না। যদি এটি অন্য কাউকে সহায়তা করে তবে @ অ্যাডাম-নেলসন এবং @ ড্যানিয়েল-সোকলোভস্কির উত্তরগুলির উপর ভিত্তি করে টেম্পলেটভিউ ব্যবহার করে টেম্পলেটভিউ ব্যবহার করে আমার দুটি রূপের এফর্ম এবং বিএফর্মের সরলীকৃত উদাহরণ এখানে রয়েছে ( https://stackoverflow.com/a/17303480 / 2680349 ):

# views.py
def _get_form(request, formcls, prefix):
    data = request.POST if prefix in request.POST else None
    return formcls(data, prefix=prefix)

class MyView(TemplateView):
    template_name = 'mytemplate.html'

    def get(self, request, *args, **kwargs):
        return self.render_to_response({'aform': AForm(prefix='aform_pre'), 'bform': BForm(prefix='bform_pre')})

    def post(self, request, *args, **kwargs):
        aform = _get_form(request, AForm, 'aform_pre')
        bform = _get_form(request, BForm, 'bform_pre')
        if aform.is_bound and aform.is_valid():
            # Process aform and render response
        elif bform.is_bound and bform.is_valid():
            # Process bform and render response
        return self.render_to_response({'aform': aform, 'bform': bform})

# mytemplate.html
<form action="" method="post">
    {% csrf_token %}
    {{ aform.as_p }}
    <input type="submit" name="{{aform.prefix}}" value="Submit" />
    {{ bform.as_p }}
    <input type="submit" name="{{bform.prefix}}" value="Submit" />
</form>

আমি মনে করি এটি আসলে একটি পরিষ্কার সমাধান। ধন্যবাদ।
ছানতাল

আমি এই সমাধানটি সত্যিই পছন্দ করি। একটি প্রশ্ন: _গেট_ফর্ম () মাইভিউ ক্লাসের পদ্ধতি না হওয়ার কোনও কারণ আছে কি?
এয়ারট্রাইক

1
@ অ্যান্ড্রেটেরা এটি অবশ্যই হয়ে থাকতে পারে, যদিও আপনি সম্ভবত এটি জেনেরিক শ্রেণিতে রাখতে চান যা টেম্পলেটভিউ থেকে উত্তরাধিকার সূত্রে আসে যাতে আপনি এটি অন্য মতামতে পুনরায় ব্যবহার করতে পারেন।
ybendana

1
এটি একটি দুর্দান্ত সমাধান। আমার __get_for এর একটি লাইন পরিবর্তন করা দরকার যাতে এটি কাজ করে: data = request.POST if prefix in next(iter(request.POST.keys())) else None অন্যথায় inকাজ করে না।
লারাপসোডিয়া

এর জন্য একটি একক <ফর্ম> ট্যাগ ব্যবহার করার অর্থ বিশ্বব্যাপী প্রয়োজনীয় ক্ষেত্রগুলি প্রয়োজন যখন সেগুলি জমা দেওয়ার বোতামটি ক্লিক করা হয়েছিল তার উপর নির্ভর করে প্রতি ফর্ম হওয়া উচিত। দুটি <for>> ট্যাগগুলিতে বিভক্ত (একই ক্রিয়া সহ) কাজ করে।
ফ্ল্যাশ

3

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

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

<form method="post" id="formOne">
    {% csrf_token %}
   <input type="hidden" name="form_type" value="formOne">

    .....
</form>

.....

<form method="post" id="formTwo">
    {% csrf_token %}
    <input type="hidden" name="form_type" value="formTwo">
   ....
</form>

views.py

def handlemultipleforms(request, template="handle/multiple_forms.html"):
    """
    Handle Multiple <form></form> elements
    """
    if request.method == 'POST':
        if request.POST.get("form_type") == 'formOne':
            #Handle Elements from first Form
        elif request.POST.get("form_type") == 'formTwo':
            #Handle Elements from second Form

আমি মনে করি এটি একটি ভাল এবং সহজ উপায়
শেডরাক

2

এটি কিছুটা দেরিতে হলেও এটি আমি খুঁজে পেয়েছি সেরা সমাধান। আপনি ফর্মের নাম এবং এটির শ্রেণীর জন্য একটি বর্ণনামূলক অভিধান তৈরি করেন, ফর্মটি সনাক্ত করতে আপনাকে একটি বৈশিষ্ট্যও যুক্ত করতে হবে, এবং আপনার দৃষ্টিতে আপনাকে এটির সাথে একটি লুকানো ক্ষেত্র হিসাবে যুক্ত করতে হবে form.formlabel

# form holder
form_holder = {
    'majeur': {
        'class': FormClass1,
    },
    'majsoft': {
        'class': FormClass2,
    },
    'tiers1': {
        'class': FormClass3,
    },
    'tiers2': {
        'class': FormClass4,
    },
    'tiers3': {
        'class': FormClass5,
    },
    'tiers4': {
        'class': FormClass6,
    },
}

for key in form_holder.keys():
    # If the key is the same as the formlabel, we should use the posted data
    if request.POST.get('formlabel', None) == key:
        # Get the form and initate it with the sent data
        form = form_holder.get(key).get('class')(
            data=request.POST
        )

        # Validate the form
        if form.is_valid():
            # Correct data entries
            messages.info(request, _(u"Configuration validée."))

            if form.save():
                # Save succeeded
                messages.success(
                    request,
                    _(u"Données enregistrées avec succès.")
                )
            else:
                # Save failed
                messages.warning(
                    request,
                    _(u"Un problème est survenu pendant l'enregistrement "
                      u"des données, merci de réessayer plus tard.")
                )
        else:
            # Form is not valid, show feedback to the user
            messages.error(
                request,
                _(u"Merci de corriger les erreurs suivantes.")
            )
    else:
        # Just initiate the form without data
        form = form_holder.get(key).get('class')(key)()

    # Add the attribute for the name
    setattr(form, 'formlabel', key)

    # Append it to the tempalte variable that will hold all the forms
    forms.append(form)

আমি আশা করি এটি ভবিষ্যতে সহায়তা করবে।


2

আপনি যদি ক্লাস-ভিত্তিক মতামত এবং বিভিন্ন 'অ্যাকশন' অ্যাটর্সগুলির সাথে যোগাযোগ করতে চান তবে আমি বোঝাতে চাইছি

দুটি ফর্মের জন্য ক্রিয়ায় বিভিন্ন ইউআরএল রাখুন। তারপরে দুটি ভিন্ন রূপের সাথে ডিল করার জন্য আপনার দুটি ভিন্ন ভিউ ফাংশন থাকবে।

আপনি ওভারলোডেড ব্যবহার করে সহজেই বিভিন্ন ফর্ম থেকে ত্রুটিগুলি পরিচালনা করতে পারেন get_context_data পদ্ধতিটি :

views.py:

class LoginView(FormView):
    form_class = AuthFormEdited
    success_url = '/'
    template_name = 'main/index.html'

    def dispatch(self, request, *args, **kwargs):
        return super(LoginView, self).dispatch(request, *args, **kwargs)

    ....

    def get_context_data(self, **kwargs):
        context = super(LoginView, self).get_context_data(**kwargs)
        context['login_view_in_action'] = True
        return context

class SignInView(FormView):
    form_class = SignInForm
    success_url = '/'
    template_name = 'main/index.html'

    def dispatch(self, request, *args, **kwargs):
        return super(SignInView, self).dispatch(request, *args, **kwargs)

    .....

    def get_context_data(self, **kwargs):
        context = super(SignInView, self).get_context_data(**kwargs)
        context['login_view_in_action'] = False
        return context

টেমপ্লেট:

<div class="login-form">
<form action="/login/" method="post" role="form">
    {% csrf_token %}
    {% if login_view_in_action %}
        {% for e in form.non_field_errors %}
            <div class="alert alert-danger alert-dismissable">
                {{ e }}
                <a class="panel-close close" data-dismiss="alert">×</a>
            </div>
        {% endfor %}
    {% endif %}
    .....
    </form>
</div>

<div class="signin-form">
<form action="/registration/" method="post" role="form">
    {% csrf_token %}
    {% if not login_view_in_action %}
        {% for e in form.non_field_errors %}
            <div class="alert alert-danger alert-dismissable">
                {{ e }}
                <a class="panel-close close" data-dismiss="alert">×</a>
            </div>
        {% endfor %}
    {% endif %}
   ....
  </form>
</div>

2

দেখুন:

class AddProductView(generic.TemplateView):
template_name = 'manager/add_product.html'

    def get(self, request, *args, **kwargs):
    form = ProductForm(self.request.GET or None, prefix="sch")
    sub_form = ImageForm(self.request.GET or None, prefix="loc")
    context = super(AddProductView, self).get_context_data(**kwargs)
    context['form'] = form
    context['sub_form'] = sub_form
    return self.render_to_response(context)

def post(self, request, *args, **kwargs):
    form = ProductForm(request.POST,  prefix="sch")
    sub_form = ImageForm(request.POST, prefix="loc")
    ...

টেমপ্লেট:

{% block container %}
<div class="container">
    <br/>
    <form action="{% url 'manager:add_product' %}" method="post">
        {% csrf_token %}
        {{ form.as_p }}
        {{ sub_form.as_p }}
        <p>
            <button type="submit">Submit</button>
        </p>
    </form>
</div>
{% endblock %}

4
আপনি দয়া করে আপনার উত্তর ব্যাখ্যা করতে পারেন? এটি অন্যকে একটি সিমিলার সমস্যায় সহায়তা করবে এবং আপনার বা প্রশ্নকারীদের কোডটি ডিবাগ করতে সহায়তা করবে ...
creyD

0

এখানে উপরোক্ত পরিচালনা করার সহজ উপায়।

এইচটিএমএল টেমপ্লেটে আমরা পোস্ট রেখেছি

<form action="/useradd/addnewroute/" method="post" id="login-form">{% csrf_token %}

<!-- add details of form here-->
<form>
<form action="/useradd/addarea/" method="post" id="login-form">{% csrf_token %}

<!-- add details of form here-->

<form>

দেখুন

   def addnewroute(request):
      if request.method == "POST":
         # do something



  def addarea(request):
      if request.method == "POST":
         # do something

ইউআরএলে প্রয়োজনীয় তথ্য দিন

urlpatterns = patterns('',
url(r'^addnewroute/$', views.addnewroute, name='addnewroute'),
url(r'^addarea/', include('usermodules.urls')),
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.