0% found this document useful (0 votes)
103 views206 pages

271CIS-3 Lab Manual

The document is a lab manual for the course 'Programming for Data Science' at King Khalid University, detailing the course structure, lab topics, and software tools used. It covers Python programming fundamentals, including installation, syntax, data types, and error handling, along with practical applications in data science. The manual also lists references and organizations that utilize Python, emphasizing its versatility and widespread use in the tech industry.

Uploaded by

luken1272
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
103 views206 pages

271CIS-3 Lab Manual

The document is a lab manual for the course 'Programming for Data Science' at King Khalid University, detailing the course structure, lab topics, and software tools used. It covers Python programming fundamentals, including installation, syntax, data types, and error handling, along with practical applications in data science. The manual also lists references and organizations that utilize Python, emphasizing its versatility and widespread use in the tech industry.

Uploaded by

luken1272
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 206

Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Lab Manual
271-CIS-3
Programming for Data Science
Department of Information systems
College of Computer Science
King Khalid University

Course Coordinator

Hisham Hummadi

271-CIS-3 Lab Manual - 2022 1


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Course Name Course Code


Introduction to Data Science 372-CIS-3

Lab Syllabus with Work Plan


Lab No. Topics to be covered
LAB - 1 Introduction to Python and Environment
LAB - 2 Installing Python Interpreter and IDE
LAB 3-4 Python Types: Object Types, Numeric Types, Dynamic Types
LAB 5-6 Python Types: Strings, Lists and Dictionaries
LAB 7-8 Python Statements: Iterative Structures, Conditional Structures
LAB 9-10 Scope, Functions
LAB 11-12 Modules and Packages
LAB 13-16 Object Oriented Programming
LAB 17-18 Exception Handling
LAB 19-20 Connecting and working with Database
LAB 21-26 Web application development with Python: Django framework

Software(s)/Tools Used
Jupyter Notebooks
Google Colab

References
• Lecture notes
• Learning Python, 5th Edition, By Mark Lutz, ISBN: 978-1449355739, Publisher: O'Reilly
Media, Release Date: June 2013ISBN: 978-1680501841.
• https://cognitiveclass.ai/

• https://developer.mozilla.org/en-US/docs/Learn/Server-side/Django

Mr. Hisham Hummadi IS Department Approval

271-CIS-3 Lab Manual - 2022 2


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-1 Introduction to Python and Environment

What is Python?
Python is a popular programming language. It was created by Guido van Rossum, and released in 1991. Python is a
high-level, general-purpose and a very popular programming language. Python programming language (latest
Python 3) is being used in web development, Machine Learning applications, along with all cutting edge
technology in Software Industry. Python Programming Language is very well suited for Beginners, also for
experienced programmers with other programming languages like C++ and Java.
What can Python do?

• Python can be used on a server to create web applications.


• Python can be used alongside software to create workflows.
• Python can connect to database systems. It can also read and modify files.
• Python can be used to handle big data and perform complex mathematics.
• Python can be used for rapid prototyping, or for production-ready software development.

Why Python?

• Python works on different platforms (Windows, Mac, Linux, Raspberry Pi, etc).
• Python has a simple syntax similar to the English language.
• Python has syntax that allows developers to write programs with fewer lines than some other programming
languages.
• Python runs on an interpreter system, meaning that code can be executed as soon as it is written. This means that
prototyping can be very quick.
• Python can be treated in a procedural way, an object-orientated way or a functional way.

Python Syntax compared to other programming languages

• Python was designed for readability, and has some similarities to the English language with influence from
mathematics.
• Python uses new lines to complete a command, as opposed to other programming languages which often use
semicolons or parentheses.
• Python relies on indentation, using whitespace, to define scope; such as the scope of loops, functions and classes.
Other programming languages often use curly-brackets for this purpose.

Below are some facts about Python Programming Language:

Python is currently the most widely used multi-purpose, high-level programming language. Python allows
programming in Object-Oriented and Procedural paradigms.

Python programs generally are smaller than other programming languages like Java. Programmers have to type relatively
less and indentation requirement of the language, makes them readable all the time.

271-CIS-3 Lab Manual - 2022 3


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python language is being used by almost all tech-giant companies like – Google, Amazon, Facebook, Instagram,
Dropbox, Uber… etc.

The biggest strength of Python is huge collection of standard library which can be used for the following:

• Machine Learning
• GUI Applications (like Kivy, Tkinter, PyQt etc. )
• Web frameworks like Django (used by YouTube, Instagram, Dropbox)
• Image processing (like OpenCV, Pillow)
• Web scraping (like Scrapy, BeautifulSoup, Selenium)
• Test frameworks
• Multimedia
• Scientific computing
• Text processing and many more..

Python Language advantages and applications


Python is a high level, interpreted and general purpose dynamic programming language that focuses on code
readability.It has fewer steps when compared to Java and C.It was founded in 1991 by developer Guido Van
Rossum.It is used in many organizations as it supports multiple programming paradigms.It also performs
automatic memory management.

Advantages :
1. Presence of third-party modules
2. Extensive support libraries(NumPy for numerical calculations, Pandas for data analytics etc)
3. Open source and community development
4. Easy to learn
5. User-friendly data structures
6. High-level language
7. Dynamically typed language(No need to mention data type based on value assigned, it takes data type)
8. Object-oriented language
9. Portable and Interactive
10. Portable across Operating systems

Applications :

1. GUI based desktop applications(Games, Scientific Applications)


2. Web frameworks and applications
3. Enterprise and Business applications
4. Operating Systems
5. Language Development
6. Prototyping

271-CIS-3 Lab Manual - 2022 4


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Organizations using Python :


1. Google(Components of Google spider and Search Engine)
2. Yahoo(Maps)
3. YouTube
4. Mozilla
5. Dropbox
6. Microsoft
7. Cisco
8. Spotify
9. Quora

271-CIS-3 Lab Manual - 2022 5


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-2 Installing Python Interpreter and IDE

Installation
• Download Anaconda3 https://www.anaconda.com/products/individual
• Open Anaconda3 and select Jupyter

271-CIS-3 Lab Manual - 2022 6


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

• Create folder for your subject to download all lectures on it. You will open that files from
Jupyter.

How can you start writing new code in Jupyter??

Select this one

271-CIS-3 Lab Manual - 2022 7


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

You should select code here.


The other choices are for write
paragraphs not python code

Write python codes and then


select run to see the output
under the code

Python - Writing Your First Python Code!

Your First Program in Python


A statement or expression is an instruction the computer will run or execute. Perhaps the simplest program you can
write is to print a statement in Python.
**Tip**: To *execute* the Python code in the grey code cell below, **click on it and press Shift + Enter**.
In [1]:
print("Hello World!")
Hello World!
In [ ]:

After executing the cell above, you should see that Python return the string, Hello Python 101. Congratulations on
running your first Python code!
**Tip:** **pr∫()pr∫()** is the **function** that you **executed**, and you *passed in* an **argument**
of 'HelloWorld!'′HelloWorld!′.

Python 3
How do we know that Python 3 is running? Take a look in the top-right hand corner of this notebook. You should see
"Python 3"!

271-CIS-3 Lab Manual - 2022 8


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Writing comments in Python


In addition to writing code, note that it is customary to comment your code to help describe what it does. Not only does
this help other people understand your code, it can also serve as a reminder to you of what your code does. (This is
especially true when you write some code and then come back to it weeks or months later.)

To write comments in your Python code, use the hash symbol (#) before writing your comment. When you run the code
Python will ignore everything after the # in that line.
In [2]:
print('Hello Python 101') #this my comment
#print('Hi')
Hello Python 101
Great! After executing the cell above, you should notice that "this is my comment did not appeared in the output,
because it was a comment (and thus ignored by Python). The second line was also not executed because print('Hi') was
preceded by a hash symbol (#) as well!

Errors in Python
Before continuing, it's important to note when things go wrong in Python, and we cause errors.
There are many kinds of errors, and you do not need to memorize the various types of errors. Instead, what's most
important is know what the error messages mean.

For example, if you spell print as frint, you will get an error message.
In [2]:
frint("Hello World!")
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-2-cbc42dbb0087> in <module>
----> 1 frint("Hello World!")

NameError: name 'frint' is not defined


The error message tells you (1) where the error occurred, and (2) what kind of error it was. Here, Python attempted to
run the function frint, but could not determine what frint -- since it is undefined.

Does Python know the error in the script before you run it?

No, Python is naive! Python will try to run the code line-by-line, and it will stop if it runs into an error.
In [3]:
print("This will be printed")
frint("This will cause an error")
print("This will NOT be printed")
This will be printed
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-3-aa3f0d14d353> in <module>
1 print("This will be printed")
----> 2 frint("This will cause an error")
3 print("This will NOT be printed")

NameError: name 'frint' is not defined

271-CIS-3 Lab Manual - 2022 9


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-3 Python Types: Object Types, Numeric Types, Dynamic Types

Types of objects in Python


You can have many different object types in Python, let's start with strings, integers and floats. Anytime you write
words (text) in Python, you're using character strings (strings for short). Numbers, on the other hand, depend: numbers
can be integers (like -1, 0, 100) or floats, which are real numbers (like 3.14, -42.0).

The following chart summarizes three data types for the last examples, the first column indicates the expression the
second column indicates the data type
In [4]:
11 #integer
Out[4]:
11
In [6]:
2.14 #float
Out[6]:
2.14
In [7]:
"Hello Python 101" #character string
Out[7]:
'Hello Python 101'

We can see the actual data type in python by using the type() command
In [5]:
type(12)
Out[5]:
int
In [6]:
type(2.14)
Out[6]:
float
In [7]:
type("Hello Python 101")
271-CIS-3 Lab Manual - 2022 10
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Out[7]:
str

Using the type() function, check the object type of 12.0?


In [11]:
# Write your code below

type(12.0)
Out[11]:
float

Integers
Here are some integers, integers can be negative or positive:

We can verify some of the above examples using the type command:
In [8]:
type(-1)
Out[8]:
int
In [13]:
type(4)
Out[13]:
int
In [14]:
type(0)
Out[14]:
int

Floats
Floats are real numbers; they include the integers but also "numbers in-between the integers". Consider the numbers
between 0 and one we can select numbers in-between them, these numbers are floats. Similarly, consider the numbers
between 0.5 and 0.6. We can select numbers in-between them, these are floats as well. We can continue the process,
zooming in for different numbers, of course, there is a limit, but it is quite small.
We can verify some of the above examples using the type command:
In [15]:
type(1.0)
Out[15]:
float
In [16]:
type(0.5)
Out[16]:
float

271-CIS-3 Lab Manual - 2022 11


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [17]:
type(0.56)
Out[17]:
float

Converting from one object type to a different object type


You can change the type of the object in Python; this is called typecasting. For example, you can convert an integer into a
float, as in 2 to 2.0.
In [18]:
type(2) #verify that this is an integer
Out[18]:
int

Converting to float:
In [19]:
float(2)
Out[19]:
2.0
In [20]:
type(float(2))
Out[20]:
float

Converting to integer:
Nothing really changes. If you cast a float to an integer, you must be careful. For example, if you cast the float 1.1 to 1 you
will lose some information :
In [21]:
int(1.1)
Out[21]:
1

Converting from strings to integers/floats:


If a string contains an integer value, you can convert it to an integer:
In [22]:
int('1')
Out[22]:
1
You can also convert strings containing float values into float objects
In [10]:
float('1.2')
Out[10]:
1.2
However, if we attempt to convert a string that contains a non-numerical value, we get an error:
In [11]:
int("A")
271-CIS-3 Lab Manual - 2022 12
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-11-51b62aeb0293> in <module>
----> 1 int("A")

ValueError: invalid literal for int() with base 10: 'A'

Converting to strings:
You can convert an int to a string:
In [25]:
str(1)
Out[25]:
'1'
You can convert a float to a string
In [26]:
str(1.2)
Out[26]:
'1.2'

Boolean
Boolean is another important type in Python; a Boolean can take on two values. The first value is true, just remember we
use an uppercase T:
In [12]:
True
Out[12]:
True
Boolean values can also be false, with an uppercase F:
In [13]:
False
Out[13]:
False
Using the type command on a Boolean value we obtain the term bool, this is short for Boolean
In [14]:
type(True)
Out[14]:
bool
In [15]:
type(False)
Out[15]:
bool
If we cast a Boolean true to an integer or float we will get a 1, if we cast a Boolean false to an integer or float. If we get a
zero if you cast a 1 to a boolean, you get a true similarly, if you cast a 0 to a Boolean you get a false.
In [31]:
int(True)
Out[31]:
1
In [32]:
271-CIS-3 Lab Manual - 2022 13
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

bool(1)
Out[32]:
True
In [33]:
bool(0)
Out[33]:
False
In [34]:
float(True)
Out[34]:
1.0

Expressions
Expressions are operations that Python performs. For example, basic arithmetic operations like adding multiple
numbers.
In [21]:
43 + 60 + 16 + 41
Out[21]:
160
We can perform operations such as subtraction using the subtraction sign. In this case the result is a negative number.
In [22]:
50 - 60
Out[22]:
-10
We can use multiplication using an asterisk:
In [23]:
5 * 5
Out[23]:
25
We can also perform division with the forward slash
In [6]:
25 / 5
Out[6]:
5.0
In [7]:
25 / 6
Out[7]:
4.166666666666667
We can use the double slash for integer division, where the result is rounded
In [8]:
25//5
Out[8]:
5
In [9]:
25//6
Out[9]:
4

271-CIS-3 Lab Manual - 2022 14


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

[Tip] Summary

You can do a variety of mathematical operations in Python including:


• addition: **2 + 2**
• subtraction: **5 - 2**
• multiplication: **3 \* 2**
• division: **4 / 2**
• exponentiation: **4 \*\* 2**

Dynamic object type :


Use variable to have dynamic type : x=5 x='Hello'

when you print x you will have different output that mean it change the value whithout change
variable x.

In [38]:
# This will store 6 in the memory and binds the
# name x to it. After it runs, type of x will
# be int.
6

print(type(6))

# This will store 'hello' at some location int


# the memory and binds name x to it. After it
# runs type of x will be str.
x = 'hello'

print(type(6))
<class 'int'>
<class 'str'>

271-CIS-3 Lab Manual - 2022 15


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-4 Python Types: Object Types, Numeric Types, Dynamic Types, (cont.)

TUPLES IN PYTHON

In Python, there are different data types: string, integer and float. These data types can all be contained in a
tuple as follows:

In [1]:
tuple1=("disco",10,1.2)
tuple1
print(tuple1)
('disco', 10, 1.2)
The type of variable is a tuple.

In [5]:
type(tuple1[2])
Out[5]:
float

Each element of a tuple can be accessed via an index. The following table represents the relationship between
the index and the items in the tuple. Each element can be obtained by the name of the tuple followed by a
square bracket with the index number:

271-CIS-3 Lab Manual - 2022 16


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can print out each value in the tuple:


In [5]:
print( tuple1[0])
print( tuple1[1])
print( tuple1[2])
disco
10
1.2

We can print out the type of each value in the tuple:


In [4]:
print( type(tuple1[0]))
print( type(tuple1[1]))
print( type(tuple1[2]))
<class 'str'>
<class 'int'>
<class 'float'>

We can also use negative indexing. We use the same table above with corresponding negative values:

We can obtain the last element as follows (this time we will not use the print statement to display the values):
In [5]:
tuple1[-1]
Out[5]:
1.2

We can display the next two elements as follows:


In [6]:
tuple1[-2]
Out[6]:
10
In [7]:
tuple1[-3]
Out[7]:
'disco'

271-CIS-3 Lab Manual - 2022 17


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can concatenate or combine tuples by using the + sign:


In [6]:
tuple2=tuple1+("hard rock", 10)
tuple2
Out[6]:
('disco', 10, 1.2, 'hard rock', 10)

We can slice tuples obtaining multiple values as demonstrated by the figure below:

We can slice tuples, obtaining new tuples with the corresponding elements:
In [7]:
tuple2[0:3]
Out[7]:
('disco', 10, 1.2)

We can obtain the last two elements of the tuple:


In [10]:
tuple2[3:5]
Out[10]:
('hard rock', 10)

We can obtain the length of a tuple using the length command:


In [8]:
len(tuple2)
len(tuple1)
Out[8]:
3

This figure shows the number of elements:

271-CIS-3 Lab Manual - 2022 18


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Consider the following tuple:


In [1]:
Ratings =(0,9,6,5,10,8,9,6,2)

We can assign the tuple to a 2nd variable:


In [4]:
Ratings1=Ratings
RatingsSorted=sorted(Ratings1)
RatingsSorted
print(RatingsSorted)
[0, 2, 5, 6, 6, 8, 9, 9, 10]

We can sort the values in a tuple and save it to a new tuple:


In [ ]:

In [12]:
RatingsSorted=sorted(Ratings )
print(RatingsSorted);
[0, 2, 5, 6, 6, 8, 9, 9, 10]

A tuple can contain another tuple as well as other more complex data types. This process is called 'nesting'.
Consider the following tuple with several elements:
In [10]:
NestedT =(1, 2, ("pop", "rock") ,(3,4),("disco",(1,2)))
In [15]:
print(NestedT[4][1][0])
1
Each element in the tuple including other tuples can be obtained via an index as shown in the figure:

</a>

In [21]:
print("Element 0 of Tuple: ", NestedT[0])
print("Element 1 of Tuple: ", NestedT[1])
print("Element 2 of Tuple: ", NestedT[2])
print("Element 3 of Tuple: ", NestedT[3])
print("Element 4 of Tuple: ", NestedT[4])
Element 0 of Tuple: 1
Element 1 of Tuple: 2
Element 2 of Tuple: ('pop', 'rock')
Element 3 of Tuple: (3, 4)
Element 4 of Tuple: ('disco', (1, 2))

271-CIS-3 Lab Manual - 2022 19


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can use the second index to access other tuples as demonstrated in the figure:

</a>

We can access the nested tuples :


In [22]:
print("Element 2,0 of Tuple: ", NestedT[2][0])
print("Element 2,1 of Tuple: ", NestedT[2][1])
print("Element 3,0 of Tuple: ", NestedT[3][0])
print("Element 3,1 of Tuple: ", NestedT[3][1])
print("Element 4,0 of Tuple: ", NestedT[4][0])
print("Element 4,1 of Tuple: ", NestedT[4][1])
Element 2,0 of Tuple: pop
Element 2,1 of Tuple: rock
Element 3,0 of Tuple: 3
Element 3,1 of Tuple: 4
Element 4,0 of Tuple: disco
Element 4,1 of Tuple: (1, 2)
We can access strings in the second nested tuples using a third index:

In [23]:
NestedT[2][1][0]
Out[23]:
'r'
In [24]:
NestedT[2][1][1]
Out[24]:
'o'

271-CIS-3 Lab Manual - 2022 20


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can use a tree to visualise the process. Each new index corresponds to a deeper level in the tree:

</a>

Similarly, we can access elements nested deeper in the tree with a fourth index:
In [25]:
NestedT[4][1][0]
Out[25]:
1
In [26]:
NestedT[4][1][1]
Out[26]:
2

The following figure shows the relationship of the tree and the element NestedT[4][1][1]:

271-CIS-3 Lab Manual - 2022 21


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Variables
We can also store our output in variables, so we can use them later on. For example:
In [40]:
x = 43 + 60 + 16 + 41
To return the value of x, we can simply run the variable as a command:
In [41]:
x
Out[41]:
160
We can also perform operations on x and save the result to a new variable:
In [42]:
print(x)
160
In [9]:
y = x / 60
y
Out[9]:
2.6666666666666665
If we save something to an existing variable, it will overwrite the previous value:
In [ ]:
x = x / 60
x
It's good practice to use meaningful variable names, so you don't have to keep track of what variable is what:
In [ ]:
total_min = (43 + 42 )
total_min
In [ ]:
total_hr = total_min / 60
total_hr
You can put this all into a single expression, but remember to use round brackets to add together the album lengths
first, before dividing by 60.
In [ ]:
total_hr = (43 + 42 + 57) / 60 # get total hours in a single expression
total_hr

271-CIS-3 Lab Manual - 2022 22


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Sets
In this lab, we are going to take a look at sets in Python. A set is a unique collection of objects in Python. You can denote a
set with a curly bracket {}. Python will remove duplicate items:
In [1]:
set1={"pop", "rock", "soul", "hard rock", "rock", "R&B", "rock", "disco"}
set1
Out[1]:
{'R&B', 'disco', 'hard rock', 'pop', 'rock', 'soul'}
The process of mapping is illustrated in the figure:

You can also create a set from a list as follows:


In [2]:
album_list =[ "Michael Jackson", "Thriller", 1982, "00:42:19", \
"Pop, Rock, R&B", 46.0, 65, "30-Nov-82", None, 10.0]
print(album_list)

album_set = set(album_list)
print (album_set)
['Michael Jackson', 'Thriller', 1982, '00:42:19', 'Pop, Rock, R&B', 46.0, 65, '30-Nov-82'
, None, 10.0]
{65, '30-Nov-82', 10.0, 'Michael Jackson', 46.0, '00:42:19', None, 'Thriller', 1982, 'Pop
, Rock, R&B'}

Now let us create a set of genres:


In [3]:
music_genres = set(["pop", "pop", "rock", "folk rock", "hard rock", "soul", \
"progressive rock", "soft rock", "R&B", "disco"])
music_genres
Out[3]:
{'R&B',
'disco',
'folk rock',
'hard rock',
'pop',
'progressive rock',
'rock',
'soft rock',
'soul'}
set('rap''house''e≤ctronicμsic''rap')set(′rap′′house′′e≤ctronicμsic′′rap′)
271-CIS-3 Lab Manual - 2022 23
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Notice that the duplicates are removed and the output is sorted.
Let us get the sum of the claimed sales:
Consider the list A=[1,2,2,1] and set B=set([1,2,2,1]), does sum(A)=sum(B)
In [3]:
A=[1,2,2,1]
B=set([1,2,2,1])
print (sum(A))
print(sum(B))
6
3

Set Operations
Let us go over Set Operations, as these can be used to change the set. Consider the set A:
In [21]:
A = set(["Thriller","Back in Black", "AC/DC",21] )
A
Out[21]:
{21, 'AC/DC', 'Back in Black', 'Thriller'}

We can add an element to a set using the add() method:


In [7]:
A.add("NSYNC")
A
Out[7]:
{'AC/DC', 'Back in Black', 'NSYNC', 'Thriller'}

If we add the same element twice, nothing will happen as there can be no duplicates in a set:
In [7]:
A.add("NSYNC")
A
Out[7]:
{'AC/DC', 'Back in Black', 'NSYNC', 'Thriller'}

We can remove an item from a set using the remove method:


In [8]:
A.remove("NSYNC")
A
Out[8]:
{'AC/DC', 'Back in Black', 'Thriller'}

271-CIS-3 Lab Manual - 2022 24


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can verify if an element is in the set using the in command :


In [9]:
"AC/DC" in A
Out[9]:
True

Working with sets


Remember that with sets you can check the difference between sets, as well as the symmetric difference, intersection,
and union:
Consider the following two sets:
In [4]:
album_set1 = set(["Thriller",'AC/DC', 'Back in Black'] )
album_set2 = set([ "AC/DC","Back in Black", "The Dark Side of the Moon"] )

Visualizing the sets as two circles

In [23]:

271-CIS-3 Lab Manual - 2022 25


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

album_set1, album_set2
Out[23]:
({'AC/DC', 'Back in Black', 'Thriller'},
{'AC/DC', 'Back in Black', 'The Dark Side of the Moon'})
As both sets contain 'AC/DC' and 'Back in Black' we represent these common elements with the intersection of two
circles.

Visualizing common elements with the intersection of two circles.

We can find the common elements of the sets as follows:


In [5]:
album_set_3=album_set1 & album_set2
album_set_3
Out[5]:
{'AC/DC', 'Back in Black'}

271-CIS-3 Lab Manual - 2022 26


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can find all the elements that are only contained in album_set1 using the difference method:
In [6]:
album_set2.difference(album_set1)
Out[6]:
{'The Dark Side of the Moon'}
In [7]:
album_set1.difference(album_set2)
Out[7]:
{'Thriller'}
We only consider elements in album_set1; all the elements in album_set2, including the intersection, are not included.

The difference of “album_set1” and “album_set2

271-CIS-3 Lab Manual - 2022 27


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The difference between album_set2 and album_set1 is given by:


In [14]:
album_set2.difference(album_set1)
Out[14]:
{'The Dark Side of the Moon'}

The difference of album_set2 and album_set1

271-CIS-3 Lab Manual - 2022 28


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can also find the intersection, i.e in both album_list2 and album_list1, using the intersection command :
In [9]:
album_set2.intersection(album_set1)
Out[9]:
{'AC/DC', 'Back in Black'}

This corresponds to the intersection of the two circles:

Intersection of set

271-CIS-3 Lab Manual - 2022 29


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The union corresponds to all the elements in both sets, which is represented by colouring both circles:

Figure 7: Union of set

The union is given by:


In [16]:
album_set1.union(album_set2)
Out[16]:
{'AC/DC', 'Back in Black', 'The Dark Side of the Moon', 'Thriller'}
And you can check if a set is a superset or subset of another set, respectively, like this:
In [17]:
set(album_set1).issuperset(album_set2)
Out[17]:
False
In [18]:
set(album_set2).issubset(album_set1)
Out[18]:
False

Here is an example where issubset() is issuperset() is true:


In [19]:
set({"Back in Black", "AC/DC"}).issubset(album_set1)
Out[19]:
True
In [20]:
album_set1.issuperset({"Back in Black", "AC/DC"})
Out[20]:
True

271-CIS-3 Lab Manual - 2022 30


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-5 Python Types: Strings, Lists and Dictionaries

Strings
A string is contained within 2 quotes:
In [ ]:
"Michael Jackson"
You can also use single quotes:
In [ ]:
'Michael Jackson'
A string can be spaces and digits:
In [ ]:
'1 2 3 4 5 6 '
A string can also be special characters :
In [ ]:
'@#2_#]&*^%$'
We can print our string using the print statement:
In [ ]:
print("hello!")
We can bind or assign a string to another variable:
In [ ]:
Name= "Michael Jackson"
Age = '29'
In [ ]:
print(Name)
print(Age)

Indexing
It is helpful to think of a string as an ordered sequence. Each element in the sequence can be accessed using an index
represented by the array of numbers:

271-CIS-3 Lab Manual - 2022 31


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The first index can be accessed as follows:


In [ ]:
print(Name[13])
We can access index 6:
In [ ]:
print(Name[7])
In [ ]:

Moreover, we can access the 13th index:


In [ ]:
print(Name[13])
In [ ]:

We can also use negative indexing with strings:

</a>
The last element is given by the index -1:
In [ ]:
print(Name[-1])
The first element can be obtained by index -15:
In [ ]:
print(Name[-15])
We can find the number of characters in a string by using 'len', short for length:
In [ ]:
len("Michael Jackson")
We can obtain multiple characters from a string using slicing, we can obtain the 0 to 4th and 8th to the 12th element:

271-CIS-3 Lab Manual - 2022 32


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [ ]:
Name[0:4]
In [ ]:

In [ ]:
Name[8:12]
In [ ]:

We can also input a stride value as follows, with the '2' indicating that we are selecting every second variable:

</a>
In [ ]:
Name[::2]
We can also incorporate slicing with the stride. In this case, we select the first five elements and then use the stride:
In [ ]:
Name[0:5:2]
We can concatenate or combine strings by using the addition symbols, and the result is a new string that is a
combination of both:
In [ ]:
Statement = Name + " is the best"
Statement
To replicate values of a string we simply multiply the string by the number of times we would like to replicate it. In this
case, the number is three. The result is a new string, and this new string consists of three copies of the original string:
In [ ]:
3*"Michael Jackson "
You can create a new string by setting it to the original variable. Concatenated with a new string, the result is a new
string that changes from Michael Jackson to “Michael Jackson is the best".
In [ ]:
Name= "Michael Jackson"
Name= Name+" is the best"
Name
Statement

271-CIS-3 Lab Manual - 2022 33


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Escape Sequences
Back slashes represent the beginning of escape sequences. Escape sequences represent strings that may be difficult to
input. For example, back slash "n" represents a new line. The output is given by a new line after the back slash "n” is
encountered:
In [ ]:
print(" Michael Jackson \n is the best" )
Similarly, back slash "t" represents a tab:
In [ ]:
print(" Michael Jackson \t is the best" )
If you want to place a back slash in your string, use a double back slash:
In [ ]:
print(" Michael Jackson \\ is the best" )
We can also place an "r" before the string to display the backslash:
In [ ]:
print(r" Michael Jackson \ is the best" )

String Operations
There are many string operation methods in Python that can be used to manipulate the data. We are going to use some
basic string operations on the data.
Let's try with the method "upper"; this method converts upper case characters to lower case characters:
In [ ]:
A="Thriller is the sixth studio album"
print("before upper:",A)
B=A.upper()
print("After upper:",B)

The method replaces a segment of the string, i.e. a substring with a new string. We input the part of the string we would
like to change. The second argument is what we would like to exchange the segment with, and the result is a new string
with the segment changed:
In [ ]:
A="Michael Jackson is the best"
B=A.replace('Michael', 'Janet')
B

The method "find" finds a sub-string. The argument is the substring you would like to find, and the output is the first
index of the sequence. We can find the sub-string "jack" or "el".

271-CIS-3 Lab Manual - 2022 34


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [ ]:
Name="Michael Jackson"
Name.find('el')
In [ ]:

In [ ]:
Name.find('Jack')
If the sub-string is not in the string then the output is a negative one. For example, the string 'Jasdfasdasdf' is not a
substring:
In [ ]:
Name.find('Jasdfasdasdf')

LISTS IN PYTHON
About the Dataset
Imagine you received many music recommendations from your friends and compiled all of the recommendations into a
table, with specific information about each movie.

The table has one row for each album and several columns:

• artist - Name of the artist


• album - Name of the album
• released_year - Year the album was released
• length_min_sec - Length of the album (hours,minutes,seconds)
• genre - Genre of the album
• music_recording_sales_millions - Music recording sales (millions in USD) on SONG://DATABASE
• claimed_sales_millions - Album's claimed sales (millions in USD) on SONG://DATABASE
• date_released - Date on which the album was released
• soundtrack - Indicates if the album is the movie soundtrack (Y) or (N)
• rating_of_friends - Indicates the rating from your friends from 1 to 10

271-CIS-3 Lab Manual - 2022 35


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Lists
We are going to take a look at lists in Python. A list is a sequenced collection of different objects such as
integers, strings, and other lists as well. The address of each element within a list is called an 'index'. An index
is used to access and refer to items within a list.

Representation of a list
To create a list, type the list within square brackets [ ], with your content inside the parenthesis and separated by
commas. Let’s try it!
In [1]:
L=["Michael Jackson" , 10.1,1982]
L
Out[1]:
['Michael Jackson', 10.1, 1982]
In [2]:
type(L)
Out[2]:
list

271-CIS-3 Lab Manual - 2022 36


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can use negative and regular indexing with a list :

Representation of a list
In [3]:
print('the same element using negative and positive indexing:\n Postive:',L[0],
'\n Negative:' , L[-3] )
print('the same element using negative and positive indexing:\n Postive:',L[1],
'\n Negative:' , L[-2] )
print('the same element using negative and positive indexing:\n Postive:',L[2],
'\n Negative:' , L[-1] )
the same element using negative and positive indexing:
Postive: Michael Jackson
Negative: Michael Jackson
the same element using negative and positive indexing:
Postive: 10.1
Negative: 10.1
the same element using negative and positive indexing:
Postive: 1982
Negative: 1982
Lists can contain strings, floats, and integers. We can nest other lists, and we can also nest tuples and other data structures. The same indexing conventions apply for
nesting:

In [2]:
[ "Michael Jackson", 10.1,1982,[1,2],("A",1) ]
Out[2]:
['Michael Jackson', 10.1, 1982, [1, 2], ('A', 1)]
We can also perform slicing in lists. For example, if we want the last two elements, we use the following command:

In [3]:
L=[ "Michael Jackson", 10.1,1982,"MJ",1]
L
Out[3]:
['Michael Jackson', 10.1, 1982, 'MJ', 1]

271-CIS-3 Lab Manual - 2022 37


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Representation of a list
In [4]:
L[3:5]
Out[4]:
['MJ', 1]

We can use the method "extend" to add new elements to the list:
In [5]:
L=[ "Michael Jackson", 10.2]
L.extend(['pop',10])
L
Out[5]:
['Michael Jackson', 10.2, 'pop', 10]

Another similar method is 'appended'. If we apply 'appended' instead of 'extended', we add one element to the
list:
In [6]:
L=[ "Michael Jackson", 10.2]
L.append(['pop',10])
L
Out[6]:
['Michael Jackson', 10.2, ['pop', 10]]

Each time we apply a method, the list changes. If we apply "extend" we add two new elements to the list. The
list L is then modified by adding two new elements:
In [7]:
L=[ "Michael Jackson", 10.2]
L.extend(['pop',10])
L
Out[7]:
['Michael Jackson', 10.2, 'pop', 10]

If we append the list ['a','b'] we have one new element consisting of a nested list:
In [8]:
L.append(['a','b'])
L
Out[8]:
['Michael Jackson', 10.2, 'pop', 10, ['a', 'b']]

As lists are mutable, we can change them. For example, we can change the first element as follows:
In [3]:
A=["disco",10,1.2]
print('Before change:', A)
A[0]='hard rock'
print('After change:', A)
Before change: ['disco', 10, 1.2]
After change: ['hard rock', 10, 1.2]
We can also delete an element of a list using the del command:

In [4]:
print('Before change:', A)
del(A[0])
print('After change:', A)

271-CIS-3 Lab Manual - 2022 38


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Before change: ['hard rock', 10, 1.2]


After change: [10, 1.2]

We can convert a string to a list using 'split'. For example, the method split translates every group of characters
separated by a space into an element in a list:
In [11]:
'hard rock'.split()
Out[11]:
['hard', 'rock']

We can use the split function to separate strings on a specific character. We pass the character we would like to
split on into the argument, which in this case is a comma. The result is a list, and each element corresponds to a
set of characters that have been separated by a comma:
In [6]:
'A,B,C,D'.split(',')
Out[6]:
['A', 'B', 'C', 'D']

When we set one variable B equal to A; both A and B are referencing the same list in memory :
In [18]:
A=["hard rock",10,1.2]
B=A
print('A:',A)
print('B:',B)
A: ['hard rock', 10, 1.2]
B: ['hard rock', 10, 1.2]

Initially, the value of the first element in B is set as hard rock. If we change the first element in A to 'banana',
we get an unexpected side effect. As A and B are referencing the same list, if we change list A, then list B also
changes. If we check the first element of B we get banana instead of hard rock:
In [19]:
print('B[0]:',B[0])
A[0]="banana"
print('B[0]:',B[0])
B[0]: hard rock
B[0]: banana

271-CIS-3 Lab Manual - 2022 39


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

You can clone list A by using the following syntax:


In [24]:
B=A[:]
B
Out[24]:
['banana', 10, 1.2]

Now if you change A, B will not change:


In [28]:
print('B[0]:',B[0])
A[0]="Hard rock"
print('B[0]:',B[0])
print('A[0]:',A[0])
B[0]: banana
B[0]: banana
A[0]: Hard rock

271-CIS-3 Lab Manual - 2022 40


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-6 Python Types: Strings, Lists and Dictionaries (cont.)

Python Collections (Arrays)


There are four collection data types in the Python programming language:
List:
is a collection which is ordered and changeable. Allows duplicate members.
Tuple:
is a collection which is ordered and unchangeable. Allows duplicate members.
Set:
is a collection which is unordered and unindexed. No duplicate members.
Dictionary:
is a collection which is unordered and changeable. No duplicate members. When choosing a collection type, it is useful to
understand the properties of that type. Choosing the right type for a particular data set could mean retention of
meaning, and, it could mean an increase in efficiency or security

Dictionary:
Dictionaries are used to store data values in key:value pairs. A dictionary is a collection which is unordered, changeable
and does not allow duplicates. Dictionaries are written with curly brackets, and have keys and values:
In [ ]:
In [18]:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(thisdict)
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964}

271-CIS-3 Lab Manual - 2022 41


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Dictionary Items:
Dictionary items are unordered, changeable, and does not allow duplicates.
Dictionary items are presented in key:value pairs, and can be referred to by using the key name.
In [2]:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(thisdict["brand"])
Ford

Unordered:
When we say that dictionaries are unordered, it means that the items does not have a defined order, you cannot refer to
an item by using an index.
Changeable
Dictionaries are changeable, meaning that we can change, add or remove items after the dictionary has been created.
Duplicates Not Allowed:
Dictionaries cannot have two items with the same key:
In [19]:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964,
"year": 2020
}
print(thisdict)
{'brand': 'Ford', 'model': 'Mustang', 'year': 2020}

Dictionary Length
To determine how many items a dictionary has, use the len() function:
In [4]:
print(len(thisdict))
3

Dictionary Items - Data Types


The values in dictionary items can be of any data type:
In [34]:
thisdict = {
"brand": "Ford",
"electric": False,
"year": 1964,
"colors": ["red", "white", "blue"]
}
In [35]:
print(thisdict)

271-CIS-3 Lab Manual - 2022 42


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

{'brand': 'Ford', 'electric': False, 'year': 1964, 'colors': ['red', 'white', 'blue']}

type():
From Python's perspective, dictionaries are defined as objects with the data type 'dict':
In [20]:
thisdict = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}
print(type(thisdict))
<class 'dict'>

