একা একা জাঙ্গো মডেলফর্মের একাধিক মডেল?


99

ModelFormজাঙ্গোতে একক একাধিক মডেল অন্তর্ভুক্ত করা কি সম্ভব ? আমি একটি প্রোফাইল সম্পাদনা ফর্ম তৈরি করার চেষ্টা করছি। সুতরাং আমি ব্যবহারকারী মডেল এবং ব্যবহারকারীর প্রোফাইল মডেল থেকে কিছু ক্ষেত্র অন্তর্ভুক্ত করা প্রয়োজন । বর্তমানে আমি এই জাতীয় 2 টি ফর্ম ব্যবহার করছি

class UserEditForm(ModelForm):

    class Meta:
        model = User
        fields = ("first_name", "last_name")

class UserProfileForm(ModelForm):

    class Meta:
        model = UserProfile
        fields = ("middle_name", "home_phone", "work_phone", "cell_phone")

এগুলিকে এক রূপে একীভূত করার কোনও উপায় আছে বা আমার কি কেবল একটি ফর্ম তৈরি করতে হবে এবং নিজেকে ডিবি লোডিং এবং সংরক্ষণ করতে হবে?


উত্তর:


93

আপনি কেবলমাত্র <form>এইচটিএমএল উপাদানের টেম্পলেটটিতে উভয় ফর্ম প্রদর্শন করতে পারেন । তারপরে শুধু ভিউতে আলাদাভাবে প্রক্রিয়া করুন process আপনি এখনও form.save()ডিবি লোডিং এবং নিজেকে সংরক্ষণের প্রক্রিয়া করতে পারবেন না এবং ব্যবহার করতে সক্ষম হবেন ।

এই ক্ষেত্রে আপনার প্রয়োজন হবে না, তবে আপনি যদি একই ক্ষেত্রের নামগুলি সহ ফর্মগুলি ব্যবহার করতে যাচ্ছেন তবে prefixজাঙ্গো ফর্মগুলির জন্য কোয়ার্গে সন্ধান করুন । (আমি এটি সম্পর্কে একটি প্রশ্নের উত্তর এখানে )।


এটি পরামর্শের একটি ভাল অংশ, তবে এমন কিছু ক্ষেত্রে রয়েছে যা এটি প্রযোজ্য নয়, যেমন। একটি ফর্মসেটের জন্য কাস্টম মডেল ফর্ম।
ওয়াটওয়ার

8
শ্রেণিভিত্তিক দৃষ্টিভঙ্গিকে একাধিক ফর্ম এবং টেমপ্লেটকে একই <form>উপাদানের সাথে সংযুক্ত করে দেখানোর পক্ষে সক্ষম করার সোজা উপায় কী হবে ?
jozxyqk

4
কিন্তু কিভাবে? সাধারণত একজনকে FormViewকেবল এটির জন্য একটি একক form_classবরাদ্দ করা হয়।
এরিকবওয়ার্ক

@ এরিকবওয়ার্ক এই ক্ষেত্রে আপনার কোনও ফর্মভিউ ব্যবহার করা উচিত নয়। কেবল সাবক্লাস TemplateViewএবং ফর্মভিউয়ের মতো একই যুক্তিটি বাস্তবায়ন করুন তবে একাধিক ফর্ম সহ with
moppag

10

আপনি কোডের এই টুকরোটি ব্যবহার করার চেষ্টা করতে পারেন:

