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

السؤال

نشر

انا اريد ان اعرف كيف يتم اضافة المنتجات الى العربة او فلترة المنتجات حسب التصنيف دون اعادة تحميل الصفحةانا اعلم انه يجب ان استعمل الـ json ولكن لا اعرف كيف اربط موقعي معه بحيث لا اعلم ماذا اكتب في  viewsو الـ template,urls وشكراً

Recommended Posts

  • 0
نشر

تحتاج لاستخدام جافاسكريبت وتحديدا التقنية المعروفة باسم Ajax او استخدام Fetch API الحديثة. الفكرة تعتمد على ارسال طلب الى رابط معين في Django بصيغة JSON ثم استقبال الرد وتحديث واجهة المستخدم برمجيا. في ملف urls.py يجب عليك انشاء مسار مخصص لهذا الغرض كما يلي:

from django.urls import path

from . import views

urlpatterns = [

    path('filter-products/', views.filter_products, name='filter_products'),

]

وفي ملف views.py ستقوم بكتابة دالة تستقبل المعاملات المرسلة مثل رقم التصنيف، ثم تعيد البيانات باستخدام JsonResponse. اليك مثال بسيط:

from django.http import JsonResponse

from .models import Product

def filter_products(request):

    category_id = request.GET.get('category_id')

    products = Product.objects.filter(category_id=category_id).values('id', 'name', 'price')

    return JsonResponse({'products': list(products)})

بعد ذلك في صفحة القالب template ستحتاج الى كتابة كود جافاسكريبت يرسل الطلب عند النقر على زر معين او اختيار تصنيف، ثم يستلم البيانات ويقوم بتحديث محتوى الصفحة يدويا. الكود التالي يوضح كيفية تنفيذ ذلك باستخدام Fetch API:

function loadProducts(categoryId) {

    fetch('/filter-products/?category_id=' + categoryId)

    .then(response => response.json())

    .then(data => {

        const container = document.getElementById('products-container');

        container.innerHTML = '';

        data.products.forEach(product => {

            container.innerHTML += '<div>' + product.name + '</div>';

        });

    });

}

بهذه الطريقة سيتم تحديث قائمة المنتجات في المتصفح فورا دون الحاجة لعمل Refresh للصفحة، ويمكنك اتباع نفس المنطق تماما لاضافة المنتجات الى سلة التسوق مع تغيير العملية في views.py لتعديل الجلسة او قاعدة البيانات بدلا من مجرد جلب البيانات.

  • 0
نشر

بالضغط على زر إضافة للسلة، المتصفح يخبر السيرفر أعد بناء الصفحة كاملة بكل ما فيها من قوائم، ألوان، خطوط، صور، وضع الرقم الجديد في السلة وأرسل لي الصفحة من الصفر، وذلك ما يسبب وميض الشاشة وإعادة التحميل.

بينما الطريقة الحديثة تعمل جافاسكريبت كوسيط بين المتصفح والسيرفر، عندما تضغط على الزر يتم إرسال طلب للسيرفر في الخفاء، يسأله فقط عن المعلومة الجديدة (كم أصبح رقم السلة؟)، ثم يعود ويغير ذلك الرقم فقط على الشاشة أمام عينيك.

القالب والواجهة بعد أن يأتيه الرد من السيرفر، يستقبل القيمة الجديدة ويضعها مباشرة في العنصر المخصص لها مثلاً يغير نص العداد من 0 إلى 1، أو يمسح المنتجات القديمة ويرسم الجديدة.

ملف الروابط URLs هو و العنوان المخصص لتبادل البيانات، وبها تنشئ رابطاً ليس غرضه فتح صفحة للمستخدم، بل هو نقطة نهاية مخصصة لتتحدث معها JavaScript فقط، مثل: /api/add-to-cart/ أو /api/filter/.

ويتم معالجة البيانات في Views حيث تستقبل الطلب القادم من الرابط ومعه البيانات (رقم المنتج أو اسم التصنيف).

بينما الـ الـ JSON هو تنسيق نصي بسيط وموحد يفهمه بايثون وجافاسكريبت معاً.

بالتالي ما يحدث عند أي إضافة للسلة:

  1. أنت (المستخدم): تضغط على زر إضافة.
  2. الـ JavaScript في الصفحة: يلتقط الضغطة، يعرف أنك ضغطت على المنتج رقم 10.
  3. الـ JavaScript: يطرق باب مسار في الـ urls.py ويرسل له رقم 10.
  4. الـ views.py: يستلم رقم 10، يضيفه في قاعدة البيانات لسلة هذا المستخدم، ويرى أن مجموع السلة الآن أصبح 2.
  5. الـ views.py: يكتب رسالة JSON: "العملية تمت، والإجمالي الآن 2" ويرسلها.
  6. الـ JavaScript في الصفحة: يستلم الرسالة، يقرأ رقم 2، ويذهب للعنصر <span id="cart"> ويغير ما بداخله ليصبح 2.
  • 0