Nested dictionary:
In [7]:
nestdic = {
"brand": {"Cars":"Ford","cloths":"LV","Shoes":"Nike"},
"model": "Mustang",
"year": 1964
}
print(nestdic)
{'brand': {'Cars': 'Ford', 'cloths': 'LV', 'Shoes': 'Nike'}, 'model': 'Mustang', 'year':
1964}

Insert new key and value:


In [21]:
nestdic ['Bags']="Guess"
In [22]:
print(nestdic)
{'brand': {'Cars': 'Ford', 'cloths': 'LV', 'Shoes': 'Nike'}, 'model': 'Mustang', 'year':
1964, 'Bags': 'Guess'}

271-CIS-3 Lab Manual - 2022 43


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [23]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

car.clear()

print(car)
{}
In [24]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.copy()

print(x)
{'brand': 'Ford', 'model': 'Mustang', 'year': 1964}
In [25]:
x = ('key1', 'key2', 'key3')
y = 0

thisdict = dict.fromkeys(x, y)

print(thisdict)
{'key1': 0, 'key2': 0, 'key3': 0}
In [26]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.get("model")

print(x)
Mustang
In [28]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.items()

print(x)
dict_items([('brand', 'Ford'), ('model', 'Mustang'), ('year', 1964)])
271-CIS-3 Lab Manual - 2022 44
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [15]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.keys()

print(x)
dict_keys(['brand', 'model', 'year'])
In [30]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.keys()

car["color"] = "white"

print(x)
dict_keys(['brand', 'model', 'year', 'color'])
In [32]:
car = {
"brand": "Ford",
"model": "Mustang",
"year": 1964
}

x = car.pop("model")

print(x)
Mustang
In [33]:
print(car)
{'brand': 'Ford', 'year': 1964}

271-CIS-3 Lab Manual - 2022 45


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-7 Python Statements: Iterative Structures, Conditional Structures

Conditions in Python
Comparison Operators
Comparison operations compare some value or operand and, based on a condition, they produce a Boolean. When
comparing two values you can use these operators:

• equal: ==
• not equal: !=
• greater than: >
• less than: <
• greater than or equal to: >=
• less than or equal to: <=

Let's assign a a value of 5. Use the equality operator denoted with two equal == signs to determine if two values are
equal. The case below compares the variable a with 6.
In [ ]:
# Condition Equal

a = 5
a == 6
The result is False, as 5 does not equal to 6.
Consider the following equality comparison operator i > 5. If the value of the left operand, in this case the variable i, is
greater than the value of the right operand, in this case 5, then the statement is True. Otherwise, the statement is False.
If i is equal to 6, because 6 is larger than 5, the output is True.
In [ ]:
# Greater than Sign

i = 6
i > 5
Set i = 2. The statement is false as 2 is not greater than 5:
In [ ]:
# Greater than Sign

i = 2
i > 5

271-CIS-3 Lab Manual - 2022 46


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Let's display some values for i in the figure. Set the values greater than 5 in green and the rest in red. The green region
represents where the condition is True, the red where the statement is False. If the value of i is 2, we get False as the 2
falls in the red region. Similarly, if the value for i is 6 we get a True as the condition falls in the green region.

The inequality test uses an exclamation mark preceding the equal sign, if two operands are not equal then the condition
becomes True. For example, the following condition will produce True as long as the value of i is not equal to 6:
In [ ]:
# Inequality Sign

i = 2
i != 6
When i equals 6 the inequality expression produces False.
In [ ]:
# Inequality Sign

i = 6
i != 6

271-CIS-3 Lab Manual - 2022 47


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

See the number line below. when the condition is True the corresponding numbers are marked in green and for where
the condition is False the corresponding number is marked in red. If we set i equal to 2 the operator is true as 2 is in the
green region. If we set i equal to 6, we get a False as the condition falls in the red region.

We can apply the same methods on strings. For example, use an equality operator on two different strings. As the strings
are not equal, we get a False.
In [ ]:
# Use Equality sign to compare the strings

"ACDC" == "Michael Jackson"


If we use the inequality operator, the output is going to be True as the strings are not equal.
In [ ]:
# Use Inequality sign to compare the strings

"ACDC" != "Michael Jackson"


Inequality operation is also used to compare the letters/words/symbols according to the ASCII value of letters. The
decimal value shown in the following table represents the order of the character:
For example, the ASCII code for ! is 21, while the ASCII code for + is 43. Therefore + is larger than ! as 43 is greater than
21.
Similarly, the value for A is 101, and the value for B is 102 therefore:
In [ ]:
# Compare characters

'B' > 'A'

271-CIS-3 Lab Manual - 2022 48


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

When there are multiple letters, the first letter takes precedence in ordering:
In [ ]:
# Compare characters

'BA' > 'AB'

Note: Upper Case Letters have different ASCII code than Lower Case Letters, which means the comparison between the
letters in python is case-sensitive.
Branching
Branching allows us to run different statements for different inputs. It is helpful to think of an if statement as a locked
room, if the statement is True we can enter the room and your program will run some predefined tasks, but if the
statement is False the program will ignore the task.
For example, consider the blue rectangle representing an ACDC concert. If the individual is older than 18, they can enter
the ACDC concert. If they are 18 or younger than 18 they cannot enter the concert.

Use the condition statements learned before as the conditions need to be checked in the if statement. The syntax is as
simple as if condition statement :, which contains a word if, any condition statement, and a colon at the end. Start your
tasks which need to be executed under this condition in a new line with an indent. The lines of code after the colon and
with an indent will only be executed when the if statement is True. The tasks will end when the line of code does not
contain the indent.

In the case below, the tasks executed print(“you can enter”) only occurs if the variable age is greater than 18 is a True
case because this line of code has the indent. However, the execution of print(“move on”) will not be influenced by the if
statement.
In [ ]:
# If statement example

#age = 19
age = 18

#expression that can be true or false


if age > 18:

#within an indent, we have the expression that is run if the condition is true
print("you can enter" )

#The statements after the if statement will run regardless if the condition is true or
false
print("move on")
Try uncommenting the age variable

271-CIS-3 Lab Manual - 2022 49


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

It is helpful to use the following diagram to illustrate the process. On the left side, we see what happens when the
condition is True. The person enters the ACDC concert representing the code in the indent being executed; they then
move on. On the right side, we see what happens when the condition is False; the person is not granted access, and the
person moves on. In this case, the segment of code in the indent does not run, but the rest of the statements are run.

The else statement runs a block of code if none of the conditions are True before this else statement. Let's use the ACDC
concert analogy again. If the user is 17 they cannot go to the ACDC concert, but they can go to the Meatloaf concert. The
syntax of the else statement is similar as the syntax of the if statement, as else :. Notice that, there is no condition
statement for else. Try changing the values of age to see what happens:
In [ ]:
# Else statement example

#age = 18
age = 19

if age > 18:


print("you can enter" )
else:
print("go see Meat Loaf" )

print("move on")

271-CIS-3 Lab Manual - 2022 50


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The process is demonstrated below, where each of the possibilities is illustrated on each side of the image. On the left is
the case where the age is 17, we set the variable age to 17, and this corresponds to the individual attending the Meatloaf
concert. The right portion shows what happens when the individual is over 18, in this case 19, and the individual is
granted access to the concert.

The elif statement, short for else if, allows us to check additional conditions if the condition statements before it
are False. If the condition for the elif statement is True, the alternate expressions will be run. Consider the concert
example, where if the individual is 18 they will go to the Pink Floyd concert instead of attending the ACDC or Meat-loaf
concert. The person of 18 years of age enters the area, and as they are not older than 18 they can not see ACDC, but as
they are 18 years of age, they attend Pink Floyd. After seeing Pink Floyd, they move on. The syntax of the elif statement is
similar in that we merely change the if in if statement to elif.
In [ ]:
# Elif statment example

age = 18

if age > 18:


print("you can enter" )
elif age == 18:
print("go see Pink Floyd")
else:
print("go see Meat Loaf" )

print("move on")

271-CIS-3 Lab Manual - 2022 51


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The three combinations are shown in the figure below. The left-most region shows what happens when the individual is
less than 18 years of age. The central component shows when the individual is exactly 18. The rightmost shows when
the individual is over 18.

Look at the following code:


In [ ]:
# Condition statement example

album_year = 1983
album_year = 1970

if album_year > 1980:


print("Album year is greater than 1980")

print('do something..')
Feel free to change album_year value to other values -- you'll see that the result changes!
Notice that the code in the above indented block will only be executed if the results are True.
As before, we can add an else block to the if block. The code in the else block will only be executed if the result is False.

Syntax:

if (condition):

# do something

else:

