Learn how to create a model to store the coupon code, a valid time frame, and the discount to apply.
- [Instructor] Hello. Welcome to a new section of this video called "Extending Your Shop". In the previous section we saw how to manage payments and orders. In this section we'll be learning how to extend the shop. We'll first create a coupon system, and then add internationalization and localization. We'll also see how to translate Python code and templates. We'll then use Rosetta translation interface and look into URL patterns for internationalization. After this we'll allow users to switch language, and translate models with django-parler. Now we move on the first video of this section that deals with how to create a coupon system.
In this video we'll see how to build the coupon models. Next, we'll apply a coupon to the shopping cart, and then apply these coupons to orders. Many online shops give out coupons to customers that can be redeemed for discounts on their purchases. An online coupon usually consists of a code that is given to users which is valid for a specific time frame. The code can be redeemed one or multiple times. We're going to create a coupon system for our shop. Our coupons will be valid for clients that enter the coupon in a specific time frame. The coupons will not have any limitation on the number of times they can be redeemed, but they will be applied to the total amount of the shopping cart.
For this functionality we'll need to create a model to store the coupon code, a valid time frame and the discount to apply. Create a new application inside the myshop project using the command python manage.py startapp coupons. Edit the settings.py file of myshop and add the coupon application to the INSTALLED_APPS setting. The new application is now active in our Django project.
Let's start by creating the coupon model. Edit the models.py file of the coupons application, and add this code to it and save it. This is the model that we're going to use to store coupons. The coupon model contains these elements. The first one is a code, which the users have to enter in order to apply the coupon to their purchase. The next one is valid_from, which indicates the date time value when the coupon becomes valid, and after that comes valid_to which indicates the date time value when the coupons become invalid.
And then comes discount. The discount rate to apply. This is a percentage so it takes values from zero to 100. We use validators for this field to limit the minimum or maximum accepted values. Final one is active which is a boolean that indicates whether the coupon is active. Now run the command python manage.py makemigrations. This is to generate the initial migration for the coupons application. This is the output which you should get once you run this command.
Then we execute the next command. Python manage.py migrate to apply migrations. You should see this output. The migrations are now applied in the database. Let's add the coupon model to the administration site. Edit the admin.py file of the coupons application and add this code to it and save the file. The coupons model is now registered in the administration site. Ensure your local server is running with the command python manage.py runserver.
Open this server in your browser and login. You should see this form on your screen. Fill in the form to create a new coupon that is valid for the current date. Make sure you check the active checkbox. So here we give the code, valid from dates and valid to dates, and also the discount.
And I'll click the Save button. We can store our new coupons and make queries to retrieve existing coupons. Now we need a way for customers to apply coupons to their purchases. Take a moment to think about how this functionality would work. The best way to apply a coupon would be first the user adds products to the shipping cart. Secondly, the user can add a coupon code in a form displayed in the shopping cart detail page. After that, when the user enters a coupon code and submits the form we look for an existing coupon with the given code that is currently valid.
We then have to check that the coupon's code matches the one entered by the user, the active attribute is true, and the current date time is between the valid from and valid to values. After validating that, if a coupon is found, we save it in the user's session and display the cart including the discount applied to it and the updated total amount. Finally, at the end, when the user places the order, we save the coupon to the given order. Create a new file inside the coupons application directory and name it forms.py.
Add this code to it. This is the form we're going to use for the user to enter a coupon code. Now, edit the views.py file inside the coupons application and add this code to it. The coupon_apply view validates the coupon and stores it in the user's session. We apply the require post decorator to this view to restrict it to POST requests.
In the view, we perform these tasks. First of all, we instantiate the CouponApplyForm using the posted data, and we check whether the form is valid. Then, if the form is valid, we get the code entered by the user from the form's cleaned_data dictionary. Then we try to retrieve the coupon object with the given code. We use the iexact field lookup to perform a case insensitive exact match. The coupon has to be currently active, that is, active equals true, and valid from the current date time. We use Django's timezone.now function to get the current time zone aware date time, and we compare it with the valid_from and valid_to date fields performing lte, that is less than or equal to, and gte, which means greater than or equal to field lookups respectively.
We then store the coupon id in the user's session. In the final step, we redirect the user to the cart_detail URL to display the cart with the coupon applied. We need a URL pattern for the coupon apply view, so we create a new file inside the coupons application directory, and name it urls.py. Add this code to it.
Then edit the main urls.py of the myshop projects and include the coupons URL pattern. Remember to place it above the shop.urls pattern. Now, edit the cart.py file of the cart application. Include this import. Add this code at the end of the init method of the cart class to initialize a coupon for the current session.
In this code we try to get the coupon_id session key from the current session, and store its value in the cart object. Edit the cart object. Add this code to it and then save it. These methods are as follows. First method is coupon. We define this method as a property. If the cart contains a coupon_id function the coupon object with the given id is returned. Second method is get_discount. In this, if the cart contains a coupon we retrieve its discount rate and return the amount to be deducted from the total amount of the cart.
The last method is get_total_price_after_discount. Here, we return the total amount of the cart after deducting the amount returned by the get_discount method. The cart class is now prepared to handle a coupon applied to the current session, and apply the corresponding discount. Let's include the coupon system in the cart detail view. Edit the views.py file of the cart's application and add the import statement.
Further down, edit the cart_detail view and add this code to it and save it. Now, edit the detail HTML template of the cart application and replace this code. This is the code to display an optional coupon and its discount rate. If the cart contains a coupon we display a first row including the total amount of the cart as the subtotal.
Then we use the second row to display the coupon applied to the cart. Finally, we display the total price including any discount by calling the get_total_price_after_discount method of the cart object. In the same file, after the table, include the HTML tag form. This will display a form to enter a coupon code and apply it to the current cart. Open this URL in your browser.
Add a product to the cart, and apply the coupon you created by entering its code in the form. You should see that the cart displays the coupon discount. Now let's add the coupon to the next step of the purchase process. Edit the create.html template of the orders application, and in the unordered list add these lines of code. Here we define an if statement, give the conditions for the list, and span, and then close list tag.
Also, don't forget to end the if condition and close the unordered list tag. Open this link in your browser. You should see that the order summary includes the applied coupon if there is any. By doing so the total price will be calculated by applying the discount of the coupon. Users can now apply coupons to their shopping cart. However, we still need to store coupon information in the order that is created when users checkout the cart.
Now let's see how to apply coupons to orders. We're going to store the coupon that was applied for each order. First, we need to modify the order model to store the related coupon objects, if there is any. Edit the models.py file of the orders application and add these imports to it.
Inside the order model add these lines of code. These fields will allow us to store an optional coupon applied to the order and the discount applied by the coupon. The discount is stored in the related coupon object, but we include it in the order model to preserve it if the coupon is modified or deleted.
Since the order model has changed we need to create a migration. So for that we run the command python manage.py makemigrations. You should see this output on your screen. Apply the new migration with the next command. Python manage.py migrate orders. You should get the confirmation that the new migration has been applied. The order model field changes are now synced with the database. Go back to the models.py file, and change the get_total_cost method of the order model.
Do these changes. The get_total_cost method of the order model will now take into account the applied discount, if there is any. Now edit the views.py file of the orders application and modify the order_create view to save the related coupon and its discount when creating a new order.
Here, we insert an if condition and save the results. In this new code we created an order object using the save method of the order_create form form. We avoid saving it to the database yet by using commit=False. If the cart contains a coupon, we store the related coupon and the discount that was applied. Then we save the order object to the database.
Make sure the development server is running with the command python manage.py runserver. Let's run ngrok from the shell using this command. Superb, so as you can see, we've obtained the session status and the URLs. Now open the URL provided by ngrok in your browser, check that the order object contains the coupon, and the applied discount that we see here.
You can also modify the admin order detail template and the order PDF build to display the applied coupon in the same manner we did for the cart. Awesome. In this video we've learned the technique of creating a coupon system. In the next video we're going to add internationalization to our project.
Note: This course was created by Packt Publishing. We are pleased to host this training in our library.
- Creating an online shop project
- Registering customer orders
- Managing payments and orders
- Integrating a payment gateway
- Extending the online shop
- Creating a coupon system
- Translating Python code