نشر

عشان تتجنب إعادة تحميل الصفحة، تحتاج تستخدم AJAX (عبر fetch في JavaScript). بدل ما الفورم يرسل طلب عادي يعيد تحميل الصفحة كاملة، الـ JS يرسل طلب في الخلفية، السيرفر يرد بـ JSON، وأنت تحدّث الصفحة بالـ JS فقط.

في ملف urls.py أضف مسار (endpoint) خاص لكل عملية

from django.urls import path
from . import views

urlpatterns = [
    path('add-to-cart/<int:product_id>/', views.add_to_cart, name='add_to_cart'),
    path('filter-products/', views.filter_products, name='filter_products'),
]

في ملف views.py إضافة منتج للعربة (يرجع JSON)

from django.http import JsonResponse
from django.shortcuts import get_object_or_404
from .models import Product

def add_to_cart(request, product_id):
    if request.method == 'POST':
        product = get_object_or_404(Product, id=product_id)
        cart = request.session.get('cart', {})
        
        product_id_str = str(product_id)
        cart[product_id_str] = cart.get(product_id_str, 0) + 1
        request.session['cart'] = cart
        
        return JsonResponse({
            'success': True,
            'message': f'تمت إضافة {product.name} إلى العربة',
            'cart_count': sum(cart.values())
        })
    return JsonResponse({'success': False}, status=400)

فلترة المنتجات حسب التصنيف 

from django.template.loader import render_to_string

def filter_products(request):
    category_id = request.GET.get('category')
    
    if category_id:
        products = Product.objects.filter(category_id=category_id)
    else:
        products = Product.objects.all()
    
    html = render_to_string('products/product_list_partial.html', {'products': products})
    return JsonResponse({'html': html})

بدل ما ترجع بيانات خام وتبني HTML بالـ JS، تخلي Django يبني قطعة HTML جاهزة  وترجعها ضمن JSON، وأنت فقط تستبدل محتوى الـ div بها. هذا أسهل بكثير من بناء HTML بالجافاسكريبت.

<!-- زر إضافة للعربة -->
<button class="add-to-cart-btn" data-product-id="{{ product.id }}">
    أضف إلى العربة
</button>

<!-- فلتر التصنيفات -->
<select id="category-filter">
    <option value="">الكل</option>
    {% for cat in categories %}
        <option value="{{ cat.id }}">{{ cat.name }}</option>
    {% endfor %}
</select>

<div id="product-list">
    {% include 'products/product_list_partial.html' %}
</div>

<script>
function getCookie(name) {
    let value = null;
    document.cookie.split(';').forEach(cookie => {
        const [k, v] = cookie.trim().split('=');
        if (k === name) value = v;
    });
    return value;
}
const csrftoken = getCookie('csrftoken');

// إضافة للعربة
document.querySelectorAll('.add-to-cart-btn').forEach(btn => {
    btn.addEventListener('click', function () {
        const productId = this.dataset.productId;
        fetch(`/add-to-cart/${productId}/`, {
            method: 'POST',
            headers: {
                'X-CSRFToken': csrftoken,
                'Content-Type': 'application/json',
            }
        })
        .then(res => res.json())
        .then(data => {
            if (data.success) {
                alert(data.message);
                document.getElementById('cart-count').textContent = data.cart_count;
            }
        });
    });
});

// فلترة المنتجات
document.getElementById('category-filter').addEventListener('change', function () {
    const categoryId = this.value;
    fetch(`/filter-products/?category=${categoryId}`)
        .then(res => res.json())
        .then(data => {
            document.getElementById('product-list').innerHTML = data.html;
        });
});
</script>

CSRF token أي طلب POST لازم يرسل X-CSRFToken في الهيدر، وإلا Django يرفضه (403).

JsonResponse هو اللي يخلي السيرفر يرجع JSON بدل صفحة HTML كاملة.

event listeners بعد التحديث إذا أضفت أزرار جديدة عبر innerHTML (مثلاً بعد الفلترة)، الـ event listeners القديمة ما تشتغل عليها تلقائياً. الحل: استخدم event delegation بدل ربط كل زر لحاله 

document.getElementById('product-list').addEventListener('click', function (e) {
    if (e.target.classList.contains('add-to-cart-btn')) {
        const productId = e.target.dataset.productId;
        // نفس كود fetch
    }
});

 

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

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

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

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   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.

  • إعلانات

  • تابعنا على



×
×
  • أضف...