# do something else

271-CIS-3 Lab Manual - 2022 52


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

If the condition in the if statement is False, the statement after the else block will execute. This is demonstrated in the
figure:

In [ ]:
# Condition statement example

#album_year = 1983
album_year = 1970

if album_year > 1980:


print("Album year is greater than 1980")
else:
print("less than 1980")

print('do something..')
Feel free to change the album_year value to other values -- you'll see that the result changes based on it!

271-CIS-3 Lab Manual - 2022 53


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Logical operators
Sometimes you want to check more than one condition at once. For example, you might want to check if one condition
and another condition is True. Logical operators allow you to combine or modify conditions.

• and
• or
• not

These operators are summarized for two variables using the following truth tables:

The and statement is only True when both conditions are true. The or statement is true if one condition is True.
The not statement outputs the opposite truth value.

271-CIS-3 Lab Manual - 2022 54


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Let's see how to determine if an album was released after 1979 (1979 is not included) and before 1990 (1990 is not
included). The time periods between 1980 and 1989 satisfy this condition. This is demonstrated in the figure below. The
green on lines a and b represents periods where the statement is True. The green on line c represents where both
conditions are True, this corresponds to where the green regions overlap.

The block of code to perform this check is given by:


In [ ]:
# Condition statement example

album_year = 1980
if(album_year > 1979) and (
album_year < 1990):
print ("Album year was in between 1980 and 1989")

print("")
print("Do Stuff..")

To determine if an album was released before 1980 (~ - 1979) or after 1989 (1990 - ~), an or statement can be used.
Periods before 1980 (~ - 1979) or after 1989 (1990 - ~) satisfy this condition. This is demonstrated in the following
figure, the color green in a and b represents periods where the statement is true. The color green in c represents where
at least one of the conditions are true.

271-CIS-3 Lab Manual - 2022 55


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The block of code to perform this check is given by:


In [ ]:
# Condition statement example

album_year = 1990

if(album_year < 1980) or (album_year > 1989):


print ("Album was not made in the 1980's")
else:
print("The Album was made in the 1980's ")
The not statement checks if the statement is false:
In [ ]:
# Condition statement example

album_year = 1983

if not (album_year == '1984'):


print ("Album year is not 1984")

271-CIS-3 Lab Manual - 2022 56


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-8 Python Statements: Iterative Structures, Conditional Structures (cont.)

Loops in Python
Range
Sometimes, you might want to repeat a given operation many times. Repeated executions like this are performed
by loops. We will look at two types of loops, for loops and while loops.

Before we discuss loops lets discuss the range object. It is helpful to think of the range object as an ordered list. For now,
let's look at the simplest case. If we would like to generate a sequence that contains three elements ordered from 0 to 2
we simply use the following command:
In [ ]:
# Use the range

range(3)

What is for loop?


The for loop enables you to execute a code block multiple times. For example, you would use this if you would like to
print out every element in a list.
Let's try to use a for loop to print all the years presented in the list dates:
This can be done as follows:
In [ ]:
# For loop example

dates = [1982,1980,1973]
N = len(dates)

for i in range(N):
print(dates[i])
In [ ]:
print(dates[0])
print(dates[1])
print(dates[2])

271-CIS-3 Lab Manual - 2022 57


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The code in the indent is executed N times, each time the value of i is increased by 1 for every execution. The statement
executed is to print out the value in the list at index i as shown here:

In [ ]:
range(0,8)

In this example we can print out a sequence of numbers from 0 to 7:


In [ ]:
# Example of for loop

for i in range(2, 8):


print(i)

In Python we can directly access the elements in the list as follows:


In [ ]:
# Exmaple of for loop, loop through list

for year in dates:


print(year)

271-CIS-3 Lab Manual - 2022 58


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

For each iteration, the value of the variable years behaves like the value of dates[i] in the first example:

We can change the elements in a list:


In [ ]:
# Use for loop to change the elements in list

squares = ['red', 'yellow', 'green', 'purple', 'blue']

for i in range(0, 5):


print("Before square ", i, 'is', squares[i])
squares[i] = 'weight'
print("After square ", i, 'is', squares[i])
We can access the index and the elements of a list as follows:
In [13]:
# Loop through the list and iterate on both index and element value

squares=['red', 'yellow', 'green', 'purple', 'blue']

for i, square in enumerate(squares):


print(i, square)
0 red
1 yellow
2 green
3 purple
4 blue

271-CIS-3 Lab Manual - 2022 59


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

What is while loop?


As you can see, the for loop is used for a controlled flow of repetition. However, what if we don't know when we want to
stop the loop? What if we want to keep executing a code block until a certain condition is met? The while loop exists as a
tool for repeated execution based on a condition. The code block will keep being executed until the given logical
condition returns a False boolean value.
Let’s say we would like to iterate through list dates and stop at the year 1973, then print out the number of iterations.
This can be done with the following block of code:
In [15]:
# While Loop Example

dates = [1982, 1980, 1973, 2000]

i = 0
year = 0

while(year != 1973):
year = dates[i]
i = i + 2
print(year)

print("It took ", i ,"repetitions to get out of loop.")


1982
1973
It took 4 repetitions to get out of loop.
A while loop iterates merely until the condition in the argument is not met, as shown in the following figure:

271-CIS-3 Lab Manual - 2022 60


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-9 Scope, Functions

Functions in Python

A function is a reusable block of code which performs operations specified in the function. They let you break down
tasks and allow you to reuse your code in different programs.

There are two types of functions :

• Pre-defined functions
• User defined functions

What is a Function?
You can define functions to provide the required functionality. Here are simple rules to define a function in Python:

• Functions blocks begin def followed by the function name and parentheses ().
• There are input parameters or arguments that should be placed within these parentheses.
• You can also define parameters inside these parentheses.
• There is a body within every function that starts with a colon (:) and is indented.
• You can also place documentation before the body
• The statement return exits a function, optionally passing back a value

An example of a function that adds on to the parameter a prints and returns the output as b:
In [1]:
# First function example: Add 1 to a and store as b

def add(a):
b = a + 1
print(a, "if you add one", b)
return(b)
The figure below illustrates the terminology:

271-CIS-3 Lab Manual - 2022 61


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can obtain help about a function :


In [2]:
# Get a help on add function

help(add)
Help on function add in module __main__:

add(a)

We can call the function:


In [3]:
# Call the function add()

add(1)
1 if you add one 2
Out[3]:
2
If we call the function with a new input we get a new result:
In [4]:
# Call the function add()

add(2)
2 if you add one 3
Out[4]:
3
We can create different functions. For example, we can create a function that multiplies two numbers. The numbers will
be represented by the variables a and b:
In [6]:
# Define a function for multiple two numbers

def Mult(a, b):


c = a * b
return(c)
The same function can be used for different data types. For example, we can multiply two integers:
In [7]:
# Use mult() multiply two integers

Mult(2, 3)
Out[7]:
6
Two Floats:
In [8]:
# Use mult() multiply two floats

Mult(10.0, 3.14)
Out[8]:
31.400000000000002
We can even replicate a string by multiplying with an integer:

271-CIS-3 Lab Manual - 2022 62


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [ ]:
# Use mult() multiply two different type values together

Mult(2, "Michael Jackson ")

Variables
The input to a function is called a formal parameter.

A variable that is declared inside a function is called a local variable. The parameter only exists within the function (i.e.
the point where the function starts and stops).

A variable that is declared outside a function definition is a global variable, and its value is accessible and modifiable
throughout the program. We will discuss more about global variables at the end of the lab.
In [11]:
# Function Definition

def square(a):

# Local variable b
b = 10
c = a * a + b
print(a, "if you square + 1", c)
return(c)
The labels are displayed in the figure:

271-CIS-3 Lab Manual - 2022 63


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can call the function with an input of 3:


In [12]:
# Initializes Global variable

x = 3
# Makes function call and return function a y
y = square(x)
y
3 if you square + 1 19
Out[12]:
19

We can call the function with an input of 2 in a different manner:


In [ ]:
# Directly enter a number as parameter

square(2)
If there is no return statement, the function returns None. The following two functions are equivalent:
In [13]:
# Define functions, one with return value None and other without return value

def MJ():
print('Michael Jackson')

def MJ1():
print('Michael Jackson')
return(None)
In [14]:
# See the output

MJ()
Michael Jackson
In [15]:
# See the output

MJ1()
Michael Jackson

Printing the function after a call reveals a None is the default return statement:
In [16]:
# See what functions returns are

print(MJ())
print(MJ1())
Michael Jackson
None
Michael Jackson
None

271-CIS-3 Lab Manual - 2022 64


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Create a function con that concatenates two strings using the addition operation:
In [18]:
# Define the function for combining strings

def con(a, b):


return(a + b)
In [19]:
# Test on the con() function

con("This ", "is")


Out[19]:
'This is'

Functions Make Things Simple


Consider the two lines of code in Block 1 and Block 2: the procedure for each block is identical. The only thing that is
different is the variable names and values.

Block 1:

In [20]:
# a and b calculation block1

a1 = 4
b1 = 5
c1 = a1 + b1 + 2 * a1 * b1 - 1
if(c1 < 0):
c1 = 0
else:
c1 = 5
c1
Out[20]:
5

Block 2:

In [21]:
# a and b calculation block2

a2 = 0
b2 = 0
c2 = a2 + b2 + 2 * a2 * b2 - 1
if(c2 < 0):
c2 = 0
else:
c2 = 5
c2
Out[21]:
0

271-CIS-3 Lab Manual - 2022 65


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We can replace the lines of code with a function. A function combines many instructions into a single line of code. Once
a function is defined, it can be used repeatedly. You can invoke the same function many times in your program. You can
save your function and use it in another program or use someone else’s function. The lines of code in code Block 1 and
code Block 2 can be replaced by the following function:
In [22]:
# Make a Function for the calculation above

def Equation(a,b):
c = a + b + 2 * a * b - 1
if(c < 0):
c = 0
else:
c = 5
return(c)

This function takes two inputs, a and b, then applies several operations to return c. We simply define the function,
replace the instructions with the function, and input the new values of a1, b1 and a2, b2 as inputs. The entire process is
demonstrated in the figure:

Code Blocks 1 and Block 2 can now be replaced with code Block 3 and code Block 4.

Block 3:

In [ ]:
a1 = 4
b1 = 5
c1 = Equation(a1, b1)
c1

271-CIS-3 Lab Manual - 2022 66


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Block 4:

In [ ]:
a2 = 0
b2 = 0
c2 = Equation(a2, b2)
c2

Pre-defined functions
There are many pre-defined functions in Python, so let's start with the simple ones.
The print() function:
In [ ]:
# Build-in function print()

album_ratings = [10.0, 8.5, 9.5, 7.0, 7.0, 9.5, 9.0, 9.5]


print(album_ratings)
The sum() function adds all the elements in a list or tuple:
In [ ]:
# Use sum() to add every element in a list or tuple together

sum(album_ratings)
The len() function returns the length of a list or tuple:
In [ ]:
# Show the length of the list or tuple

len(album_ratings)

Using if/else Statements and Loops in Functions


The return() function is particularly useful if you have any IF statements in the function, when you want your output to
be dependent on some condition:
In [ ]:
# Function example

def type_of_album(artist, album, year_released):

print(artist, album, year_released)


if year_released > 1980:
return "Modern"
else:
return "Oldie"

x = type_of_album("Michael Jackson", "Thriller", 1980)


print(x)
We can use a loop in a function. For example, we can print out each element in a list:
In [ ]:
# Print the list using for loop

271-CIS-3 Lab Manual - 2022 67


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

def PrintList(the_list):
for element in the_list:
print(element)
In [ ]:
# Implement the printlist function

PrintList(['1', 1, 'the man', "abc"])

Setting default argument values in your custom functions


You can set a default value for arguments in your function. For example, in the isGoodRating() function, what if we
wanted to create a threshold for what we consider to be a good rating? Perhaps by default, we should have a default
rating of 4:
In [23]:
# Example for setting param with default value

def isGoodRating(rating=4):
if(rating < 7):
print("this album sucks it's rating is",rating)

else:
print("this album is good its rating is",rating)
In [24]:
# Test the value with default value and with input

isGoodRating()
isGoodRating(10)
this album sucks it's rating is 4
this album is good its rating is 10

271-CIS-3 Lab Manual - 2022 68


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-10 Scope, Functions (cont.)

Global variables
So far, we've been creating variables within functions, but we have not discussed variables outside the function. These
are called global variables.
Let's try to see what printer1 returns:
In [25]:
# Example of global variable

artist = "Michael Jackson"


def printer1(artist):
internal_var = artist
print(artist, "is an artist")

printer1(artist)
Michael Jackson is an artist
In [27]:
artist
Out[27]:
'Michael Jackson'
If we print internal_var we get an error.
We got a Name Error: name 'internal_var' is not defined. Why?

It's because all the variables we create in the function is a local variable, meaning that the variable assignment does not
persist outside the function.

But there is a way to create global variables from within a function as follows:
In [28]:
artist = "Michael Jackson"

def printer(artist):
global internal_var
internal_var= "Whitney Houston"
print(artist,"is an artist")

printer(artist)
printer(internal_var)
Michael Jackson is an artist
Whitney Houston is an artist
In [29]:
internal_var
Out[29]:
'Whitney Houston'

271-CIS-3 Lab Manual - 2022 69


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Scope of a Variable
The scope of a variable is the part of that program where that variable is accessible. Variables that are declared outside
of all function definitions, such as the myFavouriteBand variable in the code shown here, are accessible from anywhere
within the program. As a result, such variables are said to have global scope, and are known as global
variables. myFavouriteBand is a global variable, so it is accessible from within the getBandRating function, and we can use
it to determine a band's rating. We can also use it outside of the function, such as when we pass it to the print function to
display it:
In [30]:
# Example of global variable

myFavouriteBand = "AC/DC"

def getBandRating(bandname):
if bandname == myFavouriteBand:
return 10.0
else:
return 0.0

print("AC/DC's rating is:", getBandRating("AC/DC"))


print("Deep Purple's rating is:",getBandRating("Deep Purple"))
print("My favourite band is:", myFavouriteBand)
AC/DC's rating is: 10.0
Deep Purple's rating is: 0.0
My favourite band is: AC/DC

Take a look at this modified version of our code. Now the myFavouriteBand variable is defined within
the getBandRating function. A variable that is defined within a function is said to be a local variable of that function. That
means that it is only accessible from within the function in which it is defined. Our getBandRating function will still work,
because myFavouriteBand is still defined within the function. However, we can no longer print myFavouriteBand outside
our function, because it is a local variable of our getBandRating function; it is only defined within
the getBandRating function:
In [31]:
# Example of local variable

def getBandRating(bandname):
myFavouriteBand = "AC/DC"
if bandname == myFavouriteBand:
return 10.0
else:
return 0.0

print("AC/DC's rating is: ", getBandRating("AC/DC"))


print("Deep Purple's rating is: ", getBandRating("Deep Purple"))
print("My favourite band is", myFavouriteBand)
AC/DC's rating is: 10.0
Deep Purple's rating is: 0.0
My favourite band is AC/DC

271-CIS-3 Lab Manual - 2022 70


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Finally, take a look at this example. We now have two myFavouriteBand variable definitions. The first one of these has a
global scope, and the second of them is a local variable within the getBandRating function. Within
the getBandRating function, the local variable takes precedence. Deep Purple will receive a rating of 10.0 when passed
to the getBandRating function. However, outside of the getBandRating function, the getBandRating s local variable is not
defined, so the myFavouriteBand variable we print is the global variable, which has a value of AC/DC:
In [32]:
# Example of global variable and local variable with the same name

myFavouriteBand = "AC/DC"

def getBandRating(bandname):
myFavouriteBand = "Deep Purple"
if bandname == myFavouriteBand:
return 10.0
else:
return 0.0

print("AC/DC's rating is:",getBandRating("AC/DC"))


print("Deep Purple's rating is: ",getBandRating("Deep Purple"))
print("My favourite band is:",myFavouriteBand)
AC/DC's rating is: 0.0
Deep Purple's rating is: 10.0
My favourite band is: AC/DC

271-CIS-3 Lab Manual - 2022 71


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-11 Modules and Packages

Python Modules
What is a Module?
Consider a module to be the same as a code library. A file containing a set of functions you want to include in your
application.

Create a Module
To define a module, simply use your text editor to type some Python code into a text file, and save it with a “.py”
extension; any such file is automatically considered a Python module.

as here we create file name firstModule and write the code which we want on it

the code is:

def greeting(name): print("Hello, " + name)

Use a Module
Now we can use the module we just created, by using the import statement:
For instance, if you type the following def into a file called module1.py and import it, you create a module object with
one attribute—the name printer, which happens to be a reference to a function object:

The import Statement


In the first example, the name module1 serves two different purposes: it identifies an external file to be loaded, and it
becomes a variable in the script, which references the module object after the file is loaded:
In [ ]:
import module1 # Get module as a whole (one or more)
module1.printer('Hello world!') # Qualify to get names

The from Statement


By contrast, because from copies specific names from one file over to another scope, it allows us to use the copied names
directly in the script without going through the module (e.g., printer):
In [ ]:
from module1 import printer # Copy out a variable (one or more)
printer('Hello world!') # No need to qualify name

This form of from allows us to list one or more names to be copied out, separated by commas.
In [ ]:

271-CIS-3 Lab Manual - 2022 72


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The from * Statement


Finally, the next example uses a special form of from: when we use a * instead of specific names, we get copies of all
names assigned at the top level of the referenced module. Here again, we can then use the copied name printer in our
script without going through the module name:
In [ ]:
from module1 import * # Copy out _all_ variables
printer('Hello world!')
In [ ]:
from module1 import * # Copy out _all_ variables
printer('New live')
printer(2)

Re-naming a Module
You can create an alias when you import a module, by using the as keyword:
In [ ]:
import module1 as m
m.printer('Hello world!')
In [ ]:

Built-in Modules
There are several built-in modules in Python, which you can import whenever you like. Import and use the platform
module:
In [ ]:
import platform

x = platform.system()
print(x)

Using the dir() Function


There is a built-in function to list all the function names (or variable names) in a module. The dir() function:
In [ ]:
import platform

x = dir(platform)
print(x)

271-CIS-3 Lab Manual - 2022 73


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Example
In [ ]:
from small import x, y # Copy two names out
x = 42 # Changes local x only
y[0] = 42

print (x)
print(y)

Import From Module


You can choose to import only parts from a module, by using the from keyword.
In [ ]:
import greeting1 as G

G.greeting("Jonathan",25,"USA")
In [ ]:
from greeting1 import person1

print (person1["age"])
In [ ]:

Note:
When importing using the from keyword, do not use the module name when referring to elements in the module.
Example: person1["age"], not mymodule.person1["age"]
In [ ]:

271-CIS-3 Lab Manual - 2022 74


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-12 Modules and Packages (cont.)

Packages
Python has packages for directories and modules for files.
A Python package can have sub-packages and modules.

A directory
must contain a file named __init__.py in order for Python to consider it as a package. This file can be left
empty but we generally place the initialization code for that package in this file.
Example: Suppose we are developing a game. One possible organization of packages and modules could
be as shown in the figure below.

271-CIS-3 Lab Manual - 2022 75


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Importing module from a package


We can import modules from packages using the dot (.) operator.
For example, if we want to import the start module in the above example, it can be done as follows:

import Game.Level.start
Practical Example:
1* Create floder inside your folder name it as MyApp

2* go inside Packages inside and create the __init__.py file (any name for it)

3* Also create two Module:

First module name is <b> greeting.py </b> inside it write :

def SayHello(name):

print("Hello ", name)

Second module name is <b> Functions.py </b> inside it write :

def sum(x,y):

return x+y

def average(x,y):

return (x+y)/2

def power(x,y):

return x**y

271-CIS-3 Lab Manual - 2022 76


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [1]:
import MyApp.mypackage.greeting as M
In [2]:
M.SayHello("I'm KKU CS Student")
Hello I'm KKU CS Student
In [5]:
import MyApp.mypackage.Functions as f
f.power(1,2)
Out[5]:
1
In [ ]:

__init__.py
The package folder contains a special file called init.py, which stores the package's content. It serves two
purposes:

*The Python interpreter recognizes a folder as the package if it contains__init__.py file.

* __init__.py exposes specified resources from its modules to be imported.

An empty __init__.py file makes all functions from the above modules available when this package is imported.

Note that __init__.py is essential for the folder to be recognized by Python as a package. You can optionally define
functions from individual modules to be made available

The __init__.py file is normally kept empty.

271-CIS-3 Lab Manual - 2022 77


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [9]:
import MyApp.mypackage.Functions as f
f.power(2,3)
Out[9]:
8
In [10]:
from MyApp.mypackage.Functions import power
from MyApp.mypackage.greeting import SayHello
SayHello("Hello")
x=power(3,2)
print("power(3,2) : ", x)
power(2,3)
Hello Hello
power(3,2) : 9
Out[10]:
8

271-CIS-3 Lab Manual - 2022 78


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-13 Object Oriented Programming

Object-Oriented programming is a widely used concept to write powerful applications. As a data


scientist, you will be required to write applications to process your data, among a range of other things.
In this tutorial, you will discover the basics of object-oriented programming in Python.

OOP: Introduction

Object-oriented programming has some advantages over other design patterns. Development is faster
and cheaper, with better software maintainability. This, in turn, leads to higher-quality software, which is
also extensible with new methods and attributes. The learning curve is, however, steeper. The concept
may be too complex for beginners. Computationally, OOP software is slower, and uses more memory
since more lines of code have to be written.

Object-oriented programming is based on the imperative programming paradigm, which uses statements
to change a program's state. It focuses on describing how a program should operate. Examples of
imperative programming languages are C, C++, Java, Go, Ruby and Python. This stands in contrast to
declarative programming, which focuses on what the computer program should accomplish, without
specifying how. Examples are database query languages like SQL and XQuery, where one only tells the
computer what data to query from where, but now how to do it.

OOP uses the concept of objects and classes. A class can be thought of as a 'blueprint' for objects. These
can have their own attributes (characteristics they possess), and methods (actions they perform).

OOP Example

An example of a class is the class Dog. Don't think of it as a specific dog, or your own dog. We're
describing what a dog is and can do, in general. Dogs usually have a name and age; these are instance
attributes. Dogs can also bark; this is a method.

271-CIS-3 Lab Manual - 2022 79


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

When you talk about a specific dog, you would have an object in programming: an object is an
instantiation of a class. This is the basic principle on which object-oriented programming is based. So my
dog Ozzy, for example, belongs to the class Dog. His attributes are name = 'Ozzy' and age = '2'. A
different dog will have different attributes.

OOP in Python

Python is a great programming language that supports OOP. You will use it to define a class with
attributes and methods, which you will then call. Python offers a number of benefits compared to other
programming languages like Java, C++ or R. It's a dynamic language, with high-level data types. This
means that development happens much faster than with Java or C++. It does not require the programmer
to declare types of variables and arguments. This also makes Python easier to understand and learn for
beginners, its code being more readable and intuitive.

How to create a class