class CombinedFormBase(forms.Form):
    form_classes = []

    def __init__(self, *args, **kwargs):
        super(CombinedFormBase, self).__init__(*args, **kwargs)
        for f in self.form_classes:
            name = f.__name__.lower()
            setattr(self, name, f(*args, **kwargs))
            form = getattr(self, name)
            self.fields.update(form.fields)
            self.initial.update(form.initial)

    def is_valid(self):
        isValid = True
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            if not form.is_valid():
                isValid = False
        # is_valid will trigger clean method
        # so it should be called after all other forms is_valid are called
        # otherwise clean_data will be empty
        if not super(CombinedFormBase, self).is_valid() :
            isValid = False
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            self.errors.update(form.errors)
        return isValid

    def clean(self):
        cleaned_data = super(CombinedFormBase, self).clean()
        for f in self.form_classes:
            name = f.__name__.lower()
            form = getattr(self, name)
            cleaned_data.update(form.cleaned_data)
        return cleaned_data

ব্যবহারের উদাহরণ:

class ConsumerRegistrationForm(CombinedFormBase):
    form_classes = [RegistrationForm, ConsumerProfileForm]

class RegisterView(FormView):
    template_name = "register.html"
    form_class = ConsumerRegistrationForm

    def form_valid(self, form):
        # some actions...
        return redirect(self.get_success_url())

দেখে মনে হচ্ছে কিছু স্পষ্ট চেকের কারণে অ্যাডমিনে এটি ব্যবহার করা যাবে না:admin.E016) The value of 'form' must inherit from 'BaseModelForm'.
নটহাগো

আমি কীভাবে এটি ব্যবহার করতে পারি UpdateView?
পাভেল শ্লেপনেভ

4

আমার এবং আমার দুজনেরই সমস্যা ছিল যে একজন কেবল একটি জেনেরিক শ্রেণিভিত্তিক দৃশ্যে একটি মডেলকে অন্তর্ভুক্ত করতে পারে। আমি মিয়াওর মতো এটির কাছে যাওয়ার একই ধরণের উপায় খুঁজে পেয়েছি তবে আরও মডুলার।

আমি একটি মিক্সিন লিখেছি যাতে আপনি সমস্ত জেনেরিক ক্লাস ভিত্তিক ভিউ ব্যবহার করতে পারেন। মডেল, ক্ষেত্রগুলি এবং এখন চাইল্ড-মডেল এবং চাইল্ড_ফিল্ড সংজ্ঞায়িত করুন - এবং তারপরে আপনি উভয় মডেলের ক্ষেত্রগুলি জ্যাচের বর্ণনা মতো একটি ট্যাগে মোড়ানো করতে পারেন।

class ChildModelFormMixin: 
    ''' extends ModelFormMixin with the ability to include ChildModelForm '''
    child_model = ""
    child_fields = ()
    child_form_class = None

    def get_child_model(self):
        return self.child_model

    def get_child_fields(self):
        return self.child_fields

    def get_child_form(self):
        if not self.child_form_class:
            self.child_form_class = model_forms.modelform_factory(self.get_child_model(), fields=self.get_child_fields())
        return self.child_form_class(**self.get_form_kwargs())

    def get_context_data(self, **kwargs):
        if 'child_form' not in kwargs:
            kwargs['child_form'] = self.get_child_form()
        return super().get_context_data(**kwargs)

    def post(self, request, *args, **kwargs):
        form = self.get_form()
        child_form = self.get_child_form()

        # check if both forms are valid
        form_valid = form.is_valid()
        child_form_valid = child_form.is_valid()

        if form_valid and child_form_valid:
            return self.form_valid(form, child_form)
        else:
            return self.form_invalid(form)

    def form_valid(self, form, child_form):
        self.object = form.save()
        save_child_form = child_form.save(commit=False)
        save_child_form.course_key = self.object
        save_child_form.save()

        return HttpResponseRedirect(self.get_success_url())

ব্যবহারের উদাহরণ:

class ConsumerRegistrationUpdateView(UpdateView):
    model = Registration
    fields = ('firstname', 'lastname',)
    child_model = ConsumerProfile
    child_fields = ('payment_token', 'cart',)

বা মডেলফর্মক্লাস সহ:

class ConsumerRegistrationUpdateView(UpdateView):
    model = Registration
    fields = ('firstname', 'lastname',)
    child_model = ConsumerProfile
    child_form_class = ConsumerProfileForm

