Категорія: Python

  • Як стати Software Engineer: моя історія

    Як стати Software Engineer: моя історія

    Для кого ця стаття?

    Для таких як я сам, хто в часи пандемії та суттєвої трансформації життя, вирішив змінити професію.

    Досвід

    Я — Сергій Купрієнко, зараз працюю Junior Software Engineer у великій аутсорсінговій компанії. До цього мав досвід у різних сферах: займався продажами, видавничою діяльністю, робив переклади, був редактором енциклопедії, науковцем-істориком, екскурсоводом, ученим секретарем музею. Захистив кандидатську дисертацію по історії інків та отримав науковий ступень PhD. Часто все це було паралельно, оскільки одночасно навчався та працював на 2-3 роботах.

    Хобі

    Хотів би згадати про свої хобі: історія, література (художня, нон-фікшн, наукова), переклади з іспанської мови, ведення блогу. На ентузіазмі я видав більше 10 книжок із перекладами джерел по історії Доколумбової Америки, а це, гадаю, більше, ніж було зроблено за 100 років до того. Маючи якесь хобі, як правило, згодом я отримував роботу, пов’язану з ним.

    Я мало був пов’язаний з IT-сферою напряму, аж поки не увійшов до команди Великої української енциклопедії, яка розробляла першу універсальну українську енциклопедію. Я був куратором розробки її онлайн-порталу, тобто, фактично, Project-Manager’ом, і разом із командою ми запустили у 2019 році.

    Switch

    А тепер розкажу про те, як я здійснив свійswitchіз науковця-історика в Software Engineer. В цілому, весь процес зайняв 1 рік 😊.

    Рішення про зміну професії я прийняв, порадившись із дружиною, в січні 2020 року, оскільки побачив перспективи розвитку та попит на IT-спеціалістів. Вона сказала, що варто спробувати. Це звучало фантастично, бо я не знав достеменно, що вивчати, скільки це займе часу і через що доведеться проходити. На той момент я працював у музеї на адміністративній посаді. 

    Чому я думав, що це реально? Бо на той час я опанував кілька корисних методик, які суттєво прискорювали процес самонавчання плюс інтерес до навчання, складних задач, віра, що все можливе, та інтерес до комп’ютерної сфери. 

    Методики

    Перша методика —швидкочитанняза допомогою технології Text-to-Speech. Для того, щоб нею скористатися, потрібно лише мати смартфон з Android, додаток PocketBook. В додатку треба включити аудіо режим Text-to-Speech, але на швидкості 2Х, тобто в два рази швидше звичайної вимови. І тоді будь-яку книгу можна прочитати дуже швидко. Ось моя публікація з цього приводу. Загалом, за 2018-2019 роки я прочитав більше 700 книг найрізноманітнішої тематики.

    Друга методика — швидкоперегляд. Усі навчальні відео я так само переглядав на швидкості 2Х. Гадаю, в майбутньому всі діти будуть навчатися, читаючи та переглядаючи відео зі швидкістю 2Х. 

    Python

    Коли задумався, яку мову програмування вивчати, то я вирішив обрати Python, як найпростішу для розуміння і найпоширенішу у викладанні. В березні 2020 побачив знижку на курси Data Science/Data Analytics відDatacamp, а підписка за $100 на рік – це крута інвестиція, то не вагаючись її купив. Далі подумав, як спланувати навчання і тут натрапив на сайт від компанії Epam, де можна було детально прописати всі можливі цілі, яких потрібно досягнути для рівня Junior. У мене було бажання стати Data Analyst. Під це і сформував свій план розвитку. Хоча в подальшому я і змінив своє ставлення до цієї цілі. Тож не варто цементувати в бетоні речі, доцільно бути гнучким до вимог ринку, роботодавця або клієнтів.

    Звідси, мої поради для таких, як я: потрібно поставити ціль; визначити конкретні кроки для її досягнення; бути готовим змінювати ціль, якщо вона застаріла.

    Закладки

    Також я мав за гарну звичку додавати будь-який цікавий сайт в закладки свого браузера Chrome. Пізніше з цих закладок я зробив репозиторій на GitHub, де розподілив посилання на сайти по категоріях. Паралельно я перечитав сотні статей про Python наMedium.com— і, скажу, що це один із найкращих ресурсів для розробників. Загалом за рік я переглянув чи перечитав більше 1500 статей по Python.

    Поради: зберігайте важливі сайти в закладках; структуруйте за темами.

    Paternity leave

    Звідки у мене було стільки вільного часу на все це? Доволі просто — я перебував уpaternity leaveзі своїм малятком. І скажу, що це був найкращий час у моєму житті, сповнений барвистими емоціями і новими враженнями. Власне, необтяжений якоюсь іншою роботою, я зміг себе присвятити батьківству та навчанню.

    Резюме та тестові завдання

    Поки тривало навчання, я робив мало своїх проектів. І це було найбільшою помилкою. Усвідомив я це лише в літку 2020 року. Тоді я почав надсилати свої перші резюме й отримувати перші відгуки. А це було неабияким випробуванням, адже майже усюди для новачків обов’язкова умова — виконати тестове завдання. Більшість тестових завдань були міні-проектами, частина – алгоритмічні задачки. Іноді ламав голову по три-чотири дні. Часто не міг вирішити одне чи два завдання з переліку в три-п’ять пунктів. На тиждень міг опустити руки. Але потім почав розуміти поразки як стимул поліпшити свої знання та навички. І все це давало змогу вивчити невідомі раніше теми.

    Поради: починайте робити власні проекти якомога раніше; продовжувати йти незважаючи на поразки, бо саме поразки вас загартовують.

    Перші проекти на Python

    В основному підтягував знання по напрямку Software Engineer наLinkedIn Learning, де зібрано чудові високоякісні курси по будь-якій мові програмування (підписка на перший рік коштувала 27 Євро). Я, мабуть, переглянув та протестував сотні цих курсів на різні теми по Python, Data Science, Machine Learning, NLP, Django та Flask.

    Саме веб-фреймворки Django і Flask мене зацікавили найбільше. І коли почав ними займатися, то відчув, що це і є ті речі, з яких можна зробити реальні пет-проекти, які можна вказувати в резюме. 

    Прокачайте свій Github-профіль

    Але перші реальні пропозиції роботи почали надходити лише в грудні 2020, і то лише тому, що я завів акаунт на GitHub зі своїми проектами і паралельно розміщував цікаві тематичні статті на своєму сайті.

    Вважаю, що чим більше ви як Software Engineer урізноманітните свій GitHub-профіль та резюме, тим більше шансів у вас буде отримати першу роботу в IT. Ось який профіль я зробив собі.

    До речі, на замітку рекрутерам, саме через такий тематичний пошук мене знайшла рекрутерка і запропонувала тему, яка цікавила мене і яка потрібна була замовнику. Тобто win-win ситуація. 

    Поради: розміщуйте власні пет-проекти на github, вказуйте їх у резюме.

    Прокачайте свій LinkedIn-профіль

    Паралельно, раджу прокачати свій профіль в LinkedIn, бо саме звідти часто надходять пропозиції від рекрутерів. Для цього я скористався особистими порадами Юлії Шишенко та її статтею. А також додав у друзі більше 2000 людей (HR, рекрутерів, Python-розробників, Data Scientist’ів і т.п.). Також створіть профіль на Djinni (https://djinni.co/), але новачкам отримати офер там може бути тривалим випробуванням, хоча як не дивно, саме там я отримав перший дивний офер.

    Поради: оптимізуйте профіль у LinkedIn, адже саме там вас будуть шукати рекрутери.

    Перший офер

    Найцікавіше почалося, коли мені запропонували перший офер у листопаді 2020 року…

    Але трохи передісторії 😊 

    Перша спроба потрапити в IT-компанію була доволі дивна. В листопаді 2020 року після інтерв’ю та тестового завдання на логіку я отримав офер на посаду Technical Customer Support від продуктової компанії. Мені здавалося, що так я зможу потрапити в IT, але не з парадного входу. Тим більше ризиковано для мене було, тому що основний стек у компанії був PHP. Домовилися, що я вийду на роботу 1 грудня. Коли я прийшов, то мені виділили комп’ютер з усіма налаштуваннями та доступом до HelpDesk. Я почав читати документацію. Та вже в перший день мені дали опрацьовувати перші запити від клієнтів. Оскільки не все було зрозуміло, то я почав радитись у свого менеджера, але на всі мої запитання була одна відповідь (усно або в чатах): “Ти маєш сам все вирішити та зрозуміти”. Це було дивно чути. На наступний день було те саме, але ще й комп’ютер почав самовільно перезавантажуватися разів чотири чи п’ять, після чого постійно доводилося наново все запускати і це нервувало. Та вже по обіді стало зрозуміло, що ніякої підтримки я не отримаю, мов, “розбирайся сам”, і я вирішив, що не хочу тут працювати. Сказав, що мене це не влаштовує, і роботодавець та я зрозуміли, що на тому і бути, ми розійшлися. Пропрацював я лише півтора дні, і це була моя найкоротша робота в житті. Я й досі не можу зрозуміти такого підходу роботодавця, коли новачок має розбиратися сам без будь-якої підтримки, і  його залишають сам на сам із невирішеною проблемою та неробочою технікою.  

    Коучинг-сесія

    Далі почалися “темні” дні пошуку роботи. І вже коли я був на самому емоційному дні, бо я ж хотів самостійно знайти роботу, без чиєїсь допомоги, моя дружина Любов Купрієнко, психолог та психотерапевт, запропонувала провести для мене коучинг-сесію. Це було 15 січня 2021 року. Я не уявляв, для чого воно треба. Але коучинг був крутий і збувся в усіх деталях, змінивши мій стан відчаю від довгого пошуку роботи на стан натхнення від бажаного результату. Ми поставили ряд цілей та конкретних формулювань, які я б хотів почути від майбутнього роботодавця:
    1) роботу мають запропонувати до 1 лютого 2021 (тобто протягом двох тижнів!),
    2) я маю почути фразу, якої чекав: “Ми раді запропонувати вам офер…”
    3) я хотів, щоб мені також сказали, що у мене буде ментор.

    І тут почалося! Стали надходити пропозиції одна за одною. 

    Офер та контр-офер

    Спочатку рекрутерка однієї з найбільших аутсорсінгових IT-компаній України пропонує мені пройти кільки етапів інтерв’ю на позицію Software Engineer та виконати непросте, але цікаве тестове завдання. І вже коли ми були на останньому етапі, на мене вийшла рекрутерка іншої — продуктової компанії. Теж запропонувала провести одне (замість традиційних 2-3) інтерв’ю з їхньою командою розробників. Я спочатку не знав, що відповісти, а потім подумав, що це найкращий шанс дізнатися про свій рівень та оцінити самого себе, тому я погодився.

    На наступний день після інтерв’ю в продуктову компанію, їхня рекрутерка запропонувала мені контр-офер з вищим рейтом, ніж в аутсорсінговій компанії. На цю нову пропозицію я сказав, що вже в процесі обговорення з іншою компанією і залишилося лише останнє підтвердження від клієнта. Клієнт підтвердив. 

    Дилема

    І почалася дилема.

    Вибрати першу, але велику компанію, з меншим рейтом, хоча і з ментором, або другу компанію, з більшим рейтом та одразу на позицію Junior. 

    Я вибрав першу. Бо мав ще навчитися багато чому новому, плюс буде ментор, який допоможе спрямувати мій розвиток у правильному напрямку. 

    Від Trainee до Junior Software Engineer

    І отримав джоб-офер своєї мрії, саме такий, як я описував у коучінгу, і саме в ті терміни, тобто протягом двох тижнів!

    За три місяці випробувального строку у якості Trainee Software Enginee, я вивчаю також Bash, основи C language, ознайомився з компіляторами.

    По завершенні випробувального терміну, отримав промоушен до рівня Junior Software Engineer.

    Продовжую вивчати все нові і нові речі – CI/CD, pipelines, Docker, можливо, Cloud-платформи або щось інше. Як то кажуть “нєсть їм числа”. 

    А тепер можна і відпочити та взяти коротку відпустку, щоб набратися нових сил, бо шлях програміста — то довгий та звивистий шлях постійного навчання і поліпшення своїх навичок 

    Ах, так, забув сказати, що моє хобі зараз – це програмування. Бо це різновид творчості. А я це люблю.

    Джерело: Highload

  • Conda cheatsheet

    Conda

    Managing Conda and Anaconda, Environments, Python, Configuration, Packages. Removing Packages or Environments

    (більше…)
  • Find the sum of the digits in the number 100! (Python)

    Find the sum of the digits in the number 100! (Python)

    Python code to demonstrate a method to compute the factorial digists sum, i.e. 100 factorial (100!).

    This test exercise I’ve recieved when I was looking for a Trainee Python Developer position.

    n = 100
    fact = 1
      
    for i in range(1, n+1): 
        fact = fact * i
    
    # Convert number to string
    text_fact = str(fact)
    
    # Initialize empty list for every letter of factorial string 
    summ = []
    
    for letter in text_fact:
        summ.append(int(letter))
    print(sum(summ))
    648
  • Django ORM and SQL: Making QuerySet Expressions

    Django ORM and SQL: Making QuerySet Expressions

    Making QuerySet & Query Expressions with Django ORM like SQL, or Django ORM == SQL.

    If you are migrating to Django from another MVC framework, chances are you already know SQL.

    In this post, we will be illustrating how to use Django ORM by drawing analogies to equivalent SQL statements. Connecting a new topic to your existing knowledge will help you learn to use the ORM faster.

    Let us consider a simple base model for a person with attributes name, age, and gender.

    (більше…)
  • Create an E-commerce Shop with Django (Part 4)

    Create an E-commerce Shop with Django (Part 4)

    How to create a checkout form in an E-commerce Shop with Django? Part 4.

    In the previous Part 3 we create models for Order and in this Part 4 of Create an E-commerce Shop with Django we will create checkout form an order.

    Prerequisites

    • Django Latest Version
    • Virtual Environment
    • IDE PyCharm or Visual Studio Code

    1. Form

    In this part of the tutorial we will create a checkout form.

    Checkout.html file has been adjusted to the needs of the checkout display. then we only need to create a form from the core directory.

    Then in the core directory create a new file called forms.py where this file will store everything related to the form.

    Import :

    from django import forms
    from django_countries.fields import CountryField
    from django_countries.widgets import CountrySelectWidget

    You can see we are using the country field library and this is a third party library so we have to install it to use it. to install country library jus run command below :

    $ pip install django-countries

    and in project’s settings.py add this code :

    INSTALLED_APPS = [
       ...
       'django_countries',
    ]

    Then we create a class form calledCheckoutFormas a form from the checkout page.

    PAYMENT = (
        ('S', 'Stripe'),
        ('P', 'Paypal')
    )
    
    class CheckoutForm(forms.Form):
        street_address = forms.CharField(widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': '1234 Main St.'
        }))
        apartment_address = forms.CharField(required=False, widget=forms.TextInput(attrs={
            'class': 'form-control',
            'placeholder': 'Apartment or suite'
        }))
        country = CountryField(blank_label='(select country)').formfield(widget=CountrySelectWidget(attrs={
            'class': 'custom-select d-block w-100'
        }))
        zip = forms.CharField(widget=forms.TextInput(attrs={
            'class': 'form-control'
        }))
        same_billing_address = forms.BooleanField(required=False)
        save_info = forms.BooleanField(required=False)
        payment_option = forms.ChoiceField(
            widget=forms.RadioSelect, choices=PAYMENT
        )

    And with this you will have checkout form.

    2. Models

    To create a checkout form we will create a new model class that functions to save shipping address an order.

    the class we will create isCheckoutAddresswhich will store the shipping address of the order from the form we made before.

    class CheckoutAddress(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        street_address = models.CharField(max_length=100)
        apartment_address = models.CharField(max_length=100)
        country = CountryField(multiple=False)
        zip = models.CharField(max_length=100)
    
        def __str__(self):
            return self.user.username

    dont forget as well to impor becouse we would use Country Field:

    from django_countries.fields import CountryField

    Do not forget migrate your model database with the command below :

    $ python manage.py migrate
    $ python manage.py makemigrations

    3. Views

    In the view don’t forget to add the country field library and don’t forget to add the model and form that we just created

    from .forms import CheckoutForm
    from .models import (
        ...
        CheckoutAddress
    )

    Create CheckoutView class

    class CheckoutView(View):
        def get(self, *args, **kwargs):
            form = CheckoutForm()
            context = {
                'form': form
            }
            return render(self.request, 'core/checkout.html', context=context)
    
        def post(self, *args, **kwargs):
            form = CheckoutForm(self.request.POST or None)
    
            try:
                order = Order.objects.get(user=self.request.user, ordered=False)
                if form.is_valid():
                    street_address = form.cleaned_data.get('street_address')
                    apartment_address = form.cleaned_data.get('apartment_address')
                    country = form.cleaned_data.get('country')
                    zip = form.cleaned_data.get('zip')
                    same_billing_address = form.cleaned_data.get('same_billing_address')
                    save_info = form.cleaned_data.get('save_info')
                    payment_option = form.cleaned_data.get('payment_option')
    
                    checkout_address = CheckoutAddress(
                        user=self.request.user,
                        street_address=street_address,
                        apartment_address=apartment_address,
                        country=country,
                        zip=zip
                    )
    
                    checkout_address.save()
                    order.checkout_address = checkout_address
                    order.save()
                    return redirect('core:checkout')
                messages.warning(self.request, 'Fail checkout')
                return redirect('core:checkout')
    
            except ObjectDoesNotExist:
                messages.error(self.request, 'You do not have an order')
                return redirect('core:order-summary')

    In the forms.py file that we made earlier. we send the form into templates via view. Thepostfunction that captures the value sent via the form in the templates.

    4. Urls

    As usual after we make the view don’t forget to register it in the core/urls.py file.

    Import

    from django.urls import path
    from .views import (
        ...
        CheckoutView
    )

    Register all your class and fuctions in views to urls.py file. after that we will add the address in

    Create path url to checkout page with code below:

    urlpatterns = [
       ...
       path('checkout', CheckoutView.as_view(), name='checkout'),
    ]

    And finally the checkout form can be accessed and save the order data into the database

    Proceed to the next part!

    I hope you’ve found the fourth part of this tutorial helpful. In the next session, we’re going to handling payment with stripe to this E-Commerce Website.

    You can visit github where find other scripts.

  • Create a E-commerce Shop with Django (Part 3)

    Create a E-commerce Shop with Django (Part 3)

    In the previous Part 2 we create models for Order and in this Part 3 of Create a E-commerce Shop with Django we will make a summary of the order in the shopping cart of your Django shop.

    Prerequisites

    • Django Latest Version
    • Virtual Environment
    • IDE PyCharm or Visual Studio Code

    Before starting the tutorial don’t forget to activate your Virtual Environment, and the project we created in the previous tutorial.

    1. Models

    Open core / models.py using the edit code and add some functions in class model as follows :

    1. Class Item

    Nothing is changed in the Item class because the order summary is not directly related to the Item class

    2. Class OrderItem

    InOrderItemclass we will add some additional functions as follows

    class OrderItem(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        ordered = models.BooleanField(default=False)
        item = models.ForeignKey(Item, on_delete=models.CASCADE)
        quantity = models.IntegerField(default=1)
    
        def __str__(self):
            return f'{self.quantity} of {self.item.item_name}'
    
        def get_total_item_price(self):
            return self.quantity * self.item.price
    
        def get_discount_item_price(self):
            return self.quantity * self.item.discount_price
    
        def get_amount_saved(self):
            saved = self.get_total_item_price() - self.get_discount_item_price()
            return f'{saved:.2f}'
    
        def get_final_price(self):
            if self.item.discount_price:
                return self.get_discount_item_price()
            return self.get_total_item_price()
    • get_total_item_price, returns the total price value of each product item
    • get_discount_item_price, returns the total price value of each product item based on discounted prices
    • get_amount_saved, returns the value of the price saved from existing discounts
    • get_final_price, returns which function is used as a price determinant (whether using the original price or discounted price)

    3. Class Order

    In the Order class add a function that will calculate the total price of the order

    class Order(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        items = models.ManyToManyField(OrderItem)
        start_date = models.DateTimeField(auto_now_add=True)
        ordered_date = models.DateTimeField()
        ordered = models.BooleanField(default=False)
    
        def __str__(self):
            return self.user.username
    
        def get_total_price(self):
            total = 0
            for order_item in self.items.all():
                total += order_item.get_final_price()
            return total
    • get_total_price, returns the value of the total price of all ordered product items

    4. Migrate model database

    Do not forget migrate your model database with the command below :

    $ python manage.py migrate
    $ python manage.py makemigrations

    2. Views

    After manage our model, now switches to the core/views.py file.

    You can just just takeorder_summary.htmland place it in the templates directory.

    1. Import
    from django.core.exceptions import ObjectDoesNotExist
    from django.shortcuts import render, get_object_or_404, redirect
    from django.contrib import messages
    from django.contrib.auth.decorators import login_required
    from django.contrib.auth.mixins import LoginRequiredMixin
    from django.views.generic import ListView, DetailView, View
    from django.utils import timezone
    from core.models import (
        Item,
        Order,
        OrderItem
    )

    Import all requiment library in your views.py, in django.views.generic you can see we import the View class. for the order summary views we will use this View class

    2. CreateOrderSummaryView

    class OrderSummaryView(LoginRequiredMixin, View):
        def get(self, *args, **kwargs):
    
            try:
                order = Order.objects.get(user=self.request.user, ordered=False)
                context = {
                    'object' : order
                }
                return render(self.request, 'core/order_summary.html', context)
            except ObjectDoesNotExist:
                messages.error(self.request, "You do not have an order")
                return redirect("/")

    In the OrderSummaryView class we use the Order model as the model and order_summary.html as tempalate.

    3. Create reduce quantity product

    In the previous tutorial we made 2 function:add_to_cart()andremove_from_cart().

    add_to_cart() make the quantiy of product adding but remove_from_cart() function will make all order removed. So we will make function that will reduce a quantity of product item and remove it if quantity equal to 0

    def reduce_quantity_item(request, pk):
        item = get_object_or_404(Item, pk=pk)
        order_qs = Order.objects.filter(
            user = request.user,
            ordered=False
        )
        if order_qs.exists():
            order = order_qs[0]
            if order.items.filter(item__pk=item.pk).exists():
                order_item = OrderItem.objects.filter(
                    item = item,
                    user = request.user,
                    ordered = False
                )[0]
                if order_item.quantity > 1:
                    order_item.quantity -= 1
                    order_item.save()
                else:
                    order_item.delete()
                messages.info(request, "Item quantity is updated")
                return redirect("core:order-summary")
            else:
                messages.info(request, "This item not in your cart")
                return redirect("core:product")
        else:
            messages.info(request, "You do not have an order")
            return redirect("core:product")

    4. Make an user must log in to make an order

    For each function add an @login_required annotation, where this will throw the user into the login page when running the function if the user has not logged in

    @login_required
    def add_to_cart(request, pk):
       ...
    @login_required
    def remove_from_cart(request, pk):
       ...
    @login_required
    def reduce_quantity_item(request, pk):
       ...

    3. Urls

    After completing the view, we will now add the OrderSummaryView url and the reduce_quantity item function in the core/url.py file

    1. Import
    from django.urls import path
    from .views import (
        remove_from_cart,
        reduce_quantity_item,
        add_to_cart,
        ProductView,
        HomeView,
        OrderSummaryView
    )

    add all the views and functions that we made in the views.py file on import, so we just add OrderSummaryView and reduce_quantity_item from the previous file.

    2. Create Path Url

    Create path url to OrderSummaryView and reduce_quantity_item() function like this :

    urlpatterns = [
        ...
        path('order-summary/', OrderSummaryView.as_view(), name="order-summary"),
        path('reduce-quantity-item/<int:pk>', reduce_quantity_item, name='reduce-quantity-item'),
    ]

    And now you can access the view and another functions.

    Proceed to the next part!

    I hope you’ve found the third part of this tutorial helpful. In the next session, we’re going to make Checkout form to this E-Commerce Website.

    You can visit github where find other scripts.

  • Create an E-commerce Shop with Django (Part 2)

    Create an E-commerce Shop with Django (Part 2)

    How to create an E-commerce Shop with Django? Part 2.

    Prerequisites

    • Django Latest Version
    • Virtual Environment
    • IDE PyCharm or Visual Studio Code

    Before starting the tutorial don’t forget to activate your Virtual Environment, and the project we created in the previous tutorial.

    1. Create Databases in Models

    Before we start to make an order the first thing to do is create a database that will store order data

    For starters we will make 3 data tables namely:
    – Item will store product data
    – OrderItem will store product data that you want to order
    – Order will store order information

    To create a database in Django framework, we will use models.py file which is in the core directory, open file with your code editor and proceed with this tutorial.

    1. Import
    from django.conf import settings
    from django.db import models
    from django.shortcuts import reverse

    2. Add Item

    CATEGORY = (
        ('S', 'Shirt'),
        ('SP', 'Sport Wear'),
        ('OW', 'Out Wear')
    )
    
    LABEL = (
        ('N', 'NEW'),
        ('BS', 'Best Seller')
    )
    
    class Item(models.Model):
        item_name = models.CharField(max_length=100)
        price = models.FloatField()
        discount_price = models.FloatField(blank=True, null=True)
        category = models.CharField(choices=CATEGORY, max_length=2)
        label = models.CharField(max_length=2)
        description = models.TextField()
    
        def __str__(self):
            return self.item_name
    
        def get_absolute_url(self):
            return reverse("core:product", kwargs={'pk': self.pk})
    
        def get_add_to_cart_url(self):
            return reverse("core:add-to-cart", kwargs={"pk": self.pk})
    
        def get_remove_from_cart_url(self):
            return reverse("core:remove-from-cart", kwargs={"pk": self.pk})

    In the item model you will see there are 3 additional functions, these functions include:

    • get_absolute_url will return url from product
    • get_add_to_cart_url will return url to function add item to cart in views.py file we will make
    • get_remove_from_cart_url will return url to function remove item from cart in views.py file we will make

    3. Add OrderItem

    class OrderItem(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        ordered = models.BooleanField(default=False)
        item = models.ForeignKey(Item, on_delete=models.CASCADE)
        quantity = models.IntegerField(default=1)
    
        def __str__(self):
            return f'{self.quantity} of {self.item.item_name}'

    OrderItem stores data of the product you want to order and the amount of the product

    4. Add Order

    class Order(models.Model):
        user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE)
        items = models.ManyToManyField(OrderItem)
        start_date = models.DateTimeField(auto_now_add=True)
        ordered_date = models.DateTimeField()
        ordered = models.BooleanField(default=False)
    
        def __str__(self):
            return self.user.username

    The Order model will store detailed information of the orders made, but in this part of the tutorial we will not display complete order information, we will add another field in the next part.

    5. Register database to admin

    open core/admin.py file witch code editor and fill with the code below :

    from django.contrib import admin
    from .models import Item, OrderItem, Order 
    admin.site.register(Item)
    admin.site.register(OrderItem)
    admin.site.register(Order)

    That will register your database on the admin page. You can check it on the admin page later

    6 . Migrate model database

    Migrate your model database with the command below :

    $ python manage.py migrate
    $ python manage.py makemigrations

    2. Managing Views

    We have created a database and now it is our turn to manage and manage our views. We will create 2 views that is HomeView and ProductView and 2 function that is add_to_cart() and remove_from_cart(). to continue open core/views.py and continue with the following tutorial

    1. Import
    from django.contrib import messages                       
    from django.shortcuts import render, get_object_or_404, redirect                      
    from django.views.generic import ListView, DetailView                      
    from django.utils import timezone                       
    from .models import (                           
        Item,
        Order,
        OrderItem
    )

    Import all the model classes that we have previously created into views.py

    2. Add HomeView

    In the previous tutorial article, we made a home function to display a view. delete the home function and change it as Class View this :

    class HomeView(ListView):
        model = Item
        template_name = 'core/home.html'

    We use the Item model as a home model and home.html as template view. home.html can be found at templates directory

    3. Add ProductView

    class ProductView(DetailView):
        model = Item
        template_name = 'core/product.html'

    We use the Item model as a home model and product.html as template view. product.html can be found at templates directory

    4. add_to_cart() function

    def add_to_cart(request, pk):
        item = get_object_or_404(Item, pk=pk)
        order_item, created = OrderItem.objects.get_or_create(
            item=item,
            user=request.user,
            ordered=False
        )
        order_qs = Order.objects.filter(user=request.user, ordered=False)
    
        if order_qs.exists():
            order = order_qs[0]
    
            if order.items.filter(item__pk=item.pk).exists():
                order_item.quantity += 1
                order_item.save()
                messages.info(request, "Added quantity Item")
                return redirect("core:product", pk=pk)
            else:
                order.items.add(order_item)
                messages.info(request, "Item added to your cart")
                return redirect("core:product", pk=pk)
        else:
            ordered_date = timezone.now()
            order = Order.objects.create(user=request.user, ordered_date=ordered_date)
            order.items.add(order_item)
            messages.info(request, "Item added to your cart")
            return redirect("core:product", pk=pk)

    This function will add your product to OrderItem database and add detail order to Order database

    5. remove_from_cart() function

    def remove_from_cart(request, pk):
        item = get_object_or_404(Item, pk=pk )
        order_qs = Order.objects.filter(
            user=request.user,
            ordered=False
        )
        if order_qs.exists():
            order = order_qs[0]
            if order.items.filter(item__pk=item.pk).exists():
                order_item = OrderItem.objects.filter(
                    item=item,
                    user=request.user,
                    ordered=False
                )[0]
                order_item.delete()
                messages.info(request, "Item \""+order_item.item.item_name+"\" remove from your cart")
                return redirect("core:product", pk=pk)
            else:
                messages.info(request, "This Item not in your cart")
                return redirect("core:product", pk=pk)
        else:
            #add message doesnt have order
            messages.info(request, "You do not have an Order")
            return redirect("core:product", pk=pk)

    This function will remove all your product from OrderItem database and remove detail order from Order database

    6. Update your templates directory

    In templates directory we make some changes.

    3. Managing Urls

    After the view is finished, then the url will be managed where the view will be displayed in the browser. Open your core/urls.py file and fill with the code below:

    from django.urls import path
    from .views import (
        remove_from_cart,
        add_to_cart,
        ProductView,
        HomeView
    )
    
    
    app_name = 'core'
    
    urlpatterns = [
        path('', HomeView.as_view(), name='home'),
        path('product/<int:pk>', ProductView.as_view(), name="product"),
        path('add-to-cart/<int:pk>', add_to_cart, name='add-to-cart'),
        path('remove-from-cart/<int:pk>', remove_from_cart, name='remove-from-cart'),
    ]

    Import all view classes and functions and add the url for each view.

    4. Demo Aplications

    1. Run your server with the command below :
    $ python manage.py runserver

    2. open http://127.0.0.1:8000/ and choose one product, if you do not have a product you can adding in admin page

    3. Click Add to cart button in product page and you will see the product will add to your OrderItem and Order database

    4. Click remove from cart button to remove your current order. it will delete order item from database Order and OrderItem

    To this end the function to create an order has been implemented

    Proceed to the next part!

    I hope you’ve found the second part of this tutorial helpful. Now you know how to create an E-commerce Shop with Django. In the next session, we’re going to make an Order Summary in our shopping cart.

    Another Django post is about Create a comment model in Django

  • Create a comment model in Django

    Create a comment model in Django

    I decide create a comment model in Django after Create my first open source project – Pyxtract and after learning Django. I wrote code for some Django apps, e.i. my Blog app.

    But how about receiving some feedbacks from your readers and letting them comment in your Django web site or blog?

    (більше…)
KUPRIENKO