To define a class in Python, you can use the class keyword, followed by the class name and a colon.
Inside the class, an __init__ method has to be defined with def. This is the initializer that you can later
use to instantiate objects. It's similar to a constructor in Java. __init__ must always be present! It takes
one argument: self, which refers to the object itself. Inside the method, the pass keyword is used as of
now, because Python expects you to type something there. Remember to use correct indentation!

class Dog:

def __init__(self):
pass

Note: self in Python is equivalent to this in C++ or Java.

271-CIS-3 Lab Manual - 2022 80


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In this case, you have a (mostly empty) Dog class, but no object yet. Let's create one!

Instantiating objects

To instantiate an object, type the class name, followed by two brackets. You can assign this to a variable
to keep track of the object.

ozzy = Dog()

And print it:


print(ozzy)
<__main__.Dog object at 0x111f47278>

Adding attributes to a class

After printing ozzy, it is clear that this object is a dog. But you haven't added any attributes yet. Let's give
the Dog class a name and age, by rewriting it:
class Dog:

def __init__(self, name, age):


self.name = name
self.age = age

You can see that the function now takes two arguments after self: name and age. These then get
assigned to self.name and self.age respectively. You can now now create a new ozzy object, with a
name and age:
ozzy = Dog("Ozzy", 2)

271-CIS-3 Lab Manual - 2022 81


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

To access an object's attributes in Python, you can use the dot notation. This is done by typing the name
of the object, followed by a dot and the attribute's name.
print(ozzy.name)

print(ozzy.age)
Ozzy
2

This can also be combined in a more elaborate sentence:


print(ozzy.name + " is " + str(ozzy.age) + " year(s) old.")
Ozzy is 2 year(s) old.

The str() function is used here to convert the age attribute, which is an integer, to a string, so you can
use it in the print() function.

Define methods in a class

Now that you have aDog class, it does have a name and age which you can keep track of, but it doesn't
actually do anything. This is where instance methods come in. You can rewrite the class to now include
a bark() method. Notice how the def keyword is used again, as well as the self argument.
class Dog:

def __init__(self, name, age):


self.name = name
self.age = age

def bark(self):
print("bark bark!")

The bark method can now be called using the dot notation, after instantiating a new ozzy object. The
method should print "bark bark!" to the screen. Notice the parentheses (curly brackets) in .bark().
These are always used when calling a method. They're empty in this case, since the bark() method does
not take any arguments.

271-CIS-3 Lab Manual - 2022 82


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

ozzy = Dog("Ozzy", 2)

ozzy.bark()
bark bark!

Recall how you printed ozzy earlier? The code below now implements this functionality in the Dog class,
with the doginfo() method. You then instantiate some objects with different properties, and call the
method on them.
class Dog:

def __init__(self, name, age):


self.name = name
self.age = age

def bark(self):
print("bark bark!")

def doginfo(self):
print(self.name + " is " + str(self.age) + " year(s) old.")
ozzy = Dog("Ozzy", 2)
skippy = Dog("Skippy", 12)
filou = Dog("Filou", 8)
ozzy.doginfo()
skippy.doginfo()
filou.doginfo()
Ozzy is 2 year(s) old.
Skippy is 12 year(s) old.
Filou is 8 year(s) old.

As you can see, you can call the doginfo() method on objects with the dot notation. The response now
depends on which Dog object you are calling the method on.

271-CIS-3 Lab Manual - 2022 83


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Since dogs get older, it would be nice if you could adjust their age accordingly. Ozzy just turned 3, so let's
change his age.
ozzy.age = 3
print(ozzy.age)
3

It's as easy as assigning a new value to the attribute. You could also implement this as
a birthday() method in the Dog class:
class Dog:

def __init__(self, name, age):


self.name = name
self.age = age

def bark(self):
print("bark bark!")

def doginfo(self):
print(self.name + " is " + str(self.age) + " year(s) old.")

def birthday(self):
self.age +=1
ozzy = Dog("Ozzy", 2)
print(ozzy.age)
2
ozzy.birthday()
print(ozzy.age)
3

Now, you don't need to manually change the dog's age. whenever it is its birthday, you can just call
the birthday() method.

271-CIS-3 Lab Manual - 2022 84


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Passing arguments to methods

You would like for our dogs to have a buddy. This should be optional, since not all dogs are as sociable.
Take a look at the setBuddy() method below. It takes self, as per usual, and buddy as arguments. In
this case, buddy will be another Dog object. Set the self.buddy attribute to buddy, and
the buddy.buddy attribute to self. This means that the relationship is reciprocal; you are your buddy's
buddy. In this case, Filou will be Ozzy's buddy, which means that Ozzy automatically becomes Filou's
buddy. You could also set these attributes manually, instead of defining a method, but that would require
more work (writing 2 lines of code instead of 1) every time you want to set a buddy. Notice that in Python,
you don't need to specify of what type the argument is. If this were Java, it would be required.

class Dog:

def __init__(self, name, age):


self.name = name
self.age = age

def bark(self):
print("bark bark!")

def doginfo(self):
print(self.name + " is " + str(self.age) + " year(s) old.")

def birthday(self):
self.age +=1

def setBuddy(self, buddy):


self.buddy = buddy
buddy.buddy = self

271-CIS-3 Lab Manual - 2022 85


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

You can now call the method with the dot notation, and pass it another Dog object. In this case, Ozzy's
buddy will be Filou:
ozzy = Dog("Ozzy", 2)
filou = Dog("Filou", 8)

ozzy.setBuddy(filou)

If you now want to get some information about Ozzy's buddy, you can use the dot notation twice:. First,
to refer to Ozzy's buddy, and a second time to refer to its attribute.
print(ozzy.buddy.name)
print(ozzy.buddy.age)
Filou
8

Notice how this can also be done for Filou.


print(filou.buddy.name)
print(filou.buddy.age)
Ozzy
2

The buddy's methods can also be called. The self argument that gets passed to doginfo() is
now ozzy.buddy, which is filou.
ozzy.buddy.doginfo()
Filou is 8 year(s) old.

271-CIS-3 Lab Manual - 2022 86


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-14 Object Oriented Programming (cont.)

PYTHON OBJECTS AND CLASSES

Object-oriented programming (OOP) is a method of structuring a program by bundling related properties and behaviors
into individual objects. In this tutorial, you’ll learn the basics of object-oriented programming in Python.

objects are like the components of a system. Think of a program as a factory assembly line of sorts. At each step of the
assembly line a system component processes some material, ultimately transforming raw material into a finished
product.

An object contains data, like the raw or preprocessed materials at each step:

Create a class, which is like a blueprint for creating an object Use classes to create new objects Model systems with class
inheritance

you learned how to:

*Define a class, which is a sort of blueprint for an object

*Instantiate an object from a class

*Use attributes and methods to define the properties and behaviors of an object

*Use inheritance to create child classes from a parent class

*Reference a method on a parent class using super()

*Check if an object inherits from another class using isinstance()

271-CIS-3 Lab Manual - 2022 87


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Define class in python


classes are just a way to define new sorts of stuff, reflecting real objects in a program’s domain.
Classes and Instances
Although they are technically two separate object types in the Python model, the classes and instances we put in these
trees are almost identical— The primary difference between classes and instances is that classes are a kind of factory
for generating instances. For example, in a realistic application, we might have an Employee class that defines what it
means to be an employee; from that class, we generate actual Employee instances. The another difference
between classes and modules — we only ever have one instance of a given module in memory (that’s why we have to
reload a module to get its new code), but with classes, we can make as many instances as we need.
Operationally, classes will usually have functions attached to them , and the instances will have more basic data items
used by the class’s functions.

How to Define a Class


Create a function. Functions do specific things, classes are specific things.
Classes often have methods, which are functions that are associated with a particular class, and do things associated
with the thing that the class is - but if all you want is to do something, a function is all you need.

Essentially, a class is a way of grouping functions (as methods) and data (as properties) into a logical unit revolving
around a certain kind of thing. If you don't need that grouping, there's no need to make a class. All class definitions start
with the class keyword, which is followed by the name of the class and a colon. Any code that is indented below the class
definition is considered part of the class’s body.

Here’s an example of a Dog class:


In [ ]:
class Dog:
pass

Note:
Python class names are written in CapitalizedWords notation by convention. For example, a class for a specific
breed of dog like the Jack Russell Terrier would be written as JackRussellTerrier.

The properties that all Dog objects must have are defined in a method called .__init__(). Every time a new Dog object
is created, .__init__() sets the initial state of the object by assigning the values of the object’s properties. That is,
.__init__() initializes each new instance of the class.

You can give .__init__() any number of parameters, but the first parameter will always be a variable called self.
When a new class instance is created, the instance is automatically passed to the self parameter in .__init__() so that
new attributes can be defined on the object.

271-CIS-3 Lab Manual - 2022 88


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Let’s update the Dog class with an .__init__() method that creates .name and .age attributes:
In [ ]:
class Dog:
def __init__(self, name, age):
self.name = name
self.age = age

Notice that the .__init__() method’s signature is indented four spaces. The body of the method is indented by eight
spaces. This indentation is vitally important. It tells Python that the .__init__() method belongs to the Dog class.

In the body of .__init__(), there are two statements using the self variable:

self.name = name creates an attribute called name and assigns to it the value of the name parameter.

self.age = age creates an attribute called age and assigns to it the value of the age parameter.

Attributes created in .__init__() are called instance attributes. An instance attribute’s value is specific to a particular
instance of the class. All Dog objects have a name and an age, but the values for the name and age attributes will
vary depending on the Dog instance.

On the other hand, class attributes are attributes that have the same value for all class instances. You can define a
class attribute by assigning a value to a variable name outside of .__init__().

For example, the following Dog class has a class attribute called species with the value "Canis familiaris":
In [ ]:

271-CIS-3 Lab Manual - 2022 89


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

class Dog:
# Class attribute
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age
They must always be assigned an initial value. When an instance of the class is created, class attributes are automatically
created and assigned to their initial values.

Use class attributes to define properties that should have the same value for every class instance. Use instance attributes
for properties that vary from one instance to another.
Creating a new object from a class is called instantiating an object. You can instantiate a new Dog object by
typing the name of the class, followed by opening and closing parentheses
In [ ]:
buddy = Dog("Buddy", 9)
miles = Dog("Miles", 4)
The Dog class’s .init() method has three parameters, so why are only two arguments passed to it in the example?

When you instantiate a Dog object, Python creates a new instance and passes it to the first parameter of .init(). This
essentially removes the self parameter, so you only need to worry about the name and age parameters.

After you create the Dog instances, you can access their instance attributes using dot notation:
In [ ]:
buddy.name
In [ ]:
miles.name
In [ ]:
#access class attribute
buddy.species
In [ ]:
#you can change the passed values any time you want
buddy.age
In [ ]:
buddy.age=5
In [ ]:
buddy.age

271-CIS-3 Lab Manual - 2022 90


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Instance Methods

Instance methods are functions that are defined inside a class and can only be called from an instance of that class.
Just like .__init__(), an instance method’s first parameter is always self.

type in the following Dog class:


In [ ]:
class Dog:
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age

# Instance method
def description(self):
#return f"{self.name} is {self.age} years old"
return self.name , self.age

# Another instance method


def speak(self, sound):
return f"{self.name} says {sound}"

This Dog class has two instance methods:

.description() returns a string displaying the name and age of the dog.

.speak() has one parameter called sound and returns a string containing the dog’s name and the sound the dog
makes.
In [ ]:
Dog1 = Dog("mile",4)

Dog1.description()
In [ ]:
Dog1.speak("Woof Woof")
In [ ]:
Dog1.speak("Bow Wow")

271-CIS-3 Lab Manual - 2022 91


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

in the above Dog class, .description() returns a string containing information about the Dog instance miles. When writing
your own classes, it’s a good idea to have a method that returns a string containing useful information about an instance
of the class. However, .description() isn’t the most Pythonic way of doing this.

you can use print() Let’s see what happens when you print() the miles object
In [ ]:
print(miles)

When you print(miles), you get a <b>cryptic looking message telling you that miles is a Dog object at the memory
address 0x00aeff70</b>. This message isn’t very helpful. You can change what gets printed by defining a special
instance method called .__str__().

In the editor window, change the name of the Dog class’s .description() method to .__str__():
In [ ]:
class Dog:
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age

# Instance method
def __str__(self):
return f"{self.name} is {self.age} years old"

# Another instance method


def speak(self, sound):
return f"{self.name} says {sound}"
In [ ]:
miles = Dog("Miles", 4)
print(miles)
In [ ]:

• __init__ is run when a new instance object is created

• __add__ is run when a new instance appears in old + expression.

• __str__ is run when an object is printed


In [ ]:

271-CIS-3 Lab Manual - 2022 92


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

class Dog:
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age

# Instance method
def __str__(self):
return f"{self.name} is {self.age} years old"

def __add__(self, other):


return self.name + other

# Another instance method


def speak(self, sound):
return f"{self.name} says {sound}"
In [ ]:
newdog= Dog("Carlos",7)
print(newdog)

b= newdog +' Nice' # __add__: makes a new instance


print(b)

Check Your Understanding

Create a Car class with two instance attributes:

1- .color, which stores the name of the car’s color as a string

2- .mileage, which stores the number of miles on the car as an integer

Then instantiate two Car objects:

1- blue car with 20,000 miles

2- red car with 30,000 miles—

and print out their colors and mileage.

271-CIS-3 Lab Manual - 2022 93


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The blue car has 20,000 miles.

The red car has 30,000 miles.


In [ ]:
class Car:

# initializer / instance attributes


def __init__(self, color, mileage):
self.color = color
self.mileage = mileage

# method 1
def showDescription(self):
print("Color of the car:\n",
self.color,"\nMileage of the car\n"
,self.mileage, "Mileage")
In [ ]:
blue_car = Car('Blue', 20000)

# call method 1
blue_car.showDescription()
# Prints This car is a Black Sedan
In [ ]:
red_car = Car('Red', 30000)

# call method 1
red_car.showDescription()
# Prints This car is a Black Sedan
In [ ]:

271-CIS-3 Lab Manual - 2022 94


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-15 Object Oriented Programming (cont.)

Inherit From Other Classes in Python


Inheritance is the process by which one class takes on the attributes and methods of another. Newly formed classes are
called child classes, and the classes that child classes are derived from are called parent classes.
Child classes can override or extend the attributes and methods of parent classes. In other words, child classes inherit all
of the parent’s attributes and methods but can also specify attributes and methods that are unique to themselves.

Dog Park Example


In [ ]:
class Dog:
species = "Canis familiaris"

def __init__(self, name, age, breed):


self.name = name
self.age = age
self.breed = breed

# Instance method
def description(self):
#return f"{self.name} is {self.age} years old"
return self.name , self.age

# Another instance method


def speak(self, sound):
return f"{self.name} says {sound}"
In [ ]:
miles = Dog("Miles", 4, "Jack Russell Terrier")
buddy = Dog("Buddy", 9, "Dachshund")
jack = Dog("Jack", 3, "Bulldog")
jim = Dog("Jim", 5, "Bulldog")
In [ ]:
buddy.speak("Yap")
In [ ]:
jim.speak("Woof")
Passing a string to every call to .speak() is repetitive and inconvenient. Moreover, the string representing the sound that
each Dog instance makes should be determined by its .breed attribute, but here you have to manually pass the correct
string to .speak() every time it’s called.

You can simplify the experience of working with the Dog class by creating a child class for each breed of dog. This allows
you to extend the functionality that each child class inherits, including specifying a default argument for .speak().

271-CIS-3 Lab Manual - 2022 95


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Parent Classes vs Child Classes


Let’s create a child class for each of the three breeds mentioned above: Jack Russell Terrier, Dachshund, and Bulldog.
For reference, here’s the full definition of the Dog class:
To create a child class, you create new class with its own name and then put the name of the parent class in
parentheses. Add the following to the dog.py file to create three new child classes of the Dog class:
In [ ]:
class Dog:
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age

# Instance method
def description(self):
#return f"{self.name} is {self.age} years old"
return self.name , self.age

# Another instance method


def speak(self, sound):
return f"{self.name} says {sound}"
In [ ]:
class JackRussellTerrier(Dog):
pass

class Dachshund(Dog):
pass

class Bulldog(Dog):
pass
In [ ]:
miles = JackRussellTerrier("Miles", 4)
buddy = Dachshund("Buddy", 9)
jack = Bulldog("Jack", 3)
jim = Bulldog("Jim", 5)
jam = Dog('Jam',8)
In [ ]:
miles.species
In [ ]:
jack.name
In [ ]:
jim.age
To determine which class a given object belongs to, you can use the built-in type():
In [ ]:
type(miles)
In [ ]:
type(jam)
What if you want to determine if miles is also an instance of the Dog class? You can do this with the built-in isinstance():
271-CIS-3 Lab Manual - 2022 96
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In [ ]:
isinstance(miles, JackRussellTerrier)
In [ ]:
isinstance(jam, Bulldog)

Extend the Functionality of a Parent Class


Since different breeds of dogs have slightly different barks, you want to provide a default value for the sound argument
of their respective .speak() methods. To do this, you need to override .speak() in the class definition for each breed.

To override a method defined on the parent class, you define a method with the same name on the child class. Here’s
what that looks like for the JackRussellTerrier class:
In [ ]:
class JackRussellTerrier(Dog):
def speak(self, sound="Arf"):
return f"{self.name} says {sound}"
In [ ]:
miles = JackRussellTerrier("Miles", 4)
miles.speak()
In [ ]:
abc = JackRussellTerrier("abc", 4)
abc.speak()
In [ ]:
miles.speak("Grrr")

One thing to keep in mind about class inheritance is that changes to the parent class automatically propagate to
child classes. This occurs as long as the attribute or method being changed isn’t overridden in the child class.

For example, in the editor window, change the string returned by .speak() in the Dog class:
In [ ]:
class Dog:
species = "Canis familiaris"

def __init__(self, name, age):


self.name = name
self.age = age

# Instance method
def description(self):
#return f"{self.name} is {self.age} years old"
return self.name , self.age

# Another instance method


def speak(self, sound):
return f"{self.name} barks: {sound}"
In [ ]:
class JackRussellTerrier(Dog):
pass

class Dachshund(Dog):
271-CIS-3 Lab Manual - 2022 97
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

pass

class Bulldog(Dog):
pass
In [ ]:
jim = Bulldog("Jim", 5)
jim.speak("Woof")
In [ ]:
class JackRussellTerrier(Dog):
def speak(self, sound="Arf"):
return f"{self.name} says {sound}"
However, calling .speak() on a JackRussellTerrier instance won’t show the new style of output:
In [ ]:
miles = JackRussellTerrier("Miles", 4)
miles.speak()
You can access the parent class from inside a method of a child class by using super():
In [ ]:
class JackRussellTerrier(Dog):
def speak(self, sound="Arf"):
return super().speak(sound)
In [ ]:
miles = JackRussellTerrier("Miles", 4)
miles.speak()
In [ ]:

In [ ]:

271-CIS-3 Lab Manual - 2022 98


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-16 Object Oriented Programming (cont.)

271-CIS-3 Lab Manual - 2022 99


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-17 Exception Handling

Python Try Except


The try block lets you test a block of code for errors.

The except block lets you handle the error.

The finally block lets you execute code, regardless of the result of the try- and except blocks.

Exception Handling

When an error occurs, or exception as we call it, Python will normally stop and generate an error
message.

These exceptions can be handled using the try statement:

Example

The try block will generate an exception, because x is not defined:

try:
print(x)
except:
print("An exception occurred")

Since the try block raises an error, the except block will be executed.

Without the try block, the program will crash and raise an error:

Example

This statement will raise an error, because x is not defined:

print(x)

271-CIS-3 Lab Manual - 2022 100


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Many Exceptions

You can define as many exception blocks as you want, e.g. if you want to execute a special block
of code for a special kind of error:

Example

Print one message if the try block raises a NameError and another for other errors:

try:
print(x)
except NameError:
print("Variable x is not defined")
except:
print("Something else went wrong")

Else

You can use the else keyword to define a block of code to be executed if no errors were raised:

Example

In this example, the try block does not generate any error:

try:
print("Hello")
except:
print("Something went wrong")
else:
print("Nothing went wrong")

271-CIS-3 Lab Manual - 2022 101


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Finally

The finally block, if specified, will be executed regardless if the try block raises an error or
not.

Example
try:
print(x)
except:
print("Something went wrong")
finally:
print("The 'try except' is finished")

This can be useful to close objects and clean up resources:

Example

Try to open and write to a file that is not writable:

try:
f = open("demofile.txt")
f.write("Lorum Ipsum")
except:
print("Something went wrong when writing to the file")
finally:
f.close()

The program can continue, without leaving the file object open.

271-CIS-3 Lab Manual - 2022 102


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Raise an exception

As a Python developer you can choose to throw an exception if a condition occurs.

To throw (or raise) an exception, use the raise keyword.

Example

Raise an error and stop the program if x is lower than 0:

x = -1

if x < 0:
raise Exception("Sorry, no numbers below zero")

The raise keyword is used to raise an exception.

You can define what kind of error to raise, and the text to print to the user.

Example

Raise a TypeError if x is not an integer:

x = "hello"

if not type(x) is int:


raise TypeError("Only integers are allowed")

271-CIS-3 Lab Manual - 2022 103


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-18 Exception Handling (cont.)

Exception Examples
print (x)
---------------------------------------------------------------------------
NameError Traceback (most recent call last)
<ipython-input-1-606ad02f996c> in <module>
----> 1 print (x)

NameError: name 'x' is not defined


In [1]:
try:
#x=5
print(x)
except:
print("An exception occurred")
An exception occurred
In [12]:
#yoou can name the error and define exception for each error (try only one time / and
exception)

try:
print("hello")
frint()
except NameError as e:
print(e)
except:
print("Something else went wrong")
hello
name 'frint' is not defined
In [8]:
#You can use the else keyword to define a block of code to be executed if no errors were
raised:
try:
print("Hello")
except:
print("Something went wrong")
else:
print("Nothing went wrong")
Hello
Nothing went wrong
In [2]:
#The finally block, if specified, will be executed regardless if the try block raises an
error or not.

try:
print(x)
except:
print("Something went wrong")
finally:
print("The 'try except' is finished")
271-CIS-3 Lab Manual - 2022 104
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Something went wrong


The 'try except' is finished

Example

Try to open and write to a file that is not writable:


try: f = open("demofile.txt") f.write("Lorum Ipsum") except: print("Something went wrong when writing to the file")
In [3]:
#Raise an error and stop the program if x is lower than 0:
x = -1

if x < 0:
raise Exception("Sorry, no numbers below zero")
---------------------------------------------------------------------------
Exception Traceback (most recent call last)
<ipython-input-3-0bedc16e1ab9> in <module>
3
4 if x < 0:
----> 5 raise Exception("Sorry, no numbers below zero")

Exception: Sorry, no numbers below zero


In [4]:
x = "hello"

if not type(x) is int:


raise TypeError("Only integers are allowed")
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-4-bc91768a6271> in <module>
2
3 if not type(x) is int:
----> 4 raise TypeError("Only integers are allowed")

TypeError: Only integers are allowed

271-CIS-3 Lab Manual - 2022 105


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