সম্পন্ন. আশা করি যে কাউকে সাহায্য করবে


এই save_child_form.course_key = self.object, কি .course_key?
অ্যাডাম স্টারহ

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

চাইল্ড ফর্মটি কেন জনবহুল হয় না এই বিষয়টি হ'ল get_child_form পদ্ধতিতে, এটি কল করে return self.child_form_class(**self.get_form_kwargs())কিন্তু এটিতে ভুল মডেল উদাহরণটি পাওয়া যায় kwargs['instance'], যেমন উদাহরণস্বরূপ মূল মডেল নয় শিশু মডেল। ঠিক করার জন্য আপনাকে প্রথমে কাওয়ারগুলি একটি ভেরিয়েবলে সংরক্ষণ করতে হবে kwargs = self.get_form_kwargs()তারপরে kwargs['initial']কল করার আগে সঠিক মডেল উদাহরণ সহ আপডেট করুন return self.child_form_class(**kwargs)। আমার ক্ষেত্রে এটি ছিল kwargs['instance'] = kwargs['instance'].profileযদি এটি বোধগম্য হয়।
robvdl

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

4

2

আপনার সম্ভবত ইনলাইন ফর্মसेटগুলি একবার দেখা উচিত । যখন আপনার মডেলগুলি কোনও বিদেশী কী দ্বারা সম্পর্কিত হয় তখন ইনলাইন ফর্মসেটগুলি ব্যবহৃত হয়।


4
যখন আপনাকে অনেকগুলি সম্পর্কের সাথে কাজ করতে হয় তখন ইনলাইন ফর্মসেটগুলি ব্যবহৃত হয়। যেমন কোনও সংস্থা যেখানে আপনি কর্মচারী যুক্ত করবেন। আমি 2 টি টেবিলকে একক আকারে একত্রিত করার চেষ্টা করছি। এটি একে অপরের সম্পর্ক।
জেসন ওয়েব 14

একটি ইনলাইন ফর্মसेट ব্যবহার কাজ করবে, তবে সম্ভবত আদর্শের চেয়ে কম হবে। আপনি এমন একটি মডেলও তৈরি করতে পারেন যা আপনার জন্য সম্পর্ক পরিচালনা করে এবং তারপরে একটি ফর্ম ব্যবহার করে। স্ট্যাকওভারফ্লো / প্রশ্নগুলি / 2770810/… হিসাবে প্রস্তাবিত 2 ফর্মগুলির সাথে একটিমাত্র পৃষ্ঠা থাকা কার্যকর হবে।
জন পারসিভাল হ্যাকওয়ার্থ

2

অনুরূপ সমস্যার জন্য আপনি আমার উত্তর এখানে পরীক্ষা করতে পারেন ।

এটি কীভাবে নিবন্ধকরণ এবং ব্যবহারকারীর প্রোফাইলকে এক ফর্মের সাথে সংযুক্ত করা যায় সে সম্পর্কে আলোচনা করে তবে এটি যে কোনও মডেলফর্ম সংমিশ্রণে সাধারণীকরণ করা যায়।


0

আমি ব্যবহৃত জ্যাঙ্গো betterforms এর বহুরূপ এবং MultiModelForm আমার প্রকল্পে। কোডটি উন্নত করা যেতে পারে, যদিও। উদাহরণস্বরূপ, এটি django.six এর উপর নির্ভরশীল, যা ৩. + দ্বারা সমর্থিত নয়, তবে এগুলি সমস্ত সহজেই স্থির করা যায়

এই প্রশ্নটি বেশ কয়েকবার স্ট্যাকওভারফ্লোতে উপস্থিত হয়েছে , সুতরাং আমি মনে করি এটির মোকাবিলার একটি প্রমিত মানের উপায় খুঁজে বের করার সময় এসেছে।

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