Skip to content

Commit

Permalink
Merge pull request #62 from pymasterspl/feature/implement-xml-file-fo…
Browse files Browse the repository at this point in the history
…r-ceneo
  • Loading branch information
memorisanka authored Dec 11, 2023
2 parents aa69535 + 6094c1b commit 6547e86
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 51 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
import logging

import requests
from django.core.management.base import BaseCommand
from lxml import etree

from apps.products_catalogue.models import CeneoCategory

logging.basicConfig(level=logging.INFO)


class Command(BaseCommand):
help = 'Update Ceneo categories in the database.'

def handle(self, *args, **kwargs):
self.stdout.write('Fetching Ceneo data...')
xml_data = self.fetch_ceneo_data()
root = etree.fromstring(xml_data)
categories = self.parse_categories(root)
for category in categories:
category['id'] = int(category['id'])
categories.sort(key=lambda x: x['id'])
self.import_ceneo_categories(categories)
self.stdout.write(self.style.SUCCESS('Ceneo categories data imported successfully.'))

@staticmethod
def fetch_ceneo_data():
url = 'https://developers.ceneo.pl/api/v3/kategorie'
try:
response = requests.get(url)
response.raise_for_status()
return response.content
except requests.RequestException as e:
logging.error(f"Failed to fetch data from Ceneo API: {e}")
raise

def parse_categories(self, category_elem):
categories = []
for elem in category_elem:
category = {
'id': int(elem.findtext('Id')),
'name': elem.findtext('Name'),
}
subcategories_elem = elem.find('Subcategories')
if subcategories_elem is not None:
categories.extend(self.parse_categories(subcategories_elem))
categories.append(category)
return categories

@staticmethod
def import_ceneo_categories(categories):
existing_categories = set(CeneoCategory.objects.values_list('id', flat=True))
new_categories = []

for category in categories:
if category['id'] in existing_categories:
logging.info(f"Category {category['id']} ({category['name']}) already exists.")
else:
new_categories.append(CeneoCategory(id=category['id'], name=category['name']))

if new_categories:
CeneoCategory.objects.bulk_create(new_categories, ignore_conflicts=True, update_conflicts=False)
logging.info(f"Imported {len(new_categories)} new Ceneo categories.")
else:
logging.info("No new categories to import.")
3 changes: 1 addition & 2 deletions Dshop/apps/products_catalogue/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,14 @@
from django.conf.urls.static import static
from django.urls import path

from .views import CeneoCategoriesView, CeneoProductListView, ProductListView, \
from .views import CeneoProductListView, ProductListView, \
ProductDetailView, AddToCartView, CartDetailView, CategoryListView, CategoryDetailView, DeleteOneCartItemView, \
DeleteCartItemView


urlpatterns = [
path('products_list/', ProductListView.as_view(), name='products-list'),
path('ceneo/', CeneoProductListView.as_view(), name='product-list'),
path('ceneo_categories/', CeneoCategoriesView.as_view(), name='ceneo-categories'),
path("products/<slug>-<int:id>/", ProductDetailView.as_view(), name='product-detail'),
path("products/cart/add/<slug>/<int:id>/<int:quantity>/", AddToCartView.as_view(), name='add_to_cart'),
path("products/cart/delete_one_cart_item/<slug>/<str:item_id>/<int:quantity>/", DeleteOneCartItemView.as_view(), name='delete_one_cart_item'),
Expand Down
55 changes: 6 additions & 49 deletions Dshop/apps/products_catalogue/views.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
import requests
from dj_shop_cart.cart import get_cart_class, Cart
from django.core.exceptions import ValidationError
from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.views import View
from django.views.generic import ListView, DetailView, DeleteView
from lxml import etree
from dj_shop_cart.cart import get_cart_class, Cart

from .models import Product, CeneoCategory, Category
from .models import Product, Category


class ProductListView(ListView):
Expand Down Expand Up @@ -50,7 +49,7 @@ def post(self, request, **kwargs):
if not product.is_available:
raise ValidationError("Produkt jest niedostępny.")

cart.add(product, quantity=quantity)
cart.add(product, quantity=quantity)

return redirect('cart_detail')

Expand All @@ -62,7 +61,7 @@ def post(self, request, **kwargs):
cart = self.model.new(request)
item_id = self.kwargs.get('item_id')

cart.remove(item_id=item_id, quantity=1)
cart.remove(item_id=item_id, quantity=1)

return redirect('cart_detail')

Expand Down Expand Up @@ -149,48 +148,6 @@ def get(self, request, *args, **kwargs):
return response


class CeneoCategoriesView(View):

@staticmethod
def fetch_ceneo_data():
url = 'https://developers.ceneo.pl/api/v3/kategorie'
try:
response = requests.get(url)
response.raise_for_status()
return response.content
except requests.RequestException as e:
raise CeneoAPIException(f"Failed to fetch data from Ceneo API: {e}")

# TODO: to add parent category to the model and add functionality to write it to database
def parse_categories(self, category_elem):
categories = []
for elem in category_elem:
category = {
'Id': int(elem.findtext('Id')),
'name': elem.findtext('Name'),
}
subcategories_elem = elem.find('Subcategories')
if subcategories_elem is not None:
categories.extend(self.parse_categories(subcategories_elem))
categories.append(category)
return categories

@staticmethod
def import_ceneo_categories(categories):
bulk_list = [CeneoCategory(id=category['Id'], name=category['name']) for category in categories]
CeneoCategory.objects.bulk_create(bulk_list, ignore_conflicts=True, update_conflicts=False)

def get(self, request, *args, **kwargs):
xml_data = self.fetch_ceneo_data()
root = etree.fromstring(xml_data)
categories = self.parse_categories(root)
for category in categories:
category['Id'] = int(category['Id'])
categories.sort(key=lambda x: x['Id'])
self.import_ceneo_categories(categories)
return HttpResponse('Ceneo categories data imported successfully.', 200)


class CeneoAPIException(Exception):
pass

Expand All @@ -208,7 +165,7 @@ class CategoryDetailView(DetailView):

def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
products_without_parent = Product.objects.filter(category=self.get_object(), parent_product=None, is_active=True)
products_without_parent = Product.objects.filter(category=self.get_object(), parent_product=None,
is_active=True)
context['products'] = products_without_parent
return context

0 comments on commit 6547e86

Please sign in to comment.