User-Defined Exceptions
In [1]:
class AlreadyGotOne(Exception):
pass # User-defined exception
def grail():
raise AlreadyGotOne() # Raise an instance

try:
grail()
except AlreadyGotOne: # Catch class name
print('got exception')
got exception
In [30]:
class Career(Exception):
def __str__(self):
return 'So I became a waiter...'
raise Career()
---------------------------------------------------------------------------
Career Traceback (most recent call last)
<ipython-input-30-df005eeec023> in <module>
2 def __str__(self):
3 return 'So I became a waiter...'
----> 4 raise Career()

Career: So I became a waiter...


In [ ]:

In [ ]:

271-CIS-3 Lab Manual - 2022 106


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Book Example
def fetcher(obj, index):
return obj[index]
In [2]:
x = 'spam'
fetcher(x, 3)
Out[2]:
'm'
In [3]:
fetcher(x, 4)
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-3-8f3b5aeb5455> in <module>
----> 1 fetcher(x, 4)

<ipython-input-1-555723af9edd> in fetcher(obj, index)


1 def fetcher(obj, index):
----> 2 return obj[index]

IndexError: string index out of range


In [4]:
try:
fetcher(x, 4)
except IndexError: # Catch and recover
print('got exception.. out of index')
got exception.. out of index
In [5]:
def catcher():
try:
fetcher(x, 4)
except IndexError:
print('got exception')
print('continuing')
In [6]:
catcher()
got exception
continuing
In [7]:
try:
raise IndexError # Trigger exception manually
except IndexError:
print('got exception')
got exception
In [8]:
raise IndexError
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-8-55a00e7db5b5> in <module>
----> 1 raise IndexError

IndexError:
In [9]:
271-CIS-3 Lab Manual - 2022 107
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

try:
fetcher(x, 3)
finally: # Termination actions
print('after fetch')
after fetch
In [10]:
def after():
try:
fetcher(x, 4)
finally:
print('after fetch')
print('after try?')
In [11]:
after()
after fetch
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-11-4f451c6f09ad> in <module>
----> 1 after()

<ipython-input-10-3140870f4544> in after()
1 def after():
2 try:
----> 3 fetcher(x, 4)
4 finally:
5 print('after fetch')

<ipython-input-1-555723af9edd> in fetcher(obj, index)


1 def fetcher(obj, index):
----> 2 return obj[index]

IndexError: string index out of range


In [12]:

271-CIS-3 Lab Manual - 2022 108


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

def after():
try:
fetcher(x, 4)
except IndexError:
print('out of index')
finally:
print('after fetch')
print('after try?')
In [13]:
after()
out of index
after fetch
after try?
In [14]:
def after():
try:
fetcher(x, 3)
finally:
print('after fetch')
print('after try?')
In [15]:
after()
after fetch
after try?

271-CIS-3 Lab Manual - 2022 109


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-19 Connecting and working with Database

Python MySQL

Python can be used in database applications.

One of the most popular databases is MySQL.

MySQL Database

To be able to experiment with the code examples in this tutorial, you should have MySQL
installed on your computer.

You can download a free MySQL database at https://www.mysql.com/downloads/.

Install MySQL Driver

Python needs a MySQL driver to access the MySQL database.

In this tutorial we will use the driver "MySQL Connector".

We recommend that you use PIP to install "MySQL Connector".

PIP is most likely already installed in your Python environment.

Navigate your command line to the location of PIP, and type the following:

Download and install "MySQL Connector":

C:\Users\Your Name\AppData\Local\Programs\Python\Python36-32\Scripts>python -m pip


install mysql-connector-python

Now you have downloaded and installed a MySQL driver.

271-CIS-3 Lab Manual - 2022 110


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Test MySQL Connector

To test if the installation was successful, or if you already have "MySQL Connector" installed,
create a Python page with the following content:

demo_mysql_test.py:

import mysql.connector

If the above code was executed with no errors, "MySQL Connector" is installed and ready to be
used.

Create Connection

Start by creating a connection to the database.

Use the username and password from your MySQL database:

demo_mysql_connection.py:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword"
)

print(mydb)

Now you can start querying the database using SQL statements.

Python MySQL Create Database

271-CIS-3 Lab Manual - 2022 111


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Creating a Database

To create a database in MySQL, use the "CREATE DATABASE" statement:

Example

create a database named "mydatabase":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword"
)

mycursor = mydb.cursor()

mycursor.execute("CREATE DATABASE mydatabase")

If the above code was executed with no errors, you have successfully created a database.

Check if Database Exists

You can check if a database exist by listing all databases in your system by using the "SHOW
DATABASES" statement:

Example

Return a list of your system's databases:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword"
)

mycursor = mydb.cursor()

mycursor.execute("SHOW DATABASES")

for x in mycursor:
print(x)

271-CIS-3 Lab Manual - 2022 112


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Or you can try to access the database when making the connection:

Example

Try connecting to the database "mydatabase":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

If the database does not exist, you will get an error.

Python MySQL Create Table


Creating a Table

To create a table in MySQL, use the "CREATE TABLE" statement.

Make sure you define the name of the database when you create the connection

Example

Create a table named "customers":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("CREATE TABLE customers (name VARCHAR(255), address VARCHAR(255))")

If the above code was executed with no errors, you have now successfully created a table.

271-CIS-3 Lab Manual - 2022 113


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Check if Table Exists

You can check if a table exist by listing all tables in your database with the "SHOW TABLES"
statement:

Example

Return a list of your system's databases:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("SHOW TABLES")

for x in mycursor:
print(x)

271-CIS-3 Lab Manual - 2022 114


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Primary Key

When creating a table, you should also create a column with a unique key for each record.

This can be done by defining a PRIMARY KEY.

We use the statement "INT AUTO_INCREMENT PRIMARY KEY" which will insert a unique number
for each record. Starting at 1, and increased by one for each record.

Example

Create primary key when creating the table:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("CREATE TABLE customers (id INT AUTO_INCREMENT PRIMARY KEY, name


VARCHAR(255), address VARCHAR(255))")

If the table already exists, use the ALTER TABLE keyword:

Example

Create primary key on an existing table:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("ALTER TABLE customers ADD COLUMN id INT AUTO_INCREMENT PRIMARY KEY")

271-CIS-3 Lab Manual - 2022 115


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python MySQL Insert Into Table


Insert Into Table

To fill a table in MySQL, use the "INSERT INTO" statement.

Example

Insert a record in the "customers" table:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"


val = ("John", "Highway 21")
mycursor.execute(sql, val)

mydb.commit()

print(mycursor.rowcount, "record inserted.")

Important!: Notice the statement: mydb.commit(). It is required to make the changes,


otherwise no changes are made to the table.

271-CIS-3 Lab Manual - 2022 116


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Insert Multiple Rows

To insert multiple rows into a table, use the executemany() method.

The second parameter of the executemany() method is a list of tuples, containing the data you
want to insert:

Example

Fill the "customers" table with data:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"


val = [
('Peter', 'Lowstreet 4'),
('Amy', 'Apple st 652'),
('Hannah', 'Mountain 21'),
('Michael', 'Valley 345'),
('Sandy', 'Ocean blvd 2'),
('Betty', 'Green Grass 1'),
('Richard', 'Sky st 331'),
('Susan', 'One way 98'),
('Vicky', 'Yellow Garden 2'),
('Ben', 'Park Lane 38'),
('William', 'Central st 954'),
('Chuck', 'Main Road 989'),
('Viola', 'Sideway 1633')
]

mycursor.executemany(sql, val)

mydb.commit()

print(mycursor.rowcount, "was inserted.")

271-CIS-3 Lab Manual - 2022 117


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Get Inserted ID

You can get the id of the row you just inserted by asking the cursor object.

Note: If you insert more than one row, the id of the last inserted row is returned.

Example

Insert one row, and return the ID:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "INSERT INTO customers (name, address) VALUES (%s, %s)"


val = ("Michelle", "Blue Village")
mycursor.execute(sql, val)

mydb.commit()

print("1 record inserted, ID:", mycursor.lastrowid)

271-CIS-3 Lab Manual - 2022 118


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python MySQL Select From


Select From a Table

To select from a table in MySQL, use the "SELECT" statement:

Example

Select all records from the "customers" table, and display the result:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("SELECT * FROM customers")

myresult = mycursor.fetchall()

for x in myresult:
print(x)

Note: We use the fetchall() method, which fetches all rows from the last executed statement.

271-CIS-3 Lab Manual - 2022 119


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Selecting Columns

To select only some of the columns in a table, use the "SELECT" statement followed by the
column name(s):

Example

Select only the name and address columns:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

mycursor.execute("SELECT name, address FROM customers")

myresult = mycursor.fetchall()

for x in myresult:
print(x)

Using the fetchone() Method

If you are only interested in one row, you can use the fetchone() method.

The fetchone() method will return the first row of the result:

Example

Fetch only one row:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

271-CIS-3 Lab Manual - 2022 120


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

mycursor.execute("SELECT * FROM customers")

myresult = mycursor.fetchone()

print(myresult)

Python MySQL Where


Select With a Filter

When selecting records from a table, you can filter the selection by using the "WHERE"
statement:

Example

Select record(s) where the address is "Park Lane 38": result:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT * FROM customers WHERE address ='Park Lane 38'"

mycursor.execute(sql)

myresult = mycursor.fetchall()

for x in myresult:
print(x)

271-CIS-3 Lab Manual - 2022 121


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Wildcard Characters

You can also select the records that starts, includes, or ends with a given letter or phrase.

Use the % to represent wildcard characters:

Example

Select records where the address contains the word "way":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT * FROM customers WHERE address LIKE '%way%'"

mycursor.execute(sql)

myresult = mycursor.fetchall()

for x in myresult:
print(x)

271-CIS-3 Lab Manual - 2022 122


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Prevent SQL Injection

When query values are provided by the user, you should escape the values.

This is to prevent SQL injections, which is a common web hacking technique to destroy or
misuse your database.

The mysql.connector module has methods to escape query values:

Example

Escape query values by using the placholder %s method:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT * FROM customers WHERE address = %s"


adr = ("Yellow Garden 2", )

mycursor.execute(sql, adr)

myresult = mycursor.fetchall()

for x in myresult:
print(x)

271-CIS-3 Lab Manual - 2022 123


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-20 Connecting and working with Database, (cont.)

Python MySQL Order By


Sort the Result

Use the ORDER BY statement to sort the result in ascending or descending order.

The ORDER BY keyword sorts the result ascending by default. To sort the result in descending
order, use the DESC keyword.

Example

Sort the result alphabetically by name: result:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT * FROM customers ORDER BY name"

mycursor.execute(sql)

myresult = mycursor.fetchall()

for x in myresult:
print(x)

271-CIS-3 Lab Manual - 2022 124


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

ORDER BY DESC

Use the DESC keyword to sort the result in a descending order.

Example

Sort the result reverse alphabetically by name:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT * FROM customers ORDER BY name DESC"

mycursor.execute(sql)

myresult = mycursor.fetchall()

for x in myresult:
print(x)

271-CIS-3 Lab Manual - 2022 125


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python MySQL Delete From By


Delete Record

You can delete records from an existing table by using the "DELETE FROM" statement:

Example

Delete any record where the address is "Mountain 21":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "DELETE FROM customers WHERE address = 'Mountain 21'"

mycursor.execute(sql)

mydb.commit()

print(mycursor.rowcount, "record(s) deleted")

Important!: Notice the statement: mydb.commit(). It is required to make the changes,


otherwise no changes are made to the table.

Notice the WHERE clause in the DELETE syntax: The WHERE clause specifies which
record(s) that should be deleted. If you omit the WHERE clause, all records will be deleted!

271-CIS-3 Lab Manual - 2022 126


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python MySQL Drop Table


Delete a Table

You can delete an existing table by using the "DROP TABLE" statement:

Example

Delete the table "customers":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "DROP TABLE customers"

mycursor.execute(sql)

Drop Only if Exist

If the the table you want to delete is already deleted, or for any other reason does not exist, you
can use the IF EXISTS keyword to avoid getting an error.

Example

Delete the table "customers" if it exists:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase")

mycursor = mydb.cursor()

sql = "DROP TABLE IF EXISTS customers"

mycursor.execute(sql)
271-CIS-3 Lab Manual - 2022 127
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Python MySQL Update Table


Update Table

You can update existing records in a table by using the "UPDATE" statement:

Example

Overwrite the address column from "Valley 345" to "Canyoun 123":

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "UPDATE customers SET address = 'Canyon 123' WHERE address = 'Valley 345'"

mycursor.execute(sql)

mydb.commit()

print(mycursor.rowcount, "record(s) affected")

Important!: Notice the statement: mydb.commit(). It is required to make the changes,


otherwise no changes are made to the table.

Notice the WHERE clause in the UPDATE syntax: The WHERE clause specifies which record
or records that should be updated. If you omit the WHERE clause, all records will be updated!

271-CIS-3 Lab Manual - 2022 128


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Prevent SQL Injection

It is considered a good practice to escape the values of any query, also in update statements.

This is to prevent SQL injections, which is a common web hacking technique to destroy or
misuse your database.

The mysql.connector module uses the placeholder %s to escape values in the delete statement:

Example

Escape values by using the placholder %s method:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "UPDATE customers SET address = %s WHERE address = %s"


val = ("Valley 345", "Canyon 123")

mycursor.execute(sql, val)

mydb.commit()

print(mycursor.rowcount, "record(s) affected")

271-CIS-3 Lab Manual - 2022 129


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Join Two or More Tables

You can combine rows from two or more tables, based on a related column between them, by
using a JOIN statement.

Consider you have a "users" table and a "products" table:

users

{ id: 1, name: 'John', fav: 154},


{ id: 2, name: 'Peter', fav: 154},
{ id: 3, name: 'Amy', fav: 155},
{ id: 4, name: 'Hannah', fav:},
{ id: 5, name: 'Michael', fav:}

products

{ id: 154, name: 'Chocolate Heaven' },


{ id: 155, name: 'Tasty Lemons' },
{ id: 156, name: 'Vanilla Dreams' }

These two tables can be combined by using users' fav field and products' id field.

Example

Join users and products to see the name of the users favorite product:

import mysql.connector

mydb = mysql.connector.connect(
host="localhost",
user="yourusername",
password="yourpassword",
database="mydatabase"
)

mycursor = mydb.cursor()

sql = "SELECT \
users.name AS user, \
products.name AS favorite \
FROM users \
INNER JOIN products ON users.fav = products.id"

mycursor.execute(sql)

myresult = mycursor.fetchall()

271-CIS-3 Lab Manual - 2022 130


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

for x in myresult:
print(x)

Note: You can use JOIN instead of INNER JOIN. They will both give you the same result.

LEFT JOIN

In the example above, Hannah, and Michael were excluded from the result, that is because
INNER JOIN only shows the records where there is a match.

If you want to show all users, even if they do not have a favorite product, use the LEFT JOIN
statement:

Example

Select all users and their favorite product:

sql = "SELECT \
users.name AS user, \
products.name AS favorite \
FROM users \
LEFT JOIN products ON users.fav = products.id"

RIGHT JOIN

If you want to return all products, and the users who have them as their favorite, even if no user
have them as their favorite, use the RIGHT JOIN statement:

Example

Select all products, and the user(s) who have them as their favorite:

sql = "SELECT \
users.name AS user, \
products.name AS favorite \
FROM users \
RIGHT JOIN products ON users.fav = products.id"

Note: Hannah and Michael, who have no favorite product, are not included in the result.

271-CIS-3 Lab Manual - 2022 131


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-21 Web application development with Python: Django framework

What is Django?

Django is a high-level Python web framework that enables rapid development of secure and maintainable
websites. Built by experienced developers, Django takes care of much of the hassle of web development, so you
can focus on writing your app without needing to reinvent the wheel. It is free and open source, has a thriving
and active community, great documentation, and many options for free and paid-for support.

Django Features:

Complete

Django follows the "Batteries included" philosophy and provides almost everything developers might want to
do "out of the box". Because everything you need is part of the one "product", it all works seamlessly together,
follows consistent design principles, and has extensive and up-to-date documentation.

Versatile

Django can be (and has been) used to build almost any type of website — from content management systems
and wikis, through to social networks and news sites. It can work with any client-side framework, and can
deliver content in almost any format (including HTML, RSS feeds, JSON, XML, etc). The tutorial you are
currently performing is built with Django.

Internally, while it provides choices for almost any functionality you might want (e.g. several popular
databases, templating engines, etc.), it can also be extended to use other components if needed.

Secure

Django helps developers avoid many common security mistakes by providing a framework that has been
engineered to "do the right things" to protect the website automatically. For example, Django provides a secure
way to manage user accounts and passwords, avoiding common mistakes like putting session information in

271-CIS-3 Lab Manual - 2022 132


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

cookies where it is vulnerable (instead cookies just contain a key, and the actual data is stored in the database)
or directly storing passwords rather than a password hash.

Django Architecture

URLs: While it is possible to process requests from every single URL via a single function, it is much more
maintainable to write a separate view function to handle each resource. A URL mapper is used to
redirect HTTP requests to the appropriate view based on the request URL. The URL mapper can also
match particular patterns of strings or digits that appear in a URL and pass these to a view function as
data.

View: A view is a request handler function, which receives HTTP requests and returns HTTP responses.
Views access the data needed to satisfy requests via models, and delegate the formatting of the response
to templates.

Models: Models are Python objects that define the structure of an application's data, and
provide mechanisms to manage (add, modify, delete) and query records in the database.

Templates: A template is a text file defining the structure or layout of a file (such as an HTML page), with
placeholders used to represent actual content. A view can dynamically create an HTML page using an
HTML template, populating it with data from a model. A template can be used to define the structure of
any type of file; it doesn't have to be HTML!

271-CIS-3 Lab Manual - 2022 133


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Sending the request to the right view (urls.py)

A URL mapper is typically stored in a file named urls.py. In the example below, the mapper (urlpatterns)
defines a list of mappings between routes (specific URL patterns) and corresponding view functions. If an
HTTP Request is received that has a URL matching a specified pattern, then the associated view function will
be called and passed the request.

The first argument to both methods is a route (pattern) that will be matched. The path() method uses angle
brackets to define parts of a URL that will be captured and passed through to the view function as named
arguments. The re_path() function uses a flexible pattern matching approach known as a regular expression.
We'll talk about these in a later article!

The second argument is another function that will be called when the pattern is matched. The
notation views.book_detail indicates that the function is called book_detail() and can be found in a module
called views (i.e. inside a file named views.py)

Handling the request (views.py)

Views are the heart of the web application, receiving HTTP requests from web clients and returning HTTP
responses. In between, they marshal the other resources of the framework to access databases, render templates,
etc.

The example below shows a minimal view function index(), which could have been called by our URL mapper
in the previous section. Like all view functions it receives an HttpRequest object as a parameter (request) and
returns an HttpResponse object. In this case we don't do anything with the request, and our response returns a
hard-coded string. We'll show you a request that does something more interesting in a later section.

271-CIS-3 Lab Manual - 2022 134


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Defining data models (models.py)

Django web applications manage and query data through Python objects referred to as models. Models define
the structure of stored data, including the field types and possibly also their maximum size, default values,
selection list options, help text for documentation, label text for forms, etc. The definition of the model is
independent of the underlying database — you can choose one of several as part of your project settings. Once
you've chosen what database you want to use, you don't need to talk to it directly at all — you just write your
model structure and other code, and Django handles all the "dirty work" of communicating with the database for
you.

The code snippet below shows a very simple Django model for a Team object. The Team class is derived from the
django class models.Model. It defines the team name and team level as character fields and specifies a maximum
number of characters to be stored for each record. The team_level can be one of several values, so we define it
as a choice field and provide a mapping between choices to be displayed and data to be stored, along with a
default value.

271-CIS-3 Lab Manual - 2022 135


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Querying data (views.py)

The Django model provides a simple query API for searching the associated database. This can match against a
number of fields at a time using different criteria (e.g. exact, case-insensitive, greater than, etc.), and can
support complex statements (for example, you can specify a search on U11 teams that have a team name that
starts with "Fr" or ends with "al").

The code snippet shows a view function (resource handler) for displaying all of our U09 teams. The list_teams
= Team.objects.filter(team_level__exact="U09") line shows how we can use the model query API to filter

for all records where the team_level field has exactly the text 'U09' (note how this criteria is passed to
the filter() function as an argument, with the field name and match type separated by a double
underscore: team_level__exact).

This function uses the render() function to create the HttpResponse that is sent back to the browser. This
function is a shortcut; it creates an HTML file by combining a specified HTML template and some data to
insert in the template (provided in the variable named "context"). In the next section we show how the template
has the data inserted in it to create the HTML.

271-CIS-3 Lab Manual - 2022 136


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Rendering data (HTML templates)

Template systems allow you to specify the structure of an output document, using placeholders for data that will
be filled in when a page is generated. Templates are often used to create HTML, but can also create other types
of document. Django supports both its native templating system and another popular Python library called
Jinja2 out of the box (it can also be made to support other systems if needed).

The code snippet shows what the HTML template called by the render() function in the previous section might
look like. This template has been written under the assumption that it will have access to a list variable
called youngest_teams when it is rendered (this is contained in the context variable inside the render() function
above). Inside the HTML skeleton we have an expression that first checks if the youngest_teams variable exists,
and then iterates it in a for loop. On each iteration the template displays each team's team_name value in
an <li> element.

271-CIS-3 Lab Manual - 2022 137


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Installing Python and Virtual Environment

macOS

macOS recent versions do not include Python 3. You can confirm this by running the following commands in
the zsh or bash terminal:

You can easily install Python 3 (along with the pip3 tool) from python.org:

1. Download the required installer:


Go to https://www.python.org/downloads/
2. Select the Download Python 3.8.6 button (the exact version number may differ).
3. Locate the file using Finder, and double-click the package file. Following the installation prompts.
You can now confirm successful installation by checking for the Python 3 version as shown below:

You can similarly check that pip3 is installed by listing the available packages:

271-CIS-3 Lab Manual - 2022 138


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Windows 10

Windows doesn't include Python by default, but you can easily install it (along with the pip3 tool) from
python.org:

1. Download the required installer:

1. Go to https://www.python.org/downloads/

2. Select the Download Python 3.8.6 button (the exact version number may differ).

2. Install Python by double-clicking on the downloaded file and following the installation prompts

3. Be sure to check the box labeled "Add Python to PATH"

You can then verify that Python 3 was installed by entering the following text into the command prompt:

The Windows installer incorporates pip3 (the Python package manager) by default. You can list installed
packages as shown:

271-CIS-3 Lab Manual - 2022 139


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Using Django inside a Python virtual environment

The libraries we'll use for creating our virtual environments are virtualenvwrapper (Linux and macOS)
and virtualenvwrapper-win (Windows), which in turn both use the virtualenv tool. The wrapper tools creates a
consistent interface for managing interfaces on all platforms.

macOS virtual environment setup

Setting up virtualenvwrapper on macOS is almost exactly the same as on Ubuntu (again, you can follow the
instructions from either the official installation guide or below).

Install virtualenvwrapper (and bundling virtualenv) using pip as shown.

