اذهب إلى المحتوى

السؤال

نشر

لدي نموذج form ويحتوي على زر "add new field" وأريد عند الضغط على هذا  الزر أن يتم إضافة حقل جديد إلى النموذج ليتمكن المستخدم من إضافة المزيد من المعلومات.

هل يجب أن يتم إعادة تحديث الصفحة ليتم إضافة حقل جديد؟ وكيف أقوم بعمل مثل هذا الزر من الأساس؟

Recommended Posts

  • 1
نشر

حتى تستطيع إضافة حقل بشكل ألي و ديناميكي يجب إستخدام بعض من JS جافا سكربت سكون  الشرح على 3 خطوات أولا ما سوف تفعله في ملف templates لماذا يجب إستخدام JS في المتصفح لتعديل على elements أو عناصر HTML بدون إعادة تحميل الصفحة يجب استخدام لغة برمجة تعمل على المتصفح نفسه.

مثال على الفكرة المطلوبة
أولاً views.py

from django.contrib.auth.decorators import login_required
from django.forms.models import modelformset_factory # model form for querysets
from django.shortcuts import redirect, render, get_object_or_404

from .forms import RecipeForm, RecipeIngredientForm
from .models import Recipe, RecipeIngredient

@login_required
def recipe_update_view(request, id=None):
    obj = get_object_or_404(Recipe, id=id, user=request.user)
    form = RecipeForm(request.POST or None, instance=obj)
    # Formset = modelformset_factory(Model, form=ModelForm, extra=0)
    RecipeIngredientFormset = modelformset_factory(RecipeIngredient, form=RecipeIngredientForm, extra=0)
    qs = obj.recipeingredient_set.all() # []
    formset = RecipeIngredientFormset(request.POST or None, queryset=qs)
    context = {
        "form": form,
        "formset": formset,
        "object": obj
    }
    if all([form.is_valid(), formset.is_valid()]):
        parent = form.save(commit=False)
        parent.save()
        # formset.save()
        for form in formset:
            child = form.save(commit=False)
            child.recipe = parent
            child.save()
        context['message'] = 'Data saved.'
    return render(request, "recipes/create-update.html", context)  

ثانياً: recipes/create-update.html: templates

أولاً جزء HTML

  {% if formset %}
        <h3>Ingredients</h3>
        {{ formset.management_form }}
        <div id='ingredient-form-list'>
            {% for form in formset %}
                    <div class='ingredient-form'>
                        {{ form.as_p }}
                    </div>
            {% endfor %}
        </div>

        <div id='empty-form' class='hidden'>{{ formset.empty_form.as_p }}</div>
        <button id='add-more' type='button'>Add more</button>
        {% endif %}
        <button style='margin-top:10px;' type='submit' >Save</button>
    </form>
</div>

والأن مع جزء JS وسيكون في نفس ملف HTML في النهاية.

<script>
    
    const addMoreBtn = document.getElementById('add-more')
    const totalNewForms = document.getElementById('id_form-TOTAL_FORMS')
    
    addMoreBtn.addEventListener('click', add_new_form)
    function add_new_form(event) {
        if (event) {
            event.preventDefault()
        }
        const currentIngredientForms = document.getElementsByClassName('ingredient-form')
        const currentFormCount = currentIngredientForms.length // + 1
        const formCopyTarget = document.getElementById('ingredient-form-list')
        const copyEmptyFormEl = document.getElementById('empty-form').cloneNode(true)
        copyEmptyFormEl.setAttribute('class', 'ingredient-form')
        copyEmptyFormEl.setAttribute('id', `form-${currentFormCount}`)
        const regex = new RegExp('__prefix__', 'g')
        copyEmptyFormEl.innerHTML = copyEmptyFormEl.innerHTML.replace(regex, currentFormCount)
        totalNewForms.setAttribute('value', currentFormCount + 1)
        // now add new empty form element to our html form
        formCopyTarget.append(copyEmptyFormEl)
    }
    


</script>



{% endblock content %}

قد يكون ليس من السهل فهم كل شئ في كود JS لكن ما يقوم به كود SCRIPT هو نسخ أحد العناصر من HTML عند حدوث حدث click على الزر Add more

و في نفس الوقت يتم التعديل على بعض Attribute في عناصر Html الجديدة و بعد القيام بأي حفظ للبيانات سيقوم بعرض ما تم حفظه اقرأ الأكواد جيداً يستحسن أن يكون لديك فكرة عامة عن JS و أتوقع ان يكون الكود مفهوم بالنسبة لك وهذا المثال ليساعدك على حل مشكلة الخاصة بك

  • 1
نشر (معدل)

إذا كنت تقصد ال Forms الخاصة بال Models في ال Admin الخاصة بالجانغو يمكننا عمل ذلك بواسطة إنشاء   model في models.py سنسميه في حالتنا class ExtraField

ونعرف بداخله الحقل الذي تريد إضافته عند الضغط على add new field

ونربطه بعلاقة Foreign Key مع ال model المرتبط بال Form سنسميه في حالتنا Post

هكذا سيكون الكود داخل ال models.py :

class ExtraField(models.Model):
    extra_data = models.CharField(max_length=200)
    post = models.ForeignKey(Post, on_delete=models.CASCADE)

    def __str__(self):
        return self.extra_data

ملاحظة : لا تنسى عمل makemigrations and migrate

من ثم في ملف الadmin.py عند تسجيل ال model المرتبط بالForm

نقوم بتعريف class ExtraFieldTabularInline :

from .models import ExtraField, Post

class ExtraFieldTabularInline(admin.TabularInline):
    model = ExtraField

من ثم نقوم بتعريف class  ال PostAdmin

بإضافة انه سيقبل Inlines اذن سنضيف ايضاً class PostAdmin :

class PostAdmin(admin.ModelAdmin):
    inlines = [ExtraFieldTabularInline]
    class Meta:
        model = Post

من ثم تسجيل form الpost في لوحة التحكم :

admin.site.register(Post, PostAdmin)

هكذا أصبح لديك اضافة حقول كما تريد ولقد تم انشاء الزر دون تحديث الصفحة وهذا إجابة لسؤالك اذا كنت تقصد الforms  داخل لوحة التحكم الخاصة بالدجانغو 

استخدمت في المثال الجدول الmodel المرتبط بال form اسميته Post لتوضيح الفكرة ولكن لك ان تطبق الفكرة على اي جدول او model حسب ما اسميته.

كانت إجابتي بخصوص الforms داخل لوحة التحكم في دجانقو لم اتطرق الى الforms الخاص بالعرض في التمبلت تحياتي .

مثال بصري الى النتيجة :_2_1.jpg

تم التعديل في بواسطة Haroun Taha

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...