Then add the following lines to the end of your shell startup file

If you're using the zsh shell then the startup file will be a hidden file named .zshrc in your home directory. If
you're using the bash shell then it will be a hidden file named .bash_profile. You may need to create the file if
it does not yet exist.

Make sure you check python version and directory by using the following command

which virtualenvwrapper.sh and which python3

271-CIS-3 Lab Manual - 2022 140


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Steps to add the default directory of VirtualENV:

1) Go to Anaconda and open VS Code

2) When VS Code open, go to Terminal > New Terminal

271-CIS-3 Lab Manual - 2022 141


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

3) Write the following code to open .zshrc file sudo code ~/.zshrc , then enter the user password if
required

4) Add the following to the file and save it using sudo

export WORKON_HOME=$HOME/.virtualenvs
export VIRTUALENVWRAPPER_PYTHON=/Library/Frameworks/Python.framework/Versions/3.9/bin/python3
export PROJECT_HOME=$HOME/Devel
source /Library/Frameworks/Python.framework/Versions/3.9/bin/virtualenvwrapper.sh

5) Then, run the following command source ~/.zshrc , if things done properly then you should have
the following output
virtualenvwrapper.user_scripts creating
/home/ubuntu/.virtualenvs/premkproject
virtualenvwrapper.user_scripts creating
/home/ubuntu/.virtualenvs/postmkproject
...
virtualenvwrapper.user_scripts creating
/home/ubuntu/.virtualenvs/preactivate
virtualenvwrapper.user_scripts creating
/home/ubuntu/.virtualenvs/postactivate
virtualenvwrapper.user_scripts creating
/home/ubuntu/.virtualenvs/get_env_details

271-CIS-3 Lab Manual - 2022 142


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Windows 10 virtual environment setup

First, you should go to Windows PowerShell

• From search bar, type “Windows PowerShell

• The following window will popup

• Make sure python is installed by using the following command

• Now install the virtualenvwrapper-win on the system by using the command


pip3 install virtualenvwrapper-win

271-CIS-3 Lab Manual - 2022 143


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Now you can create a new virtual environment with the mkvirtualenv command

Creating a virtual environment

Once you've installed virtualenvwrapper or virtualenvwrapper-win then working with virtual environments is
very similar on all platforms.

Now you can create a new virtual environment with the mkvirtualenv command. As this command runs you'll
see the environment being set up (what you see is slightly platform-specific). When the command completes the
new virtual environment will be active — you can see this because the start of the prompt will be the name of
the environment in brackets (below we show this for Ubuntu, but the final line is similar for Windows/macOS).

$ mkvirtualenv my_django_environment

Windows output

271-CIS-3 Lab Manual - 2022 144


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

MacOS output

Now you're inside the virtual environment you can install Django and start developing.

271-CIS-3 Lab Manual - 2022 145


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Installing Django

Once you've created a virtual environment, and called workon to enter it, you can use pip3 to install Django.

pip3 install django~=3.1

You can test that Django is installed by running the following command (this just tests that Python can find the
Django module):

# Linux/macOS

python3 -m django --version

3.1.2

# Windows

py -3 -m django --version

3.1.2

Note: If the above Windows command does not show a django module present, try:

py -m django --version

In Windows Python 3 scripts are launched by prefixing the command with py -3, although this can vary
depending on your specific installation. Try omitting the -3 modifier if you encounter any problems with
commands. In Linux/macOS, the command is python3.

271-CIS-3 Lab Manual - 2022 146


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Using a virtual environment

There are just a few other useful commands that you should know (there are more in the tool documentation,
but these are the ones you'll use regularly):

deactivate — Exit out of the current Python virtual environment

workon — List available virtual environments

workon name_of_environment — Activate the specified Python virtual environment

rmvirtualenv name_of_environment — Remove the specified environment.

Testing your installation

The above test works, but it isn't very much fun. A more interesting test is to create a skeleton project and see it
working. To do this, first navigate in your command prompt/terminal to where you want to store your Django
apps. Create a folder for your test site and navigate into it.

mkdir django_test

cd django_test

You can then create a new skeleton site called "mytestsite" using the django-admin tool as shown. After
creating the site you can navigate into the folder where you will find the main script for managing projects,
called manage.py.

django-admin startproject mytestsite

cd mytestsite

We can run the development web server from within this folder using manage.py and the runserver command,
as shown.

271-CIS-3 Lab Manual - 2022 147


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

$ python3 manage.py runserver

Watching for file changes with StatReloader

Performing system checks...

System check identified no issues (0 silenced).

You have 18 unapplied migration(s). Your project may not work properly until you apply the
migrations for app(s): admin, auth, contenttypes, sessions.

Run 'python manage.py migrate' to apply them.

October 27, 2020 - 03:00:01

Django version 3.1.2, using settings 'mytestsite.settings'

Starting development server at http://127.0.0.1:8000/

Quit the server with CONTROL-C.

271-CIS-3 Lab Manual - 2022 148


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Once the server is running you can view the site by navigating to the following URL on your local web
browser: http://127.0.0.1:8000/. You should see a site that looks like this:

271-CIS-3 Lab Manual - 2022 149


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-22 Web application development with Python: Django framework (cont.)

Django Tutorial: Creating a skeleton website

Overview

This article shows how you can create a "skeleton" website, which you can then populate with site-specific settings, paths,
models, views, and templates (we discuss these in later articles).

Creating the project

1. Open a command shell (or a terminal window), and make sure you are in your virtual environment.
2. Navigate to where you want to store your Django apps (make it somewhere easy to find like inside
your Documents folder), and create a folder for your new website (in this case: django_projects). Then change
into your newly-created directory:
mkdir django_projects
cd django_projects
3. Create the new project using the django-admin startproject command as shown, and then change into the
project folder:
django-admin startproject locallibrary
cd locallibrary
code locallibrary

271-CIS-3 Lab Manual - 2022 150


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The django-admin tool creates a folder/file structure as follows:

The locallibrary project sub-folder is the entry point for the website:

• __init__.py is an empty file that instructs Python to treat this directory as a Python package.
• settings.py contains all the website settings, including registering any applications we create, the location of our
static files, database configuration details, etc.
• urls.py defines the site URL-to-view mappings. While this could contain all the URL mapping code, it is more
common to delegate some of the mappings to particular applications, as you'll see later.
• wsgi.py is used to help your Django application communicate with the webserver. You can treat this as
boilerplate.
• asgi.py is a standard for Python asynchronous web apps and servers to communicate with each other. ASGI is
the asynchronous successor to WSGI and provides a standard for both asynchronous and synchronous Python
apps (whereas WSGI provided a standard for synchronous apps only). It is backward-compatible with WSGI and
supports multiple servers and application frameworks.
The manage.py script is used to create applications, work with databases, and start the development web server.

271-CIS-3 Lab Manual - 2022 151


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Creating the catalog application

Next, run the following command to create the catalog application that will live inside our locallibrary project. Make sure
to run this command from the same folder as your project's manage.py:

python3 manage.py startapp catalog

Note: The example command is for Linux/macOS X. On Windows, the command should be:

py -3 manage.py startapp catalog

If you're working on Windows, replace python3 with py -3 throughout this module.

If you are using Python 3.7.0 or later, you should only use py manage.py startapp catalog

The tool creates a new folder and populates it with files for the different parts of the application (shown in the following
example). Most of the files are named after their purpose (e.g. views should be stored in views.py, models
in models.py, tests in tests.py, administration site configuration in admin.py, application registration in apps.py)
and contain some minimal boilerplate code for working with the associated objects.

Registering the catalog application

Now that the application has been created, we have to register it with the project so that it will be included when any tools
are run (like adding models to the database for example). Applications are registered by adding them to
the INSTALLED_APPS list in the project settings.

Open the project settings file, django_projects/locallibrary/locallibrary/settings.py, and find the definition for
the INSTALLED_APPS list. Then add a new line at the end of the list, as shown below:

INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
# Add our new application
'catalog.apps.CatalogConfig', #This object was created for us in /catalog/apps.py
]

271-CIS-3 Lab Manual - 2022 152


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The new line specifies the application configuration object (CatalogConfig) that was generated for you
in /locallibrary/catalog/apps.py when you created the application.

Note: You'll notice that there are already a lot of other INSTALLED_APPS (and MIDDLEWARE, further down in the
settings file). These enable support for the Django administration site and the functionality it uses (including sessions,
authentication, etc).

There are two other settings you won't change now, but that you should be aware of:

• SECRET_KEY. This is a secret key that is used as part of Django's website security strategy. If you're not protecting
this code in development, you'll need to use a different code (perhaps read from an environment variable or file)
when putting it into production.
• DEBUG. This enables debugging logs to be displayed on error, rather than HTTP status code responses. This should
be set to False in production as debug information is useful for attackers, but for now we can keep it set to True.

271-CIS-3 Lab Manual - 2022 153


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Specifying the database

This is also the point where you would normally specify the database to be used for the project. It makes sense to use the
same database for development and production where possible, in order to avoid minor differences in behavior. You can
find out about the different options in Databases (Django docs).

We'll use the SQLite database for this example, because we don't expect to require a lot of concurrent access on a
demonstration database, and it requires no additional work to set up! You can see how this database is configured
in settings.py:

DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': BASE_DIR / 'db.sqlite3',
}
}

Hooking up the URL mapper

The website is created with a URL mapper file (urls.py) in the project folder. While you can use this file to manage all
your URL mappings, it is more usual to defer mappings to the associated application.

Open locallibrary/locallibrary/urls.py and note the instructional text which explains some of the ways to use the
URL mapper.

"""locallibrary URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/3.1/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
from django.contrib import admin
from django.urls import path

urlpatterns = [
path('admin/', admin.site.urls),
]

271-CIS-3 Lab Manual - 2022 154


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

To add a new list item to the urlpatterns list, add the following lines to the bottom of the file. This new item includes
a path() that forwards requests with the pattern catalog/ to the module catalog.urls (the file with the relative
URL catalog/urls.py).

# Use include() to add paths from the catalog application


from django.urls import include

urlpatterns += [
path('catalog/', include('catalog.urls')),
]
Note: Note that we included the import line (from django.urls import include) with the code that uses it (so it is
easy to see what we've added), but it is common to include all your import lines at the top of a Python file.

Now let's redirect the root URL of our site (i.e. 127.0.0.1:8000) to the URL 127.0.0.1:8000/catalog/. This is the
only app we'll be using in this project. To do this, we'll use a special view function, RedirectView, which takes the new
relative URL to redirect to (/catalog/) as its first argument when the URL pattern specified in the path() function is
matched (the root URL, in this case).

Add the following lines to the bottom of the file:

#Add URL maps to redirect the base URL to our application


from django.views.generic import RedirectView
urlpatterns += [
path('', RedirectView.as_view(url='catalog/', permanent=True)),
]

Django does not serve static files like CSS, JavaScript, and images by default, but it can be useful for the development
web server to do so while you're creating your site. As a final addition to this URL mapper, you can enable the serving of
static files during development by appending the following lines.

Add the following final block to the bottom of the file now:

# Use static() to add url mapping to serve static files during development (only)
from django.conf import settings
from django.conf.urls.static import static

urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)

271-CIS-3 Lab Manual - 2022 155


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

As a final step, create a file inside your catalog folder called urls.py, and add the following text to define the (empty)
imported urlpatterns. This is where we'll add our patterns as we build the application.

from django.urls import path


from . import views

urlpatterns = [

Running database migrations

Django uses an Object-Relational-Mapper (ORM) to map model definitions in the Django code to the data structure used
by the underlying database. As we change our model definitions, Django tracks the changes and can create database
migration scripts (in /locallibrary/catalog/migrations/) to automatically migrate the underlying data structure in the
database to match the model.

When we created the website, Django automatically added a number of models for use by the admin section of the site
(which we'll look at later). Run the following commands to define tables for those models in the database (make sure you
are in the directory that contains manage.py):

python3 manage.py makemigrations


python3 manage.py migrate

Warning: You'll need to run these commands every time your models change in a way that will affect the structure of the
data that needs to be stored (including both addition and removal of whole models and individual fields).

• The makemigrations command creates (but does not apply) the migrations for all applications installed in your
project. You can specify the application name as well to just run a migration for a single project. This gives you a
chance to check out the code for these migrations before they are applied. If you're a Django expert, you may
choose to tweak them slightly!
• The migrate command is what applies the migrations to your database. Django tracks which ones have been
added to the current database.

271-CIS-3 Lab Manual - 2022 156


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Running the website

During development, you can serve the website first using the development web server, and then viewing it on your
local web browser.

• Run the development web server by calling the runserver command (in the same directory as manage.py):
python3 manage.py runserver

Performing system checks...

System check identified no issues (0 silenced).


August 15, 2018 - 16:11:26
Django version 2.1, using settings 'locallibrary.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CTRL-BREAK.

Once the server is running, you can view the site by navigating to http://127.0.0.1:8000/ in your local web browser.
You should see a site error page that looks like this:

Don't worry! This error page is expected because we don't have any pages/urls defined in the catalog.urls module
(which we're redirected to when we get a URL to the root of the site).

271-CIS-3 Lab Manual - 2022 157


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-23 Web application development with Python: Django framework (cont.)

Django Tutorial: Using models

Model definition

Models are usually defined in an application's models.py file. They are implemented as subclasses
of django.db.models.Model, and can include fields, methods and metadata. The code fragment below shows a "typical"
model, named MyModelName:

from django.db import models

class MyModelName(models.Model):
"""A typical class defining a model, derived from the Model class."""

# Fields
my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')
...

# Metadata
class Meta:
ordering = ['-my_field_name']

# Methods
def get_absolute_url(self):
"""Returns the url to access a particular instance of MyModelName."""
return reverse('model-detail-view', args=[str(self.id)])

def __str__(self):
"""String for representing the MyModelName object (in Admin site etc.)."""
return self.my_field_name
271-CIS-3 Lab Manual - 2022 158
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

In the below sections we'll explore each of the features inside the model in detail:

Fields

A model can have an arbitrary number of fields, of any type — each one represents a column of data that we want to store
in one of our database tables. Each database record (row) will consist of one of each field value. Let's look at the example
seen below:

my_field_name = models.CharField(max_length=20, help_text='Enter field documentation')

Common field arguments

help_text Provides a text label for HTML forms (e.g. in the admin site), as described above.
A human-readable name for the field used in field labels. If not specified, Django
verbose_name
will infer the default verbose name from the field name.
The default value for the field. This can be a value or a callable object, in which
default
case the object will be called every time a new record is created.
If True, Django will store blank values as NULL in the database for fields where
null this is appropriate (a CharField will instead store an empty string). The default
is False.
If True, the field is allowed to be blank in your forms. The default is False,
which means that Django's form validation will force you to enter a value. This is
blank
often used with null=True , because if you're going to allow blank values, you
also want the database to be able to represent them appropriately.
A group of choices for this field. If this is provided, the default corresponding
choices form widget will be a select box with these choices instead of the standard text
field.
If True, sets the current field as the primary key for the model (A primary key is a
special database column designated to uniquely identify all the different table
primary_key
records). If no field is specified as the primary key then Django will automatically
add a field for this purpose.

271-CIS-3 Lab Manual - 2022 159


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Common field types

The following list describes some of the more commonly used types of fields.

is used to define short-to-mid sized fixed-length strings. You must specify


CharField
the max_length of the data to be stored.
is used for large arbitrary-length strings. You may specify a max_length for the
TextField field, but this is used only when the field is displayed in forms (it is not enforced
at the database level).
is a field for storing integer (whole number) values, and for validating entered
IntegerField
values as integers in forms.
are used for storing/representing dates and date/time information (as
Python datetime.date in and datetime.datetime objects, respectively). These fields
DateField can additionally declare the (mutually exclusive) parameters auto_now=True (to
DateTimeField set the field to the current date every time the model is saved), auto_now_add (to
only set the date when the model is first created) , and default (to set a default
date that can be overridden by the user).
EmailField is used to store and validate email addresses.
are used to upload files and images respectively (the ImageField adds additional
FileField validation that the uploaded file is an image). These have parameters to define
ImageField how and where the uploaded files are stored.

is a special type of IntegerField that automatically increments. A primary key of


AutoField
this type is automatically added to your model if you don’t explicitly specify one.
is used to specify a one-to-many relationship to another database model (e.g. a
car has one manufacturer, but a manufacturer can make many cars). The "one"
ForeignKey side of the relationship is the model that contains the "key" (models containing a
"foreign key" referring to that "key", are on the "many" side of such a
relationship).
is used to specify a many-to-many relationship (e.g. a book can have several
genres, and each genre can contain several books). In our library app we will use
these very similarly to ForeignKeys, but they can be used in more complicated
ManyToManyField
ways to describe the relationships between groups. These have the
parameter on_delete to define what happens when the associated record is
deleted (e.g. a value of models.SET_NULL would set the value to NULL).

Methods

A model can also have methods.

Minimally, in every model you should define the standard Python class method __str__() to return a
human-readable string for each object. This string is used to represent individual records in the administration site
(and anywhere else you need to refer to a model instance). Often this will return a title or name field from the model.

def __str__(self):
return self.field_name

271-CIS-3 Lab Manual - 2022 160


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Another common method to include in Django models is get_absolute_url(), which returns a URL for displaying
individual model records on the website (if you define this method then Django will automatically add a "View on Site"
button to the model's record editing screens in the Admin site). A typical pattern for get_absolute_url() is shown
below.

def get_absolute_url(self):
"""Returns the url to access a particular instance of the model."""
return reverse('model-detail-view', args=[str(self.id)])

Model management

Once you've defined your model classes you can use them to create, update, or delete records, and to run queries to get all
records or particular subsets of records. We'll show you how to do that in the tutorial when we define our views, but here
is a brief summary.

Creating and modifying records

To create a record you can define an instance of the model and then call save().

# Create a new record using the model's constructor.


record = MyModelName(my_field_name="Instance #1")

# Save the object into the database.


record.save()
You can access the fields in this new record using the dot syntax, and change the values. You have to call save() to store
modified values to the database.

# Access model field values using Python attributes.


print(record.id) # should return 1 for the first record.
print(record.my_field_name) # should print 'Instance #1'

# Change record by modifying the fields, then calling save().


record.my_field_name = "New Instance Name"
record.save()

Searching for records

You can search for records that match certain criteria using the model's objects attribute (provided by the base class).

We can get all records for a model as a QuerySet, using objects.all(). The QuerySet is an iterable object, meaning
that it contains a number of objects that we can iterate/loop through.

all_books = Book.objects.all()

271-CIS-3 Lab Manual - 2022 161


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Django's filter() method allows us to filter the returned QuerySet to match a specified text or numeric field against
particular criteria. For example, to filter for books that contain "wild" in the title and then count them, we could do the
following.

wild_books = Book.objects.filter(title__contains='wild')
number_wild_books = wild_books.count()
The fields to match and the type of match are defined in the filter parameter name, using the
format: field_name__match_type (note the double underscore between title and contains above). Above we're
filtering title with a case-sensitive match. There are many other types of matches you can do: icontains (case
insensitive), iexact (case-insensitive exact match), exact (case-sensitive exact match) and in, gt (greater
than), startswith, etc. The full list is here.

In some cases you'll need to filter on a field that defines a one-to-many relationship to another model (e.g. a ForeignKey).
In this case you can "index" to fields within the related model with additional double underscores. So for example to filter
for books with a specific genre pattern, you will have to index to the name through the genre field, as shown below:

# Will match on: Fiction, Science fiction, non-fiction etc.


books_containing_genre = Book.objects.filter(genre__name__icontains='fiction')
There is a lot more you can do with queries, including backwards searches from related models, chaining filters, returning
a smaller set of values etc. For more information see Making queries (Django Docs).

271-CIS-3 Lab Manual - 2022 162


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Defining the LocalLibrary Models

In this section we will start defining the models for the library. Open models.py (in /locallibrary/catalog/). The
boilerplate at the top of the page imports the models module, which contains the model base class models.Model that our
models will inherit from.

from django.db import models

# Create your models here.

Genre model

Copy the Genre model code shown below and paste it into the bottom of your models.py file. This model is used to store
information about the book category — for example whether it is fiction or non-fiction, romance or military history, etc.
As mentioned above, we've created the Genre as a model rather than as free text or a selection list so that the possible
values can be managed through the database rather than being hard coded.

class Genre(models.Model):
"""Model representing a book genre."""
name = models.CharField(max_length=200, help_text='Enter a book genre (e.g. Science Fiction)')

def __str__(self):
"""String for representing the Model object."""
return self.name
The model has a single CharField field (name), which is used to describe the genre (this is limited to 200 characters and
has some help_text. At the end of the model we declare a __str__() method, which returns the name of the genre
defined by a particular record. No verbose name has been defined, so the field will be called Name in forms.

Book model

Copy the Book model below and again paste it into the bottom of your file. The Book model represents all information
about an available book in a general sense, but not a particular physical "instance" or "copy" available for loan. The model
uses a CharField to represent the book's title and isbn . For isbn, note how the first unnamed parameter explicitly sets the
label as "ISBN" (otherwise it would default to "Isbn"). We also set parameter unique as true in order to ensure all books
have a unique ISBN (the unique parameter makes the field value globally unique in a table). The model uses TextField for
the summary, because this text may need to be quite long.

271-CIS-3 Lab Manual - 2022 163


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

from django.urls import reverse # Used to generate URLs by reversing the URL patterns

class Book(models.Model):
"""Model representing a book (but not a specific copy of a book)."""
title = models.CharField(max_length=200)

# Foreign Key used because book can only have one author, but authors can have multiple books
# Author as a string rather than object because it hasn't been declared yet in the file
author = models.ForeignKey('Author', on_delete=models.SET_NULL, null=True)

summary = models.TextField(max_length=1000, help_text='Enter a brief description of the book')


isbn = models.CharField('ISBN', max_length=13, unique=True,
help_text='13 Character <a href="https://www.isbn-
international.org/content/what-isbn">ISBN number</a>')

# ManyToManyField used because genre can contain many books. Books can cover many genres.
# Genre class has already been defined so we can specify the object above.
genre = models.ManyToManyField(Genre, help_text='Select a genre for this book')

def __str__(self):
"""String for representing the Model object."""
return self.title

def get_absolute_url(self):
"""Returns the url to access a detail record for this book."""
return reverse('book-detail', args=[str(self.id)])

The genre is a ManyToManyField, so that a book can have multiple genres and a genre can have many books. The author
is declared as ForeignKey, so each book will only have one author, but an author may have many books (in practice a
book might have multiple authors, but not in this implementation!)

In both field types the related model class is declared as the first unnamed parameter using either the model class or a
string containing the name of the related model. You must use the name of the model as a string if the associated class has
not yet been defined in this file before it is referenced! The other parameters of interest in the author field are null=True,
which allows the database to store a Null value if no author is selected, and on_delete=models.SET_NULL, which will set
the value of the book's author field to Null if the associated author record is deleted.

The model also defines __str__() , using the book's title field to represent a Book record. The final
method, get_absolute_url() returns a URL that can be used to access a detail record for this model (for this to work we
will have to define a URL mapping that has the name book-detail, and define an associated view and template).

BookInstance model

Next, copy the BookInstance model (shown below) under the other models. The BookInstance represents a
specific copy of a book that someone might borrow, and includes information about whether the copy is

271-CIS-3 Lab Manual - 2022 164


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

available or on what date it is expected back, "imprint" or version details, and a unique id for the book in the
library.

Some of the fields and methods will now be familiar. The model uses:

• ForeignKey to identify the associated Book (each book can have many copies, but a copy can only have
one Book). The key specifies on_delete=models.RESTRICT to ensure that the Book cannot be deleted while
referenced by a BookInstance.
• CharField to represent the imprint (specific release) of the book.
import uuid # Required for unique book instances

class BookInstance(models.Model):
"""Model representing a specific copy of a book (i.e. that can be borrowed from the
library)."""
id = models.UUIDField(primary_key=True, default=uuid.uuid4, help_text='Unique ID for this
particular book across whole library')
book = models.ForeignKey('Book', on_delete=models.RESTRICT, null=True)
imprint = models.CharField(max_length=200)
due_back = models.DateField(null=True, blank=True)

LOAN_STATUS = (
('m', 'Maintenance'),
('o', 'On loan'),
('a', 'Available'),
('r', 'Reserved'),
)

status = models.CharField(
max_length=1,
choices=LOAN_STATUS,
blank=True,
default='m',
help_text='Book availability',
)

class Meta:
ordering = ['due_back']

def __str__(self):
"""String for representing the Model object."""
return f'{self.id} ({self.book.title})'

271-CIS-3 Lab Manual - 2022 165


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

We additionally declare a few new types of field:

• UUIDField is used for the id field to set it as the primary_key for this model. This type of field allocates a
globally unique value for each instance (one for every book you can find in the library).
• DateField is used for the due_back date (at which the book is expected to become available after being borrowed
or in maintenance). This value can be blank or null (needed for when the book is available). The model metadata
(Class Meta) uses this field to order records when they are returned in a query.
• status is a CharField that defines a choice/selection list. As you can see, we define a tuple containing tuples of
key-value pairs and pass it to the choices argument. The value in a key/value pair is a display value that a user can
select, while the keys are the values that are actually saved if the option is selected. We've also set a default value
of 'm' (maintenance) as books will initially be created unavailable before they are stocked on the shelves.
The method __str__() represents the BookInstance object using a combination of its unique id and the
associated Book's title.

Author model

Copy the Author model (shown below) underneath the existing code in models.py.

class Author(models.Model):
"""Model representing an author."""
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)

class Meta:
ordering = ['last_name', 'first_name']

def get_absolute_url(self):
"""Returns the url to access a particular author instance."""
return reverse('author-detail', args=[str(self.id)])

def __str__(self):
"""String for representing the Model object."""
return f'{self.last_name}, {self.first_name}'
All of the fields/methods should now be familiar. The model defines an author as having a first name, last name, and dates
of birth and death (both optional). It specifies that by default the __str__() returns the name in last
name, firstname order. The get_absolute_url() method reverses the author-detail URL mapping to get the URL
for displaying an individual author.

271-CIS-3 Lab Manual - 2022 166


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Re-run the database migrations

All your models have now been created. Now re-run your database migrations to add them to your database.

python3 manage.py makemigrations


python3 manage.py migrate

271-CIS-3 Lab Manual - 2022 167


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-24 Web application development with Python: Django framework (cont.)

Django Tutorial: Django admin site


Registering models

First, open admin.py in the catalog application (/locallibrary/catalog/admin.py). It currently looks like this — note
that it already imports django.contrib.admin:

from django.contrib import admin

# Register your models here.


Register the models by copying the following text into the bottom of the file. This code imports the models and then
calls admin.site.register to register each of them.

from .models import Author, Genre, Book, BookInstance

admin.site.register(Book)
admin.site.register(Author)
admin.site.register(Genre)
admin.site.register(BookInstance)
This is the simplest way of registering a model, or models, with the site. The admin site is highly customisable, and we'll
talk more about the other ways of registering your models further down.

Creating a superuser

In order to log into the admin site, we need a user account with Staff status enabled. In order to view and create records
we also need this user to have permissions to manage all our objects. You can create a "superuser" account that has full
access to the site and all needed permissions using manage.py.

Call the following command, in the same directory as manage.py, to create the superuser. You will be prompted to enter
a username, email address, and strong password.

python3 manage.py createsuperuser

Once this command completes a new superuser will have been added to the database. Now restart the development server
so we can test the login:

python3 manage.py runserver

Logging in and using the site


271-CIS-3 Lab Manual - 2022 168
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

To login to the site, open the /admin URL (e.g. http://127.0.0.1:8000/admin) and enter your new superuser userid and
password credentials (you'll be redirected to the login page, and then back to the /admin URL after you've entered your
details).

This part of the site displays all our models, grouped by installed application. You can click on a model name to go to a
screen that lists all its associated records, and you can further click on those records to edit them. You can also directly
click the Add link next to each model to start creating a record of that type.

Click on the Add link to the right of Books to create a new book (this will display a dialog much like the one below).
Note how the titles of each field, the type of widget used, and the help_text (if any) match the values you specified in the
model.

Enter values for the fields. You can create new authors or genres by pressing the + button next to the respective fields (or
select existing values from the lists if you've already created them). When you're done you can press SAVE, Save and
add another, or Save and continue editing to save the record.

271-CIS-3 Lab Manual - 2022 169


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Note: At this point we'd like you to spend some time adding a few books, authors, and genres (e.g. Fantasy) to your
application. Make sure that each author and genre includes a couple of different books (this will make your list and detail
views more interesting when we implement them later on in the article series).

When you've finished adding books, click on the Home link in the top bookmark to be taken back to the main admin
page. Then click on the Books link to display the current list of books (or on one of the other links to see other model
lists). Now that you've added a few books, the list might look similar to the screenshot below. The title of each book is
displayed; this is the value returned in the Book model's __str__() method that we specified in the last article.

271-CIS-3 Lab Manual - 2022 170


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

From this list you can delete books by selecting the checkbox next to the book you don't want, selecting
the delete... action from the Action drop-down list, and then pressing the Go button. You can also add new books by
pressing the ADD BOOK button.

You can edit a book by selecting its name in the link. The edit page for a book, shown below, is almost identical to the
"Add" page. The main differences are the page title (Change book) and the addition of Delete, HISTORY and VIEW
ON SITE buttons (this last button appears because we defined the get_absolute_url() method in our model).

271-CIS-3 Lab Manual - 2022 171


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Now navigate back to the Home page (using the Home link in the breadcrumb trail) and then view
the Author and Genre lists — you should already have quite a few created from when you added the new books, but feel
free to add some more.

What you won't have is any Book Instances, because these are not created from Books (although you can create
a Book from a BookInstance — this is the nature of the ForeignKey field). Navigate back to the Home page and press
the associated Add button to display the Add book instance screen below. Note the large, globally unique Id, which can
be used to separately identify a single copy of a book in the library.

Create a number of these records for each of your books. Set the status as Available for at least some records and On
loan for others. If the status is not Available, then also set a future Due back date.

That's it! You've now learned how to set up and use the administration site. You've also created records
for Book, BookInstance, Genre, and Author that we'll be able to use once we create our own views and templates.

271-CIS-3 Lab Manual - 2022 172


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Advanced configuration

Django does a pretty good job of creating a basic admin site using the information from the registered models:

• Each model has a list of individual records, identified by the string created with
the model's __str__() method, and linked to detail views/forms for editing. By default, this view has an action
menu at the top that you can use to perform bulk delete operations on records.
• The model detail record forms for editing and adding records contain all the fields in the model, laid out vertically
in their declaration order.
You can further customise the interface to make it even easier to use. Some of the things you can do are:

• List views:
o Add additional fields/information displayed for each record.
o Add filters to select which records are listed, based on date or some other selection value (e.g. Book loan
status).
o Add additional options to the actions menu in list views and choose where this menu is displayed on the
form.
• Detail views
o Choose which fields to display (or exclude), along with their order, grouping, whether they are editable,
the widget used, orientation etc.
o Add related fields to a record to allow inline editing (e.g. add the ability to add and edit book records
while you're creating their author record).
In this section we're going to look at a few changes that will improve the interface for our LocalLibrary, including adding
more information to Book and Author model lists, and improving the layout of their edit views. We won't change
the Language and Genre model presentation because they only have one field each, so there is no real benefit in doing so!

You can find a complete reference of all the admin site customisation choices in The Django Admin site (Django Docs).

271-CIS-3 Lab Manual - 2022 173


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Register a ModelAdmin class

To change how a model is displayed in the admin interface you define a ModelAdmin class (which describes the layout)
and register it with the model.

Let's start with the Author model. Open admin.py in the catalog application (/locallibrary/catalog/admin.py).
Comment out your original registration (prefix it with a #) for the Author model:

# admin.site.register(Author)

Now add a new AuthorAdmin and registration as shown below.

# Define the admin class


class AuthorAdmin(admin.ModelAdmin):
pass

# Register the admin class with the associated model


admin.site.register(Author, AuthorAdmin)
Now we'll add ModelAdmin classes for Book, and BookInstance. We again need to comment out the original registrations:

# admin.site.register(Book)

# admin.site.register(BookInstance)

Now to create and register the new models; for the purpose of this demonstration, we'll instead use
the @register decorator to register the models (this does exactly the same thing as the admin.site.register() syntax):

# Register the Admin classes for Book using the decorator


@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
pass

# Register the Admin classes for BookInstance using the decorator


@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):

pass

Currently all of our admin classes are empty (see pass) so the admin behavior will be unchanged! We can now extend
these to define our model-specific admin behavior.

271-CIS-3 Lab Manual - 2022 174


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Configure list views

The LocalLibrary currently lists all authors using the object name generated from the model __str__() method. This is
fine when you only have a few authors, but once you have many you may end up having duplicates. To differentiate them,
or just because you want to show more interesting information about each author, you can use list_display to add
additional fields to the view.

Replace your AuthorAdmin class with the code below. The field names to be displayed in the list are declared in a tuple in
the required order, as shown (these are the same names as specified in your original model).

class AuthorAdmin(admin.ModelAdmin):

list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')

Now navigate to the author list in your website. The fields above should now be displayed, like so:

For our Book model we'll additionally display the author and genre. The author is a ForeignKey field (one-to-many)
relationship, and so will be represented by the __str__() value for the associated record. Replace the BookAdmin class
with the version below.

class BookAdmin(admin.ModelAdmin):

list_display = ('title', 'author', 'display_genre')

Unfortunately we can't directly specify the genre field in list_display because it is a ManyToManyField (Django
prevents this because there would be a large database access "cost" in doing so). Instead we'll define
a display_genre function to get the information as a string (this is the function we've called above; we'll define it below).

271-CIS-3 Lab Manual - 2022 175


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Note: Getting the genre may not be a good idea here, because of the "cost" of the database operation. We're showing you
how because calling functions in your models can be very useful for other reasons — for example to add a Delete link
next to every item in the list.

Add the following code into your Book model (models.py). This creates a string from the first three values of
the genre field (if they exist) and creates a short_description that can be used in the admin site for this method.

def display_genre(self):
"""Create a string for the Genre. This is required to display genre in Admin."""
return ', '.join(genre.name for genre in self.genre.all()[:3])

display_genre.short_description = 'Genre'
After saving the model and updated admin, open your website and go to the Books list page; you should see a book list
like the one below:

The Genre model (and the Language model, if you defined one) both have a single field, so there is no point creating an
additional model for them to display additional fields.

Note: It is worth updating the BookInstance model list to show at least the status and the expected return date.
We've added that as a challenge at the end of this article!

271-CIS-3 Lab Manual - 2022 176


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Add list filters

Once you've got a lot of items in a list, it can be useful to be able to filter which items are displayed. This is done by
listing fields in the list_filter attribute. Replace your current BookInstanceAdmin class with the code fragment below.

class BookInstanceAdmin(admin.ModelAdmin):

list_filter = ('status', 'due_back')

The list view will now include a filter box to the right. Note how you can choose dates and status to filter the values:

Organize detail view layout

By default, the detail views lay out all fields vertically, in their order of declaration in the model. You can change the
order of declaration, which fields are displayed (or excluded), whether sections are used to organize the information,
whether fields are displayed horizontally or vertically, and even what edit widgets are used in the admin forms.

Note: The LocalLibrary models are relatively simple so there isn't a huge need for us to change the layout; we'll make
some changes anyway however, just to show you how.

Controlling which fields are displayed and laid out

Update your AuthorAdmin class to add the fields line, as shown below:
271-CIS-3 Lab Manual - 2022 177
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

class AuthorAdmin(admin.ModelAdmin):
list_display = ('last_name', 'first_name', 'date_of_birth', 'date_of_death')

fields = ['first_name', 'last_name', ('date_of_birth', 'date_of_death')]


The fields attribute lists just those fields that are to be displayed on the form, in order. Fields are displayed vertically by
default, but will display horizontally if you further group them in a tuple (as shown in the "date" fields above).

In your website go to the author detail view — it should now appear as shown below:

Note: You can also use the exclude attribute to declare a list of attributes to be excluded from the form (all other
attributes in the model will be displayed).

Sectioning the detail view

You can add "sections" to group related model information within the detail form, using the fieldsets attribute.

In the BookInstance model we have information related to what the book is (i.e. name, imprint, and id) and when it will
be available (status, due_back). We can add these to our BookInstanceAdmin class as shown below, using
the fieldsets property.

@admin.register(BookInstance)
class BookInstanceAdmin(admin.ModelAdmin):
list_filter = ('status', 'due_back')

fieldsets = (
(None, {
'fields': ('book', 'imprint', 'id')
}),
('Availability', {
'fields': ('status', 'due_back')
}),
)
Each section has its own title (or None, if you don't want a title) and an associated tuple of fields in a dictionary — the
format is complicated to describe, but fairly easy to understand if you look at the code fragment immediately above.
271-CIS-3 Lab Manual - 2022 178
Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Now navigate to a book instance view in your website; the form should appear as shown below:

Inline editing of associated records

Sometimes it can make sense to be able to add associated records at the same time. For example, it may make
sense to have both the book information and information about the specific copies you've got on the same detail
page.

You can do this by declaring inlines, of type TabularInline (horizontal layout) or StackedInline (vertical layout,
just like the default model layout). You can add the BookInstance information inline to our Book detail by
specifiying inlines in your BookAdmin:

class BooksInstanceInline(admin.TabularInline):
model = BookInstance

@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'author', 'display_genre')

inlines = [BooksInstanceInline]

271-CIS-3 Lab Manual - 2022 179


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Now navigate to a view for a Book in your website — at the bottom you should now see the book instances relating to this
book (immediately below the book's genre fields):

In this case all we've done is declare our tabular inline class, which just adds all fields from the inlined model. You can
specify all sorts of additional information for the layout, including the fields to display, their order, whether they are read
only or not, etc.

271-CIS-3 Lab Manual - 2022 180


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-25 Web application development with Python: Django framework (cont.)

Django Tutorial: Creating our home page

Defining the resource URLs

As this version of LocalLibrary is essentially read-only for end users, we just need to provide a landing page for the site
(a home page), and pages that display list and detail views for books and authors.

The URLs that we'll need for our pages are:

• catalog/ — The home (index) page.


• catalog/books/ — A list of all books.
• catalog/authors/ — A list of all authors.
• catalog/book/<id> — The detail view for a particular book, with a field primary key of <id> (the default). For
example, the URL for the third book added to the list will be /catalog/book/3.
• catalog/author/<id> — The detail view for the specific author with a primary key field of <id>. For example,
the URL for the 11th author added to the list will be /catalog/author/11.
• The first three URLs will return the index page, books list, and authors list. These URLs do not encode any
additional information, and the queries that fetch data from the database will always be the same. However, the
results that the queries return will depend on the contents of the database.
By contrast the final two URLs will display detailed information about a specific book or author. These URLs encode the
identity of the item to display (represented by <id> above). The URL mapper will extract the encoded information and
pass it to the view, and the view will dynamically determine what information to get from the database. By encoding the
information in the URL we will use a single set of a url mapping, a view, and a template to handle all books (or authors).

271-CIS-3 Lab Manual - 2022 181


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Creating the index page

The first page we'll create is the index page (catalog/). The index page will include some static HTML, along with
generated "counts" of different records in the database. To make this work we'll create a URL mapping, a view, and a
template.

Note: It's worth paying a little extra attention in this section. Most of the information also applies to the other pages we'll
create.

URL mapping

When we created the skeleton website, we updated the locallibrary/urls.py file to ensure that whenever a URL that
starts with catalog/ is received, the URLConf module catalog.urls will process the remaining substring.

The following code snippet from locallibrary/urls.py includes the catalog.urls module:

urlpatterns += [
path('catalog/', include('catalog.urls')),
]
Note: Whenever Django encounters the import function django.urls.include(), it splits the URL string at the
designated end character and sends the remaining substring to the included URLconf module for further processing.

We also created a placeholder file for the URLConf module, named /catalog/urls.py. Add the following lines to that
file:

urlpatterns = [
path('', views.index, name='index'),
]
The path() function defines the following:

• A URL pattern, which is an empty string: ''. We'll discuss URL patterns in detail when working on the other
views.
• A view function that will be called if the URL pattern is detected: views.index, which is the
function named index() in the views.py file.
The path() function also specifies a name parameter, which is a unique identifier for this particular URL mapping. You
can use the name to "reverse" the mapper, i.e. to dynamically create a URL that points to the resource that the mapper is
designed to handle. For example, we can use the name parameter to link to our home page from any other page by adding
the following link in a template:

<a href="{% url 'index' %}">Home</a>.

271-CIS-3 Lab Manual - 2022 182


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

View (function-based)

A view is a function that processes an HTTP request, fetches the required data from the database, renders the data in an
HTML page using an HTML template, and then returns the generated HTML in an HTTP response to display the page to
the user. The index view follows this model — it fetches information about the number of Book, BookInstance,
available BookInstance and Author records that we have in the database, and passes that information to a template for
display.

Open catalog/views.py and note that the file already imports the render() shortcut function to generate an HTML
file using a template and data:

from django.shortcuts import render

# Create your views here.


Paste the following lines at the bottom of the file:

from .models import Book, Author, BookInstance, Genre

def index(request):
"""View function for home page of site."""

# Generate counts of some of the main objects


num_books = Book.objects.all().count()
num_instances = BookInstance.objects.all().count()

# Available books (status = 'a')


num_instances_available = BookInstance.objects.filter(status__exact='a').count()

# The 'all()' is implied by default.


num_authors = Author.objects.count()

context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
}

# Render the HTML template index.html with the data in the context variable
return render(request, 'index.html', context=context)

271-CIS-3 Lab Manual - 2022 183


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The first line imports the model classes that we'll use to access data in all our views.

The first part of the view function fetches the number of records using the objects.all() attribute on the model classes.
It also gets a list of BookInstance objects that have a value of 'a' (Available) in the status field. You can find more
information about how to access model data in our previous tutorial Django Tutorial: Using models > Searching for
records.

At the end of the view function we call the render() function to create an HTML page and return the page as a response.
This shortcut function wraps a number of other functions to simplify a very common use case. The render() function
accepts the following parameters:

• the original request object, which is an HttpRequest.


• an HTML template with placeholders for the data.
• a context variable, which is a Python dictionary, containing the data to insert into the placeholders.
We'll talk more about templates and the context variable in the next section. Let's get to creating our template so we can
actually display something to the user!

Template

A template is a text file that defines the structure or layout of a file (such as an HTML page), it uses placeholders to
represent actual content.

A Django application created using startapp (like the skeleton of this example) will look for templates in a subdirectory
named 'templates' of your applications. For example, in the index view that we just added, the render() function will
expect to find the file index.html in /locallibrary/catalog/templates/ and will raise an error if the file is not present.

You can check this by saving the previous changes and accessing 127.0.0.1:8000 in your browser - it will display a
fairly intuitive error message: "TemplateDoesNotExist at /catalog/", and other details.

Note: Based on your project's settings file, Django will look for templates in a number of places, searching in your
installed applications by default. You can find out more about how Django finds templates and what template formats it
supports in the Templates section of the Django documentation.

271-CIS-3 Lab Manual - 2022 184


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Extending templates

The index template will need standard HTML markup for the head and body, along with navigation sections to link to the
other pages of the site (which we haven't created yet), and to sections that display introductory text and book data.

Much of the HTML and navigation structure will be the same in every page of our site. Instead of duplicating boilerplate
code on every page, you can use the Django templating language to declare a base template, and then extend it
to replace just the bits that are different for each specific page.

The following code snippet is a sample base template from a base_generic.html file. We'll be creating the template for
LocalLibrary shortly. The sample below includes common HTML with sections for a title, a sidebar, and main contents
marked with the named block and endblock template tags. You can leave the blocks empty, or include default content to
use when rendering pages derived from the template.

Note: Template tags are functions that you can use in a template to loop through lists, perform conditional operations
based on the value of a variable, and so on. In addition to template tags, the template syntax allows you to reference
variables that are passed into the template from the view, and use template filters to format variables (for example, to
convert a string to lower case).

<!DOCTYPE html>
<html lang="en">
<head>
{% block title %}<title>Local Library</title>{% endblock %}
</head>
<body>
{% block sidebar %}<!-- insert default navigation text for every page -->{% endblock %}
{% block content %}<!-- default content text (typically empty) -->{% endblock %}
</body>
</html>
When defining a template for a particular view, we first specify the base template using the extends template tag — see
the code sample below. Then we declare what sections from the template we want to replace (if any),
using block/endblock sections as in the base template.

For example, the code snippet below shows how to use the extends template tag and override the content block. The
generated HTML will include the code and structure defined in the base template, including the default content
you defined in the title block, but the new content block in place of the default one.

271-CIS-3 Lab Manual - 2022 185


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

{% extends "base_generic.html" %}

{% block content %}
<h1>Local Library Home</h1>
<p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p>
{% endblock %}

The LocalLibrary base template

We will use the following code snippet as the base template for the LocalLibrary website. As you can see, it contains
some HTML code and defines blocks for title, sidebar, and content. We have a default title and a default sidebar with
links to lists of all books and authors, both enclosed in blocks to be easily changed in the future.

Note: We also introduce two additional template tags: url and load static. These tags will be explained in following
sections.

Create a new file **base_generic.html **in /locallibrary/catalog/templates/ and paste the following code to the file:

<!DOCTYPE html>
<html lang="en">
<head>
{% block title %}<title>Local Library</title>{% endblock %}
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet"
href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" integrity="sha384-
TX8t27EcRE3e/ihU7zmQxVncDAy5uIKz4rEkgIXeMed4M0jlfIDPvg6uqKI2xXr2" crossorigin="anonymous">
<!-- Add additional CSS in static file -->
{% load static %}
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
</head>
<body>
<div class="container-fluid">
<div class="row">
<div class="col-sm-2">
{% block sidebar %}
<ul class="sidebar-nav">
<li><a href="{% url 'index' %}">Home</a></li>
<li><a href="">All books</a></li>
<li><a href="">All authors</a></li>
</ul>
{% endblock %}
</div>
<div class="col-sm-10 ">{% block content %}{% endblock %}</div>
</div>
</div>
</body>
</html>

271-CIS-3 Lab Manual - 2022 186


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The template includes CSS from Bootstrap to improve the layout and presentation of the HTML page. Using Bootstrap
(or another client-side web framework) is a quick way to create an attractive page that displays well on different screen
sizes.

The base template also references a local css file (styles.css) that provides additional styling. Create a styles.css file
in /locallibrary/catalog/static/css/ and paste the following code in the file:

.sidebar-nav {

margin-top: 20px;

padding: 0;

list-style: none;

The index template

Create a new HTML file **index.html **in /locallibrary/catalog/templates/ and paste the following code in the file.
This code extends our base template on the first line, and then replaces the default content block for the template.

{% extends "base_generic.html" %}

{% block content %}
<h1>Local Library Home</h1>
<p>Welcome to LocalLibrary, a website developed by <em>Mozilla Developer Network</em>!</p>
<h2>Dynamic content</h2>
<p>The library has the following record counts:</p>
<ul>
<li><strong>Books:</strong> {{ num_books }}</li>
<li><strong>Copies:</strong> {{ num_instances }}</li>
<li><strong>Copies available:</strong> {{ num_instances_available }}</li>
<li><strong>Authors:</strong> {{ num_authors }}</li>
</ul>
{% endblock %}
In the Dynamic content section we declare placeholders (template variables) for the information from the view that we
want to include. The variables are enclosed with double brace (handlebars).

Note: You can easily recognize template variables and template tags (functions) - variables are enclosed in double braces
({{ num_books }}), and tags are enclosed in single braces with percentage signs ({% extends "base_generic.html"
%}).

271-CIS-3 Lab Manual - 2022 187


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The important thing to note here is that variables are named with the keys that we pass into the context dictionary in
the render() function of our view (see sample below). Variables will be replaced with their associated values when the
template is rendered.

context = {
'num_books': num_books,
'num_instances': num_instances,
'num_instances_available': num_instances_available,
'num_authors': num_authors,
}

return render(request, 'index.html', context=context)

Referencing static files in templates

Your project is likely to use static resources, including JavaScript, CSS, and images. Because the location of these files
might not be known (or might change), Django allows you to specify the location in your templates relative to
the STATIC_URL global setting. The default skeleton website sets the value of STATIC_URL to '/static/', but you might
choose to host these on a content delivery network or elsewhere.

Within the template you first call the load template tag specifying "static" to add the template library, as shown in the
code sample below. You can then use the static template tag and specify the relative URL to the required file.

<!-- Add additional CSS in static file -->

{% load static %}

<link rel="stylesheet" href="{% static 'css/styles.css' %}">

You can add an image into the page in a similar way, for example:

{% load static %}

<img src="{% static 'catalog/images/local_library_model_uml.png' %}" alt="UML diagram"


style="width:555px;height:540px;">

Note: The samples above specify where the files are located, but Django does not serve them by default. We
configured the development web server to serve files by modifying the global URL mapper
(/locallibrary/locallibrary/urls.py) when we created the website skeleton, but still need to enable file serving in
production. We'll look at this later.

271-CIS-3 Lab Manual - 2022 188


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Linking to URLs

The base template above introduced the url template tag.

<li><a href="{% url 'index' %}">Home</a></li>

This tag accepts the name of a path() function called in your urls.py and the values for any arguments that the
associated view will receive from that function, and returns a URL that you can use to link to the resource.

Configuring where to find the templates

The location where Django searches for templates is specified in the TEMPLATES object in the settings.py file. The
default settings.py (as created for this tutorial) looks something like this:

TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]

The setting of 'APP_DIRS': True, is the most important, as it tells Django to search for templates in a subdirectory of
each application in the project, named "templates" (this makes it easier to group templates with their associated
application for easy re-use).

We can also specify specific locations for Django to search for directories using 'DIRS': [] (but that isn't needed yet).

Note: You can find out more about how Django finds templates and what template formats it
supports in the Templates section of the Django documentation.

271-CIS-3 Lab Manual - 2022 189


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

What does it look like?

At this point we have created all required resources to display the index page. Run the server (python3 manage.py
runserver) and open http://127.0.0.1:8000/ in your browser. If everything is configured correctly, your site should look
like the following screenshot.

Note: The All books and All authors links will not work yet because the paths, views, and templates for those pages
are not defined. We just inserted placeholders for those links in the base_generic.html template.

271-CIS-3 Lab Manual - 2022 190


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

LAB-26 Web application development with Python: Django framework (cont.)

Generic list and detail views

Book list page

The book list page will display a list of all the available book records in the page, accessed using the
URL: catalog/books/. The page will display a title and author for each record, with the title being a hyperlink to the
associated book detail page. The page will have the same structure and navigation as all other pages in the site, and we
can, therefore, extend the base template (base_generic.html) we created in the previous tutorial.

URL mapping

Open /catalog/urls.py and copy in the line setting the path for 'books/', as shown below. Just as for the index
page, this path() function defines a pattern to match against the URL ('books/'), a view function that will be
called if the URL matches (views.BookListView.as_view()), and a name for this particular mapping.

urlpatterns = [

path('', views.index, name='index'),

path('books/', views.BookListView.as_view(), name='books'),

As discussed in the previous tutorial the URL must already have matched /catalog, so the view will actually be called
for the URL: /catalog/books/.

The view function has a different format than before — that's because this view will actually be implemented as a class.
We will be inheriting from an existing generic view function that already does most of what we want this view function to
do, rather than writing our own from scratch.

For Django class-based views we access an appropriate view function by calling the class method as_view(). This does
all the work of creating an instance of the class, and making sure that the right handler methods are called for
incoming HTTP requests.

271-CIS-3 Lab Manual - 2022 191


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

View (class-based)

We could quite easily write the book list view as a regular function (just like our previous index view), which would
query the database for all books, and then call render() to pass the list to a specified template. Instead, however, we're
going to use a class-based generic list view (ListView) — a class that inherits from an existing view. Because the generic
view already implements most of the functionality we need and follows Django best-practice, we will be able to create a
more robust list view with less code, less repetition, and ultimately less maintenance.

Open catalog/views.py, and copy the following code into the bottom of the file:

from django.views import generic

class BookListView(generic.ListView):

model = Book

That's it! The generic view will query the database to get all records for the specified model (Book) then render a template
located at /locallibrary/catalog/templates/catalog/book_list.html (which we will create below). Within the
template you can access the list of books with the template variable named object_list OR book_list (i.e. generically
"the_model_name_list").

Note: This awkward path for the template location isn't a misprint — the generic views look for templates
in /application_name/the_model_name_list.html (catalog/book_list.html in this case) inside the
application's /application_name/templates/ directory (/catalog/templates/).

You can add attributes to change the default behavior above. For example, you can specify another template file if you
need to have multiple views that use this same model, or you might want to use a different template variable name
if book_list is not intuitive for your particular template use-case. Possibly the most useful variation is to change/filter the
subset of results that are returned — so instead of listing all books you might list top 5 books that were read by other
users.

class BookListView(generic.ListView):
model = Book
context_object_name = 'my_book_list' # your own name for the list as a template variable
queryset = Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title
war
template_name = 'books/my_arbitrary_template_name_list.html' # Specify your own template
name/location

271-CIS-3 Lab Manual - 2022 192


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Overriding methods in class-based views

While we don't need to do so here, you can also override some of the class methods.

For example, we can override the get_queryset() method to change the list of records returned. This is more flexible
than just setting the queryset attribute as we did in the preceding code fragment (though there is no real benefit in this
case):

class BookListView(generic.ListView):
model = Book

def get_queryset(self):
return Book.objects.filter(title__icontains='war')[:5] # Get 5 books containing the title
war
We might also override get_context_data() in order to pass additional context variables to the template (e.g. the list of
books is passed by default). The fragment below shows how to add a variable named "some_data" to the context (it would
then be available as a template variable).

class BookListView(generic.ListView):
model = Book

def get_context_data(self, **kwargs):


# Call the base implementation first to get the context
context = super(BookListView, self).get_context_data(**kwargs)
# Create any data and add it to the context
context['some_data'] = 'This is just some data'
return context
When doing this it is important to follow the pattern used above:

• First get the existing context from our superclass.


• Then add your new context information.
• Then return the new (updated) context.
Note: Check out Built-in class-based generic views (Django docs) for many more examples of what you can do.

271-CIS-3 Lab Manual - 2022 193


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Creating the List View template

Create the HTML file /locallibrary/catalog/templates/catalog/book_list.html and copy in the text below. As
discussed above, this is the default template file expected by the generic class-based list view (for a model named Book in
an application named catalog).

Templates for generic views are just like any other templates (although of course the context/information passed to the
template may differ). As with our index template, we extend our base template in the first line and then replace the block
named content.

{% extends "base_generic.html" %}

{% block content %}
<h1>Book List</h1>
{% if book_list %}
<ul>
{% for book in book_list %}
<li>
<a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{book.author}})
</li>
{% endfor %}
</ul>
{% else %}
<p>There are no books in the library.</p>
{% endif %}
{% endblock %}
The view passes the context (list of books) by default as object_list and book_list aliases; either will work.

Conditional execution

We use the if, else, and endif template tags to check whether the book_list has been defined and is not empty.
If book_list is empty, then the else clause displays text explaining that there are no books to list. If book_list is not
empty, then we iterate through the list of books.

{% if book_list %}
<!-- code here to list the books -->
{% else %}
<p>There are no books in the library.</p>
{% endif %}
The condition above only checks for one case, but you can test on additional conditions using the elif template tag
(e.g. {% elif var2 %}). For more information about conditional operators see: if, ifequal/ifnotequal,
and ifchanged in Built-in template tags and filters (Django Docs).

271-CIS-3 Lab Manual - 2022 194


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

For loops

The template uses the for and endfor template tags to loop through the book list, as shown below. Each iteration
populates the book template variable with information for the current list item.

{% for book in book_list %}

<li> <!-- code here get information from each book item --> </li>

{% endfor %}

While not used here, within the loop Django will also create other variables that you can use to track the iteration. For
example, you can test the forloop.last variable to perform conditional processing the last time that the loop is run.

Accessing variables

The code inside the loop creates a list item for each book that shows both the title (as a link to the yet-to-be-created detail
view) and the author.

<a href="{{ book.get_absolute_url }}">{{ book.title }}</a> ({{book.author}})

We access the fields of the associated book record using the "dot notation" (e.g. book.title and book.author), where
the text following the book item is the field name (as defined in the model).

We can also call functions in the model from within our template — in this case we call Book.get_absolute_url() to
get a URL you could use to display the associated detail record. This works provided the function does not have any
arguments (there is no way to pass arguments!)

Note: We have to be a little careful of "side effects" when calling functions in templates. Here we just get a URL to
display, but a function can do pretty much anything — we wouldn't want to delete our database (for example) just by
rendering our template!

271-CIS-3 Lab Manual - 2022 195


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Update the base template

Open the base template (/locallibrary/catalog/templates/base_generic.html) and insert {% url 'books' %} into
the URL link for All books, as shown below. This will enable the link in all pages (we can successfully put this in place
now that we've created the "books" URL mapper).

<li><a href="{% url 'index' %}">Home</a></li>

<li><a href="{% url 'books' %}">All books</a></li>

<li><a href="">All authors</a></li>

What does it look like?

You won't be able to build the book list yet, because we're still missing a dependency — the URL map for the book detail
pages, which is needed to create hyperlinks to individual books. We'll show both list and detail views after the next
section.

Book detail page

The book detail page will display information about a specific book, accessed using the
URL catalog/book/<id> (where <id> is the primary key for the book). In addition to fields in the Book model (author,
summary, ISBN, language, and genre), we'll also list the details of the available copies (BookInstances) including the
status, expected return date, imprint, and id. This will allow our readers to not only learn about the book, but also to
confirm whether/when it is available.

271-CIS-3 Lab Manual - 2022 196


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

URL mapping

Open /catalog/urls.py and add the path named 'book-detail' shown below. This path() function defines a pattern,
associated generic class-based detail view, and a name.

urlpatterns = [

path('', views.index, name='index'),

path('books/', views.BookListView.as_view(), name='books'),

path('book/<int:pk>', views.BookDetailView.as_view(), name='book-detail'),

For the book-detail path the URL pattern uses a special syntax to capture the specific id of the book that we want to see.
The syntax is very simple: angle brackets define the part of the URL to be captured, enclosing the name of the variable
that the view can use to access the captured data. For example, <something> , will capture the marked pattern and pass
the value to the view as a variable "something". You can optionally precede the variable name with a converter
specification that defines the type of data (int, str, slug, uuid, path).

In this case we use '<int:pk>' to capture the book id, which must be a specially formatted string and pass it to the view
as a parameter named pk (short for primary key). This is the id that is being used to store the book uniquely in the
database, as defined in the Book Model.

271-CIS-3 Lab Manual - 2022 197


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

View (class-based)

Open catalog/views.py, and copy the following code into the bottom of the file:

class BookDetailView(generic.DetailView):

model = Book

That's it! All you need to do now is create a template


called /locallibrary/catalog/templates/catalog/book_detail.html, and the view will pass it the database information
for the specific Book record extracted by the URL mapper. Within the template you can access the book's details with the
template variable named object OR book (i.e. generically "the_model_name").

If you need to, you can change the template used and the name of the context object used to reference the book in the
template. You can also override methods to, for example, add additional information to the context.

What happens if the record doesn't exist?

If a requested record does not exist then the generic class-based detail view will raise an Http404 exception for you
automatically — in production, this will automatically display an appropriate "resource not found" page, which you can
customise if desired.

Just to give you some idea of how this works, the code fragment below demonstrates how you would implement the class-
based view as a function if you were not using the generic class-based detail view.

def book_detail_view(request, primary_key):


try:
book = Book.objects.get(pk=primary_key)
except Book.DoesNotExist:
raise Http404('Book does not exist')

return render(request, 'catalog/book_detail.html', context={'book': book})


The view first tries to get the specific book record from the model. If this fails the view should raise an Http404 exception
to indicate that the book is "not found". The final step is then, as usual, to call render() with the template name and the
book data in the context parameter (as a dictionary).

271-CIS-3 Lab Manual - 2022 198


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Alternatively, we can use the get_object_or_404() function as a shortcut to raise an Http404 exception if the record is
not found.

from django.shortcuts import get_object_or_404

def book_detail_view(request, primary_key):


book = get_object_or_404(Book, pk=primary_key)
return render(request, 'catalog/book_detail.html', context={'book': book})

Creating the Detail View template

Create the HTML file /locallibrary/catalog/templates/catalog/book_detail.html and give it the below content. As discussed
above, this is the default template file name expected by the generic class-based detail view (for a model named Book in
an application named catalog).

{% extends "base_generic.html" %}

{% block content %}
<h1>Title: {{ book.title }}</h1>

<p><strong>Author:</strong> <a href="">{{ book.author }}</a></p> <!-- author detail link not yet
defined -->
<p><strong>Summary:</strong> {{ book.summary }}</p>
<p><strong>ISBN:</strong> {{ book.isbn }}</p>
<p><strong>Language:</strong> {{ book.language }}</p>
<p><strong>Genre:</strong> {{ book.genre.all|join:", " }}</p>

<div style="margin-left:20px;margin-top:20px">
<h4>Copies</h4>

{% for copy in book.bookinstance_set.all %}


<hr>
<p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{%
else %}text-warning{% endif %}">
{{ copy.get_status_display }}
</p>
{% if copy.status != 'a' %}
<p><strong>Due to be returned:</strong> {{ copy.due_back }}</p>
{% endif %}
<p><strong>Imprint:</strong> {{ copy.imprint }}</p>
<p class="text-muted"><strong>Id:</strong> {{ copy.id }}</p>
{% endfor %}
</div>
{% endblock %}

271-CIS-3 Lab Manual - 2022 199


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

The author link in the template above has an empty URL because we've not yet created an author detail page to link to.
Once the detail page exists we can get its URL with either of these two approaches:

• Use the url template tag to reverse the 'author-detail' URL (defined in the URL mapper), passing it the author
instance for the book:
<a href="{% url 'author-detail' book.author.pk %}">{{ book.author }}</a>

• Call the author model's get_absolute_url() method (this performs the same reversing operation):
<a href="{{ book.author.get_absolute_url }}">{{ book.author }}</a>

While both methods effectively do the same thing, get_absolute_url() is preferred because it helps you write more
consistent and maintainable code (any changes only need to be done in one place: the author model).

Though a little larger, almost everything in this template has been described previously:

• We extend our base template and override the "content" block.


• We use conditional processing to determine whether or not to display specific content.
• We use for loops to loop through lists of objects.
• We access the context fields using the dot notation (because we've used the detail generic view, the context is
named book; we could also use "object")
The first interesting thing we haven't seen before is the function book.bookinstance_set.all(). This method is
"automagically" constructed by Django in order to return the set of BookInstance records associated with a
particular Book.

{% for copy in book.bookinstance_set.all %}

<!-- code to iterate across each copy/instance of a book -->

{% endfor %}

This method is needed because you declare a ForeignKey (one-to many) field in only the "one" side of the relationship
(the BookInstance). Since you don't do anything to declare the relationship in the other ("many") models, it (the Book)
doesn't have any field to get the set of associated records. To overcome this problem, Django constructs an appropriately
named "reverse lookup" function that you can use. The name of the function is constructed by lower-casing the
model name where the ForeignKey was declared, followed by _set (i.e. so the function
created in Book is bookinstance_set()).

271-CIS-3 Lab Manual - 2022 200


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Note: Here we use all() to get all records (the default). While you can use the filter() method to get a subset of
records in code, you can't do this directly in templates because you can't specify arguments to functions.

Beware also that if you don't define an order (on your class-based view or model), you will also see errors from the
development server like this one:

[29/May/2017 18:37:53] "GET /catalog/books/?page=1 HTTP/1.1" 200 1637

/foo/local_library/venv/lib/python3.5/site-packages/django/views/generic/list.py:99:
UnorderedObjectListWarning: Pagination may yield inconsistent results with an unordered
object_list: <QuerySet [<Author: Ortiz, David>, <Author: H. McRaven, William>, <Author:
Leigh, Melinda>]>

allow_empty_first_page=allow_empty_first_page, **kwargs)

That happens because the paginator object expects to see some ORDER BY being executed on your underlying
database. Without it, it can't be sure the records being returned are actually in the right order!

This tutorial hasn't covered Pagination (yet!), but since you can't use sort_by() and pass a parameter (the same
with filter() described above) you will have to choose between three choices:

1. Add a ordering inside a class Meta declaration on your model.


2. Add a queryset attribute in your custom class-based view, specifying an order_by().
3. Adding a get_queryset method to your custom class-based view and also specify the order_by().
If you decide to go with a class Meta for the Author model (probably not as flexible as customizing the class-based
view, but easy enough), you will end up with something like this:

class Author(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
date_of_birth = models.DateField(null=True, blank=True)
date_of_death = models.DateField('Died', null=True, blank=True)

def get_absolute_url(self):
return reverse('author-detail', args=[str(self.id)])

def __str__(self):
return f'{self.last_name}, {self.first_name}'

class Meta:
ordering = ['last_name']
Of course, the field doesn't need to be last_name: it could be any other.

271-CIS-3 Lab Manual - 2022 201


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Last but not least, you should sort by an attribute/column that actually has an index (unique or not) on your database to
avoid performance issues. Of course, this will not be necessary here (we are probably getting ahead of ourselves with so
few books and users), but it is something worth keeping in mind for future projects.

The second interesting (and non-obvious) thing in the template is where we set a class (text-success, text-danger, text-
warning) to color-code the human readable status text for each book instance ("available", "maintenance", etc.). Astute
readers will note that the method BookInstance.get_status_display() that we use to get the status text does not appear
elsewhere in the code.

<p class="{% if copy.status == 'a' %}text-success{% elif copy.status == 'm' %}text-danger{% else
%}text-warning{% endif %}">

{{ copy.get_status_display }} </p>

This function is automatically created because BookInstance.status is a choices field. Django automatically creates a
method get_FOO_display() for every choices field "Foo" in a model, which can be used to get the current value of the
field.

271-CIS-3 Lab Manual - 2022 202


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

What does it look like?

At this point, we should have created everything needed to display both the book list and book detail pages. Run the
server (python3 manage.py runserver) and open your browser to http://127.0.0.1:8000/.

Click the All books link to display the list of books.

Then click a link to one of your books. If everything is set up correctly, you should see something like the
following screenshot.

271-CIS-3 Lab Manual - 2022 203


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Pagination

If you've just got a few records, our book list page will look fine. However, as you get into the tens or hundreds of records
the page will take progressively longer to load (and have far too much content to browse sensibly). The solution to this
problem is to add pagination to your list views, reducing the number of items displayed on each page.

Django has excellent inbuilt support for pagination. Even better, this is built into the generic class-based list views so you
don't have to do very much to enable it!

Views

Open catalog/views.py, and add the paginate_by line shown below.

class BookListView(generic.ListView):

model = Book

paginate_by = 10

With this addition, as soon as you have more than 10 records the view will start paginating the data it sends to the
template. The different pages are accessed using GET parameters — to access page 2 you would use the
URL /catalog/books/?page=2.

Templates

Now that the data is paginated, we need to add support to the template to scroll through the results set. Because we might
want paginate all list views, we'll add this to the base template.

Open /locallibrary/catalog/templates/base_generic.html and find the "content block" (as shown below).

{% block content %}{% endblock %}

271-CIS-3 Lab Manual - 2022 204


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

Copy in the following pagination block immediately following the {% endblock %}. The code first checks if pagination is
enabled on the current page. If so, it adds next and previous links as appropriate (and the current page number).

{% block pagination %}
{% if is_paginated %}
<div class="pagination">
<span class="page-links">
{% if page_obj.has_previous %}
<a href="{{ request.path }}?page={{ page_obj.previous_page_number
}}">previous</a>
{% endif %}
<span class="page-current">
Page {{ page_obj.number }} of {{ page_obj.paginator.num_pages }}.
</span>
{% if page_obj.has_next %}
<a href="{{ request.path }}?page={{ page_obj.next_page_number }}">next</a>
{% endif %}
</span>
</div>
{% endif %}
{% endblock %}
The page_obj is a Paginator object that will exist if pagination is being used on the current page. It allows you to get all
the information about the current page, previous pages, how many pages there are, etc.

We use {{ request.path }} to get the current page URL for creating the pagination links. This is useful because it is
independent of the object that we're paginating.

271-CIS-3 Lab Manual - 2022 205


Department of Information Systems ‫ﻗﺴﻢ ﻧﻈﻢ اﻟﻤﻌﻠﻮﻣﺎت‬

What does it look like?

The screenshot below shows what the pagination looks like — if you haven't entered more than 10 titles into your
database, then you can test it more easily by lowering the number specified in the paginate_by line in
your catalog/views.py file. To get the below result we changed it to paginate_by = 2.

The pagination links are displayed on the bottom, with next/previous links being displayed depending on which page
you're on.

271-CIS-3 Lab Manual - 2022 206

You might also like