- By Guillaume
- Weight: 5
- Project to be done in teams of 2 people (My team: Arsene Awounou, Pericles Adjovi)
For this project, students are expected to look at these concepts:
Before starting, please read the AirBnB concept page.
This is the first step towards building your first full web application: the AirBnB clone. This first step is very important because you will use what you build during this project with all other following projects: HTML/CSS templating, database storage, API, front-end integration...
Each task is linked and will help you to:
- put in place a parent class (called
BaseModel
) to take care of the initialization, serialization and deserialization of your future instances - create a simple flow of serialization/deserialization: Instance <-> Dictionary <-> JSON string <-> file
- create all classes used for AirBnB (
User
,State
,City
,Place
...) that inherit fromBaseModel
- create the first abstracted storage engine of the project: File storage.
- create all unittests to validate all our classes and storage engine
Do you remember the Shell? It's exactly the same but limited to a specific use-case. In our case, we want to be able to manage the objects of our project:
- Create a new object (ex: a new User or a new Place)
- Retrieve an object from a file, a database etc...
- Do operations on objects (count, compute stats, etc...)
- Update attributes of an object
- Destroy an object
Read or watch:
- cmd module
- packages concept page
- uuid module
- datetime
- unittest module
- args/kwargs
- Python test cheatsheet
At the end of this project, you are expected to be able to explain to anyone, without the help of Google:
- How to create a Python package
- How to create a command interpreter in Python using the
cmd
module - What is Unit testing and how to implement it in a large project
- How to serialize and deserialize a Class
- How to write and read a JSON file
- How to manage
datetime
- What is an
UUID
- What is
*args
and how to use it - What is
**kwargs
and how to use it - How to handle named arguments in a function
- Allowed editors:
vi
,vim
,emacs
- All your files will be interpreted/compiled on Ubuntu 20.04 LTS using python3 (version 3.8.5)
- All your files should end with a new line
- The first line of all your files should be exactly
#!/usr/bin/python3
- A
README.md
file, at the root of the folder of the project, is mandatory - Your code should use the pycodestyle (version 2.7.*)
- All your files must be executable
- The length of your files will be tested using
wc
- All your modules should have a documentation (
python3 -c 'print(__import__("my_module").__doc__)'
) - All your classes should have a documentation (
python3 -c 'print(__import__("my_module").MyClass.__doc__)'
) - All your functions (inside and outside a class) should have a documentation (
python3 -c 'print(__import__("my_module").my_function.__doc__)'
andpython3 -c 'print(__import__("my_module").MyClass.my_function.__doc__)'
) - A documentation is not a simple word, it's a real sentence explaining what's the purpose of the module, class or method (the length of it will be verified)
- Allowed editors:
vi
,vim
,emacs
- All your files should end with a new line
- All your test files should be inside a folder
tests
- You have to use the unittest module
- All your test files should be python files (extension:
.py
) - All your test files and folders should start by
test_
- Your file organization in the tests folder should be the same as your project
- e.g., For
models/base_model.py
, unit tests must be in:tests/test_models/test_base_model.py
- e.g., For
models/user.py
, unit tests must be in:tests/test_models/test_user.py
- All your tests should be executed by using this command:
python3 -m unittest discover tests
- You can also test file by file by using this command:
python3 -m unittest tests/test_models/test_base_model.py
- All your modules should have a documentation (
python3 -c 'print(__import__("my_module").__doc__)'
) - All your classes should have a documentation (
python3 -c 'print(__import__("my_module").MyClass.__doc__)'
) - All your functions (inside and outside a class) should have a documentation (
python3 -c 'print(__import__("my_module").my_function.__doc__)'
andpython3 -c 'print(__import__("my_module").MyClass.my_function.__doc__)'
) - We strongly encourage you to work together on test cases, so that you don't miss any edge case
There should be one project repository per group. If you clone/fork/whatever a project repository with the same name before the second deadline, you risk a 0% score.
Your shell should work like this in interactive mode:
$ ./console.py
(hbnb) help
Documented commands (type help <topic>):
========================================
EOF help quit
(hbnb)
(hbnb)
(hbnb) quit
$
But also in non-interactive mode: (like the Shell project in C)
$ echo "help" | ./console.py
(hbnb)
Documented commands (type help <topic>):
========================================
EOF help quit
(hbnb)
$
$ cat test_help
help
$
$ cat test_help | ./console.py
(hbnb)
Documented commands (type help <topic>):
========================================
EOF help quit
(hbnb)
$
All tests should also pass in non-interactive mode: $ echo "python3 -m unittest discover tests" | bash
mandatory
- Write a
README.md
:- description of the project
- description of the command interpreter:
- how to start it
- how to use it
- examples
- You should have an
AUTHORS
file at the root of your repository, listing all individuals having contributed content to the repository. For format, reference Docker's AUTHORS page - You should use branches and pull requests on GitHub - it will help you as team to organize your work
Repo:
- GitHub repository:
AirBnB_clone
- File:
README.md, AUTHORS
mandatory
Write beautiful code that passes the pycodestyle checks.
Repo:
- GitHub repository:
AirBnB_clone
mandatory
All your files, classes, functions must be tested with unit tests
guillaume@ubuntu:~/AirBnB$ python3 -m unittest discover tests
...................................................................................
...................................................................................
.......................
----------------------------------------------------------------------
Ran 189 tests in 13.135s
OK
guillaume@ubuntu:~/AirBnB$
Note that this is just an example, the number of tests you create can be different from the above example.
Warning:
Unit tests must also pass in non-interactive mode:
guillaume@ubuntu:~/AirBnB$ echo "python3 -m unittest discover tests" | bash
...................................................................................
...................................................................................
.......................
----------------------------------------------------------------------
Ran 189 tests in 13.135s
OK
guillaume@ubuntu:~/AirBnB$
Repo:
- GitHub repository:
AirBnB_clone
- File:
tests/
mandatory
Write a class BaseModel
that defines all common attributes/methods for other classes:
models/base_model.py
- Public instance attributes:
id
: string - assign with anuuid
when an instance is created:- you can use
uuid.uuid4()
to generate uniqueid
but don't forget to convert to a string - the goal is to have unique
id
for eachBaseModel
- you can use
created_at
: datetime - assign with the current datetime when an instance is createdupdated_at
: datetime - assign with the current datetime when an instance is created and it will be updated every time you change your object
__str__
: should print:[<class name>] (<self.id>) <self.__dict__>
- Public instance methods:
save(self)
: updates the public instance attributeupdated_at
with the current datetimeto_dict(self)
: returns a dictionary containing all keys/values of__dict__
of the instance:- by using
self.__dict__
, only instance attributes set will be returned - a key
__class__
must be added to this dictionary with the class name of the object created_at
andupdated_at
must be converted to string object in ISO format:- format:
%Y-%m-%dT%H:%M:%S.%f
(ex:2017-06-14T22:31:03.285259
) - you can use
isoformat()
ofdatetime
object
- format:
- This method will be the first piece of the serialization/deserialization process: create a dictionary representation with "simple object type" of our
BaseModel
- by using
guillaume@ubuntu:~/AirBnB$ cat test_base_model.py
#!/usr/bin/python3
from models.base_model import BaseModel
my_model = BaseModel()
my_model.name = "My First Model"
my_model.my_number = 89
print(my_model)
my_model.save()
print(my_model)
my_model_json = my_model.to_dict()
print(my_model_json)
print("JSON of my_model:")
for key in my_model_json.keys():
print("\t{}: ({}) - {}".format(key, type(my_model_json[key]), my_model_json[key]))
guillaume@ubuntu:~/AirBnB$ ./test_base_model.py
[BaseModel] (b6a6e15c-c67d-4312-9a75-9d084935e579) {'my_number': 89, 'name': 'My First Model', 'updated_at': datetime.datetime(2017, 9, 28, 21, 5, 54, 119434), 'id': 'b6a6e15c-c67d-4312-9a75-9d084935e579', 'created_at': datetime.datetime(2017, 9, 28, 21, 5, 54, 119427)}
[BaseModel] (b6a6e15c-c67d-4312-9a75-9d084935e579) {'my_number': 89, 'name': 'My First Model', 'updated_at': datetime.datetime(2017, 9, 28, 21, 5, 54, 119572), 'id': 'b6a6e15c-c67d-4312-9a75-9d084935e579', 'created_at': datetime.datetime(2017, 9, 28, 21, 5, 54, 119427)}
{'my_number': 89, 'name': 'My First Model', '__class__': 'BaseModel', 'updated_at': '2017-09-28T21:05:54.119572', 'id': 'b6a6e15c-c67d-4312-9a75-9d084935e579', 'created_at': '2017-09-28T21:05:54.119427'}
JSON of my_model:
my_number: (<class 'int'>) - 89
name: (<class 'str'>) - My First Model
__class__: (<class 'str'>) - BaseModel
updated_at: (<class 'str'>) - 2017-09-28T21:05:54.119572
id: (<class 'str'>) - b6a6e15c-c67d-4312-9a75-9d084935e579
created_at: (<class 'str'>) - 2017-09-28T21:05:54.119427
guillaume@ubuntu:~/AirBnB$
Repo:
- GitHub repository:
AirBnB_clone
- File:
models/base_model.py, models/__init__.py, tests/
mandatory
Previously we created a method to generate a dictionary representation of an instance (method to_dict()
).
Now it's time to re-create an instance with this dictionary representation.
<class 'BaseModel'> -> to_dict() -> <class 'dict'> -> <class 'BaseModel'>
Update models/base_model.py
:
__init__(self, *args, **kwargs)
:- you will use
*args, **kwargs
arguments for the constructor of aBaseModel
. (more information inside the AirBnB clone concept page) *args
won't be used- if
kwargs
is not empty:- each key of this dictionary is an attribute name (Note
__class__
fromkwargs
is the only one that should not be added as an attribute. See the example output, below) - each value of this dictionary is the value of this attribute name
- Warning:
created_at
andupdated_at
are strings in this dictionary, but inside yourBaseModel
instance is working withdatetime
object. You have to convert these strings intodatetime
object. Tip: you know the string format of these datetime
- each key of this dictionary is an attribute name (Note
- otherwise:
- create
id
andcreated_at
as you did previously (new instance)
- create
- you will use
guillaume@ubuntu:~/AirBnB$ cat test_base_model_dict.py
#!/usr/bin/python3
from models.base_model import BaseModel
my_model = BaseModel()
my_model.name = "My_First_Model"
my_model.my_number = 89
print(my_model.id)
print(my_model)
print(type(my_model.created_at))
print("--")
my_model_json = my_model.to_dict()
print(my_model_json)
print("JSON of my_model:")
for key in my_model_json.keys():
print("\t{}: ({}) - {}".format(key, type(my_model_json[key]), my_model_json[key]))
print("--")
my_new_model = BaseModel(**my_model_json)
print(my_new_model.id)
print(my_new_model)
print(type(my_new_model.created_at))
print("--")
print(my_model is my_new_model)
guillaume@ubuntu:~/AirBnB$ ./test_base_model_dict.py
56d43177-cc5f-4d6c-a0c1-e167f8c27337
[BaseModel] (56d43177-cc5f-4d6c-a0c1-e167f8c27337) {'id': '56d43177-cc5f-4d6c-a0c1-e167f8c27337', 'created_at': datetime.datetime(2017, 9, 28, 21, 3, 54, 52298), 'my_number': 89, 'updated_at': datetime.datetime(2017, 9, 28, 21, 3, 54, 52302), 'name': 'My_First_Model'}
<class 'datetime.datetime'>
--
{'id': '56d43177-cc5f-4d6c-a0c1-e167f8c27337', 'created_at': '2017-09-28T21:03:54.052298', '__class__': 'BaseModel', 'my_number': 89, 'updated_at': '2017-09-28T21:03:54.052302', 'name': 'My_First_Model'}
JSON of my_model:
id: (<class 'str'>) - 56d43177-cc5f-4d6c-a0c1-e167f8c27337
created_at: (<class 'str'>) - 2017-09-28T21:03:54.052298
__class__: (<class 'str'>) - BaseModel
my_number: (<class 'int'>) - 89
updated_at: (<class 'str'>) - 2017-09-28T21:03:54.052302
name: (<class 'str'>) - My_First_Model
--
56d43177-cc5f-4d6c-a0c1-e167f8c27337
[BaseModel] (56d43177-cc5f-4d6c-a0c1-e167f8c27337) {'id': '56d43177-cc5f-4d6c-a0c1-e167f8c27337', 'created_at': datetime.datetime(2017, 9, 28, 21, 3, 54, 52298), 'my_number': 89, 'updated_at': datetime.datetime(2017, 9, 28, 21, 3, 54, 52302), 'name': 'My_First_Model'}
<class 'datetime.datetime'>
--
False
guillaume@ubuntu:~/AirBnB$
Repo:
- GitHub repository:
AirBnB_clone
- File:
models/base_model.py, tests/
mandatory
Now we can recreate a BaseModel
from another one by using a dictionary representation:
<class 'BaseModel'> -> to_dict() -> <class 'dict'> -> <class 'BaseModel'>
It's great but it's still not persistent: every time you launch the program, you don't restore all objects created before... The first way you will see here is to save these objects to a file.
Writing the dictionary representation to a file won't be relevant:
- Python doesn't know how to convert a string to a dictionary (easily)
- It's not human readable
- Using this file with another program in Python or other language will be hard.
So, you will convert the dictionary representation to a JSON string. JSON is a standard representation of a data structure. With this format, humans can read and all programming languages have a JSON reader and writer.
Now the flow of serialization-deserialization will be:
<class 'BaseModel'> -> to_dict() -> <class 'dict'> -> JSON dump -> <class 'str'> -> FILE -> <class 'str'> -> JSON load -> <class 'dict'> -> <class 'BaseModel'>
Magic right?
Terms:
- simple Python data structure: Dictionaries, arrays, number and string. ex:
{ '12': { 'numbers': [1, 2, 3], 'name': "John" } }
- JSON string representation: String representing a simple data structure in JSON format. ex:
'{ "12": { "numbers": [1, 2, 3], "name": "John" } }'
Write a class FileStorage
that serializes instances to a JSON file and deserializes JSON file to instances:
models/engine/file_storage.py
- Private class attributes:
__file_path
: string - path to the JSON file (ex:file.json
)__objects
: dictionary - empty but will store all objects by<class name>.id
(ex: to store aBaseModel
object withid=12121212
, the key will beBaseModel.12121212
)
- Public instance methods:
all(self)
: returns the dictionary__objects
new(self, obj)
: sets in__objects
theobj
with key<obj class name>.id
save(self)
: serializes__objects
to the JSON file (path:__file_path
)reload(self)
: deserializes the JSON file to__objects
(only if the JSON file (__file_path
) exists ; otherwise, do nothing. If the file doesn't exist, no exception should be raised)
Update models/__init__.py
: to create a unique FileStorage
instance for your application
- import
file_storage.py
- create the variable
storage
, an instance ofFileStorage
- call
reload()
method on this variable
Update models/base_model.py
: to link your BaseModel
to FileStorage
by using the variable storage
- import the variable
storage
- in the method
save(self)
:- call
save(self)
method ofstorage
- call
__init__(self, *args, **kwargs)
:- if it's a new instance (not from a dictionary representation), add a call to the method
new(self)
onstorage
- if it's a new instance (not from a dictionary representation), add a call to the method
guillaume@ubuntu:~/AirBnB$ cat test_save_reload_base_model.py
#!/usr/bin/python3
from models import storage
from models.base_model import BaseModel
all_objs = storage.all()
print("-- Reloaded objects --")
for obj_id in all_objs.keys():
obj = all_objs[obj_id]
print(obj)
print("-- Create a new object --")
my_model = BaseModel()
my_model.name = "My_First_Model"
my_model.my_number = 89
my_model.save()
print(my_model)
guillaume@ubuntu:~/AirBnB$ cat file.json
cat: file.json: No such file or directory
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ ./test_save_reload_base_model.py
-- Reloaded objects --
-- Create a new object --
[BaseModel] (ee49c413-023a-4b49-bd28-f2936c95460d) {'my_number': 89, 'updated_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47381), 'created_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47372), 'name': 'My_First_Model', 'id': 'ee49c413-023a-4b49-bd28-f2936c95460d'}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ cat file.json ; echo ""
{"BaseModel.ee49c413-023a-4b49-bd28-f2936c95460d": {"my_number": 89, "__class__": "BaseModel", "updated_at": "2017-09-28T21:07:25.047381", "created_at": "2017-09-28T21:07:25.047372", "name": "My_First_Model", "id": "ee49c413-023a-4b49-bd28-f2936c95460d"}}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ ./test_save_reload_base_model.py
-- Reloaded objects --
[BaseModel] (ee49c413-023a-4b49-bd28-f2936c95460d) {'name': 'My_First_Model', 'id': 'ee49c413-023a-4b49-bd28-f2936c95460d', 'updated_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47381), 'my_number': 89, 'created_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47372)}
-- Create a new object --
[BaseModel] (080cce84-c574-4230-b82a-9acb74ad5e8c) {'name': 'My_First_Model', 'id': '080cce84-c574-4230-b82a-9acb74ad5e8c', 'updated_at': datetime.datetime(2017, 9, 28, 21, 7, 51, 973308), 'my_number': 89, 'created_at': datetime.datetime(2017, 9, 28, 21, 7, 51, 973301)}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ ./test_save_reload_base_model.py
-- Reloaded objects --
[BaseModel] (080cce84-c574-4230-b82a-9acb74ad5e8c) {'id': '080cce84-c574-4230-b82a-9acb74ad5e8c', 'updated_at': datetime.datetime(2017, 9, 28, 21, 7, 51, 973308), 'created_at': datetime.datetime(2017, 9, 28, 21, 7, 51, 973301), 'name': 'My_First_Model', 'my_number': 89}
[BaseModel] (ee49c413-023a-4b49-bd28-f2936c95460d) {'id': 'ee49c413-023a-4b49-bd28-f2936c95460d', 'updated_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47381), 'created_at': datetime.datetime(2017, 9, 28, 21, 7, 25, 47372), 'name': 'My_First_Model', 'my_number': 89}
-- Create a new object --
[BaseModel] (e79e744a-55d4-45a3-b74a-ca5fae74e0e2) {'id': 'e79e744a-55d4-45a3-b74a-ca5fae74e0e2', 'updated_at': datetime.datetime(2017, 9, 28, 21, 8, 6, 151750), 'created_at': datetime.datetime(2017, 9, 28, 21, 8, 6, 151711), 'name': 'My_First_Model', 'my_number': 89}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ cat file.json ; echo ""
{"BaseModel.e79e744a-55d4-45a3-b74a-ca5fae74e0e2": {"__class__": "BaseModel", "id": "e79e744a-55d4-45a3-b74a-ca5fae74e0e2", "updated_at": "2017-09-28T21:08:06.151750", "created_at": "2017-09-28T21:08:06.151711", "name": "My_First_Model", "my_number": 89}, "BaseModel.080cce84-c574-4230-b82a-9acb74ad5e8c": {"__class__": "BaseModel", "id": "080cce84-c574-4230-b82a-9acb74ad5e8c", "updated_at": "2017-09-28T21:07:51.973308", "created_at": "2017-09-28T21:07:51.973301", "name": "My_First_Model", "my_number": 89}, "BaseModel.ee49c413-023a-4b49-bd28-f2936c95460d": {"__class__": "BaseModel", "id": "ee49c413-023a-4b49-bd28-f2936c95460d", "updated_at": "2017-09-28T21:07:25.047381", "created_at": "2017-09-28T21:07:25.047372", "name": "My_First_Model", "my_number": 89}}
guillaume@ubuntu:~/AirBnB$
Repo:
- GitHub repository:
AirBnB_clone
- File:
models/engine/file_storage.py, models/engine/__init__.py, models/__init__.py, models/base_model.py, tests/
mandatory
Write a program called console.py
that contains the entry point of the command interpreter:
- You must use the module
cmd
- Your class definition must be:
class HBNBCommand(cmd.Cmd):
- Your command interpreter should implement:
quit
andEOF
to exit the programhelp
(this action is provided by default bycmd
but you should keep it updated and documented as you work through tasks)- a custom prompt:
(hbnb)
- an empty line +
ENTER
shouldn't execute anything
- Your code should not be executed when imported
Warning:
You should end your file with:
if __name__ == '__main__':
HBNBCommand().cmdloop()
to make your program executable except when imported. Please don't add anything around - the Checker won't like it otherwise
guillaume@ubuntu:~/AirBnB$ ./console.py
(hbnb) help
Documented commands (type help <topic>):
========================================
EOF help quit
(hbnb)
(hbnb) help quit
Quit command to exit the program
(hbnb)
(hbnb)
(hbnb) quit
guillaume@ubuntu:~/AirBnB$
No unittests needed
Repo:
- GitHub repository:
AirBnB_clone
- File:
console.py
mandatory
Update your command interpreter (console.py
) to have these commands:
create
: Creates a new instance ofBaseModel
, saves it (to the JSON file) and prints theid
. Ex:$ create BaseModel
- If the class name is missing, print
** class name missing **
(ex:$ create
) - If the class name doesn't exist, print
** class doesn't exist **
(ex:$ create MyModel
)
- If the class name is missing, print
show
: Prints the string representation of an instance based on the class name andid
. Ex:$ show BaseModel 1234-1234-1234
.- If the class name is missing, print
** class name missing **
(ex:$ show
) - If the class name doesn't exist, print
** class doesn't exist **
(ex:$ show MyModel
) - If the
id
is missing, print** instance id missing **
(ex:$ show BaseModel
) - If the instance of the class name doesn't exist for the
id
, print** no instance found **
(ex:$ show BaseModel 121212
)
- If the class name is missing, print
destroy
: Deletes an instance based on the class name andid
(save the change into the JSON file). Ex:$ destroy BaseModel 1234-1234-1234
.- If the class name is missing, print
** class name missing **
(ex:$ destroy
) - If the class name doesn't exist, print
** class doesn't exist ** (ex:
$ destroy MyModel)
- If the
id
is missing, print** instance id missing **
(ex:$ destroy BaseModel
) - If the instance of the class name doesn't exist for the
id
, print** no instance found **
(ex:$ destroy BaseModel 121212
)
- If the class name is missing, print
all
: Prints all string representation of all instances based or not on the class name. Ex:$ all BaseModel
or$ all
.- The printed result must be a list of strings (like the example below)
- If the class name doesn't exist, print
** class doesn't exist **
(ex:$ all MyModel
)
update
: Updates an instance based on the class name andid
by adding or updating attribute (save the change into the JSON file). Ex:$ update BaseModel 1234-1234-1234 email "aibnb@mail.com"
.- Usage:
update <class name> <id> <attribute name> "<attribute value>"
- Only one attribute can be updated at the time
- You can assume the attribute name is valid (exists for this model)
- The attribute value must be casted to the attribute type
- If the class name is missing, print
** class name missing **
(ex:$ update
) - If the class name doesn't exist, print
** class doesn't exist **
(ex:$ update MyModel
) - If the
id
is missing, print** instance id missing **
(ex:$ update BaseModel
) - If the instance of the class name doesn't exist for the
id
, print** no instance found **
(ex:$ update BaseModel 121212
) - If the attribute name is missing, print
** attribute name missing **
(ex:$ update BaseModel existing-id
) - If the value for the attribute name doesn't exist, print
** value missing **
(ex:$ update BaseModel existing-id first_name
) - All other arguments should not be used (Ex:
$ update BaseModel 1234-1234-1234 email "aibnb@mail.com" first_name "Betty"
=$ update BaseModel 1234-1234-1234 email "aibnb@mail.com"
) id
,created_at
andupdated_at
cant' be updated. You can assume they won't be passed in theupdate
command- Only "simple" arguments can be updated: string, integer and float. You can assume nobody will try to update list of ids or datetime
- Usage:
Let's add some rules:
- You can assume arguments are always in the right order
- Each arguments are separated by a space
- A string argument with a space must be between double quote
- The error management starts from the first argument to the last one
guillaume@ubuntu:~/AirBnB$ ./console.py
(hbnb) all MyModel
** class doesn't exist **
(hbnb) show BaseModel
** instance id missing **
(hbnb) show BaseModel My_First_Model
** no instance found **
(hbnb) create BaseModel
49faff9a-6318-451f-87b6-910505c55907
(hbnb) all BaseModel
["[BaseModel] (49faff9a-6318-451f-87b6-910505c55907) {'created_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903293), 'id': '49faff9a-6318-451f-87b6-910505c55907', 'updated_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903300)}"]
(hbnb) show BaseModel 49faff9a-6318-451f-87b6-910505c55907
[BaseModel] (49faff9a-6318-451f-87b6-910505c55907) {'created_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903293), 'id': '49faff9a-6318-451f-87b6-910505c55907', 'updated_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903300)}
(hbnb) destroy
** class name missing **
(hbnb) update BaseModel 49faff9a-6318-451f-87b6-910505c55907 first_name "Betty"
(hbnb) show BaseModel 49faff9a-6318-451f-87b6-910505c55907
[BaseModel] (49faff9a-6318-451f-87b6-910505c55907) {'first_name': 'Betty', 'id': '49faff9a-6318-451f-87b6-910505c55907', 'created_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903293), 'updated_at': datetime.datetime(2017, 10, 2, 3, 11, 3, 49401)}
(hbnb) create BaseModel
2dd6ef5c-467c-4f82-9521-a772ea7d84e9
(hbnb) all BaseModel
["[BaseModel] (2dd6ef5c-467c-4f82-9521-a772ea7d84e9) {'id': '2dd6ef5c-467c-4f82-9521-a772ea7d84e9', 'created_at': datetime.datetime(2017, 10, 2, 3, 11, 23, 639717), 'updated_at': datetime.datetime(2017, 10, 2, 3, 11, 23, 639724)}", "[BaseModel] (49faff9a-6318-451f-87b6-910505c55907) {'first_name': 'Betty', 'id': '49faff9a-6318-451f-87b6-910505c55907', 'created_at': datetime.datetime(2017, 10, 2, 3, 10, 25, 903293), 'updated_at': datetime.datetime(2017, 10, 2, 3, 11, 3, 49401)}"]
(hbnb) destroy BaseModel 49faff9a-6318-451f-87b6-910505c55907
(hbnb) show BaseModel 49faff9a-6318-451f-87b6-910505c55907
** no instance found **
(hbnb)
No unittests needed
Repo:
- GitHub repository:
AirBnB_clone
- File:
console.py
mandatory
Write a class User
that inherits from BaseModel
:
models/user.py
- Public class attributes:
email
: string - empty stringpassword
: string - empty stringfirst_name
: string - empty stringlast_name
: string - empty string
Update FileStorage
to manage correctly serialization and deserialization of User
.
Update your command interpreter (console.py
) to allow show
, create
, destroy
, update
and all
used with User
.
guillaume@ubuntu:~/AirBnB$ cat test_save_reload_user.py
#!/usr/bin/python3
from models import storage
from models.base_model import BaseModel
from models.user import User
all_objs = storage.all()
print("-- Reloaded objects --")
for obj_id in all_objs.keys():
obj = all_objs[obj_id]
print(obj)
print("-- Create a new User --")
my_user = User()
my_user.first_name = "Betty"
my_user.last_name = "Bar"
my_user.email = "airbnb@mail.com"
my_user.password = "root"
my_user.save()
print(my_user)
print("-- Create a new User 2 --")
my_user2 = User()
my_user2.first_name = "John"
my_user2.email = "airbnb2@mail.com"
my_user2.password = "root"
my_user2.save()
print(my_user2)
guillaume@ubuntu:~/AirBnB$ cat file.json ; echo ""
{"BaseModel.2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4": {"__class__": "BaseModel", "id": "2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4", "updated_at": "2017-09-28T21:11:14.333862", "created_at": "2017-09-28T21:11:14.333852"}, "BaseModel.a42ee380-c959-450e-ad29-c840a898cfce": {"__class__": "BaseModel", "id": "a42ee380-c959-450e-ad29-c840a898cfce", "updated_at": "2017-09-28T21:11:15.504296", "created_at": "2017-09-28T21:11:15.504287"}, "BaseModel.af9b4cbd-2ce1-4e6e-8259-f578097dd15f": {"__class__": "BaseModel", "id": "af9b4cbd-2ce1-4e6e-8259-f578097dd15f", "updated_at": "2017-09-28T21:11:12.971544", "created_at": "2017-09-28T21:11:12.971521"}, "BaseModel.38a22b25-ae9c-4fa9-9f94-59b3eb51bfba": {"__class__": "BaseModel", "id": "38a22b25-ae9c-4fa9-9f94-59b3eb51bfba", "updated_at": "2017-09-28T21:11:13.753347", "created_at": "2017-09-28T21:11:13.753337"}, "BaseModel.9bf17966-b092-4996-bd33-26a5353cccb4": {"__class__": "BaseModel", "id": "9bf17966-b092-4996-bd33-26a5353cccb4", "updated_at": "2017-09-28T21:11:14.963058", "created_at": "2017-09-28T21:11:14.963049"}}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ ./test_save_reload_user.py
-- Reloaded objects --
[BaseModel] (38a22b25-ae9c-4fa9-9f94-59b3eb51bfba) {'id': '38a22b25-ae9c-4fa9-9f94-59b3eb51bfba', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 13, 753337), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 13, 753347)}
[BaseModel] (9bf17966-b092-4996-bd33-26a5353cccb4) {'id': '9bf17966-b092-4996-bd33-26a5353cccb4', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 963049), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 963058)}
[BaseModel] (2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4) {'id': '2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 333852), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 333862)}
[BaseModel] (a42ee380-c959-450e-ad29-c840a898cfce) {'id': 'a42ee380-c959-450e-ad29-c840a898cfce', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 15, 504287), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 15, 504296)}
[BaseModel] (af9b4cbd-2ce1-4e6e-8259-f578097dd15f) {'id': 'af9b4cbd-2ce1-4e6e-8259-f578097dd15f', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 12, 971521), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 12, 971544)}
-- Create a new User --
[User] (38f22813-2753-4d42-b37c-57a17f1e4f88) {'id': '38f22813-2753-4d42-b37c-57a17f1e4f88', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848279), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848291), 'email': 'airbnb@mail.com', 'first_name': 'Betty', 'last_name': 'Bar', 'password': 'root'}
-- Create a new User 2 --
[User] (d0ef8146-4664-4de5-8e89-096d667b728e) {'id': 'd0ef8146-4664-4de5-8e89-096d667b728e', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848280), 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848294), 'email': 'airbnb2@mail.com', 'first_name': 'John', 'password': 'root'}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ cat file.json ; echo ""
{"BaseModel.af9b4cbd-2ce1-4e6e-8259-f578097dd15f": {"id": "af9b4cbd-2ce1-4e6e-8259-f578097dd15f", "updated_at": "2017-09-28T21:11:12.971544", "created_at": "2017-09-28T21:11:12.971521", "__class__": "BaseModel"}, "BaseModel.38a22b25-ae9c-4fa9-9f94-59b3eb51bfba": {"id": "38a22b25-ae9c-4fa9-9f94-59b3eb51bfba", "updated_at": "2017-09-28T21:11:13.753347", "created_at": "2017-09-28T21:11:13.753337", "__class__": "BaseModel"}, "BaseModel.9bf17966-b092-4996-bd33-26a5353cccb4": {"id": "9bf17966-b092-4996-bd33-26a5353cccb4", "updated_at": "2017-09-28T21:11:14.963058", "created_at": "2017-09-28T21:11:14.963049", "__class__": "BaseModel"}, "BaseModel.2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4": {"id": "2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4", "updated_at": "2017-09-28T21:11:14.333862", "created_at": "2017-09-28T21:11:14.333852", "__class__": "BaseModel"}, "BaseModel.a42ee380-c959-450e-ad29-c840a898cfce": {"id": "a42ee380-c959-450e-ad29-c840a898cfce", "updated_at": "2017-09-28T21:11:15.504296", "created_at": "2017-09-28T21:11:15.504287", "__class__": "BaseModel"}, "User.38f22813-2753-4d42-b37c-57a17f1e4f88": {"id": "38f22813-2753-4d42-b37c-57a17f1e4f88", "created_at": "2017-09-28T21:11:42.848279", "updated_at": "2017-09-28T21:11:42.848291", "email": "airbnb@mail.com", "first_name": "Betty", "__class__": "User", "last_name": "Bar", "password": "root"}, "User.d0ef8146-4664-4de5-8e89-096d667b728e": {"id": "d0ef8146-4664-4de5-8e89-096d667b728e", "created_at": "2017-09-28T21:11:42.848280", "updated_at": "2017-09-28T21:11:42.848294", "email": "airbnb_2@mail.com", "first_name": "John", "__class__": "User", "password": "root"}}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ ./test_save_reload_user.py
-- Reloaded objects --
[BaseModel] (af9b4cbd-2ce1-4e6e-8259-f578097dd15f) {'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 12, 971544), 'id': 'af9b4cbd-2ce1-4e6e-8259-f578097dd15f', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 12, 971521)}
[BaseModel] (2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4) {'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 333862), 'id': '2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 333852)}
[BaseModel] (9bf17966-b092-4996-bd33-26a5353cccb4) {'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 963058), 'id': '9bf17966-b092-4996-bd33-26a5353cccb4', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 14, 963049)}
[BaseModel] (a42ee380-c959-450e-ad29-c840a898cfce) {'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 15, 504296), 'id': 'a42ee380-c959-450e-ad29-c840a898cfce', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 15, 504287)}
[BaseModel] (38a22b25-ae9c-4fa9-9f94-59b3eb51bfba) {'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 13, 753347), 'id': '38a22b25-ae9c-4fa9-9f94-59b3eb51bfba', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 13, 753337)}
[User] (38f22813-2753-4d42-b37c-57a17f1e4f88) {'password': '63a9f0ea7bb98050796b649e85481845', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848279), 'email': 'airbnb@mail.com', 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848291), 'last_name': 'Bar', 'id': '38f22813-2753-4d42-b37c-57a17f1e4f88', 'first_name': 'Betty'}
[User] (d0ef8146-4664-4de5-8e89-096d667b728e) {'password': '63a9f0ea7bb98050796b649e85481845', 'created_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848280), 'email': 'airbnb_2@mail.com', 'updated_at': datetime.datetime(2017, 9, 28, 21, 11, 42, 848294), 'id': 'd0ef8146-4664-4de5-8e89-096d667b728e', 'first_name': 'John'}
-- Create a new User --
[User] (246c227a-d5c1-403d-9bc7-6a47bb9f0f68) {'password': 'root', 'created_at': datetime.datetime(2017, 9, 28, 21, 12, 19, 611352), 'email': 'airbnb@mail.com', 'updated_at': datetime.datetime(2017, 9, 28, 21, 12, 19, 611363), 'last_name': 'Bar', 'id': '246c227a-d5c1-403d-9bc7-6a47bb9f0f68', 'first_name': 'Betty'}
-- Create a new User 2 --
[User] (fce12f8a-fdb6-439a-afe8-2881754de71c) {'password': 'root', 'created_at': datetime.datetime(2017, 9, 28, 21, 12, 19, 611354), 'email': 'airbnb_2@mail.com', 'updated_at': datetime.datetime(2017, 9, 28, 21, 12, 19, 611368), 'id': 'fce12f8a-fdb6-439a-afe8-2881754de71c', 'first_name': 'John'}
guillaume@ubuntu:~/AirBnB$
guillaume@ubuntu:~/AirBnB$ cat file.json ; echo ""
{"BaseModel.af9b4cbd-2ce1-4e6e-8259-f578097dd15f": {"updated_at": "2017-09-28T21:11:12.971544", "__class__": "BaseModel", "id": "af9b4cbd-2ce1-4e6e-8259-f578097dd15f", "created_at": "2017-09-28T21:11:12.971521"}, "User.38f22813-2753-4d42-b37c-57a17f1e4f88": {"password": "63a9f0ea7bb98050796b649e85481845", "created_at": "2017-09-28T21:11:42.848279", "email": "airbnb@mail.com", "id": "38f22813-2753-4d42-b37c-57a17f1e4f88", "last_name": "Bar", "updated_at": "2017-09-28T21:11:42.848291", "first_name": "Betty", "__class__": "User"}, "User.d0ef8146-4664-4de5-8e89-096d667b728e": {"password": "63a9f0ea7bb98050796b649e85481845", "created_at": "2017-09-28T21:11:42.848280", "email": "airbnb_2@mail.com", "id": "d0ef8146-4664-4de5-8e89-096d667b728e", "updated_at": "2017-09-28T21:11:42.848294", "first_name": "John", "__class__": "User"}, "BaseModel.9bf17966-b092-4996-bd33-26a5353cccb4": {"updated_at": "2017-09-28T21:11:14.963058", "__class__": "BaseModel", "id": "9bf17966-b092-4996-bd33-26a5353cccb4", "created_at": "2017-09-28T21:11:14.963049"}, "BaseModel.a42ee380-c959-450e-ad29-c840a898cfce": {"updated_at": "2017-09-28T21:11:15.504296", "__class__": "BaseModel", "id": "a42ee380-c959-450e-ad29-c840a898cfce", "created_at": "2017-09-28T21:11:15.504287"}, "BaseModel.38a22b25-ae9c-4fa9-9f94-59b3eb51bfba": {"updated_at": "2017-09-28T21:11:13.753347", "__class__": "BaseModel", "id": "38a22b25-ae9c-4fa9-9f94-59b3eb51bfba", "created_at": "2017-09-28T21:11:13.753337"}, "BaseModel.2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4": {"updated_at": "2017-09-28T21:11:14.333862", "__class__": "BaseModel", "id": "2bf3ebfd-a220-49ee-9ae6-b01c75f6f6a4", "created_at": "2017-09-28T21:11:14.333852"}, "User.246c227a-d5c1-403d-9bc7-6a47bb9f0f68": {"password": "root", "created_at": "2017-09-28T21:12:19.611352", "email": "airbnb@mail.com", "id": "246c227a-d5c1-403d-9bc7-6a47bb9f0f68", "last_name": "Bar", "updated_at": "2017-09-28T21:12:19.611363", "first_name": "Betty", "__class__": "User"}, "User.fce12f8a-fdb6-439a-afe8-2881754de71c": {"password": "root", "created_at": "2017-09-28T21:12:19.611354", "email": "airbnb_2@mail.com", "id": "fce12f8a-fdb6-439a-afe8-2881754de71c", "updated_at": "2017-09-28T21:12:19.611368", "first_name": "John", "__class__": "User"}}
guillaume@ubuntu:~/AirBnB$
No unittests needed for the console
Repo:
- GitHub repository:
AirBnB_clone
- File:
models/user.py, models/engine/file_storage.py, console.py, tests/
mandatory
Write all those classes that inherit from BaseModel
:
State
(models/state.py
):- Public class attributes:
name
: string - empty string
- Public class attributes:
City
(models/city.py
):- Public class attributes:
state_id
: string - empty string: it will be theState.id
name
: string - empty string
- Public class attributes:
Amenity
(models/amenity.py
):- Public class attributes:
name
: string - empty string
- Public class attributes:
Place
(models/place.py
):- Public class attributes:
city_id
: string - empty string: it will be theCity.id
user_id
: string - empty string: it will be theUser.id
name
: string - empty stringdescription
: string - empty stringnumber_rooms
: integer - 0number_bathrooms
: integer - 0max_guest
: integer - 0price_by_night
: integer - 0latitude
: float - 0.0longitude
: float - 0.0amenity_ids
: list of string - empty list: it will be the list ofAmenity.id
later
- Public class attributes:
Review
(models/review.py
):- Public class attributes:
place_id
: string - empty string: it will be thePlace.id
user_id
: string - empty string: it will be theUser.id
text
: string - empty string
- Public class attributes:
Repo:
- GitHub repository:
AirBnB_clone
- File:
models/state.py, models/city.py, models/amenity.py, models/place.py, models/review.py, tests/
mandatory
Update FileStorage
to manage correctly serialization and deserialization of all our new classes: Place
, State
, City
, Amenity
and Review
Update your command interpreter (console.py
) to allow those actions: show
, create
, destroy
, update
and all
with all classes created previously.
Enjoy your first console!
No unittests needed for the console
Repo:
- GitHub repository:
AirBnB_clone
- File:
console.py, models/engine/file_storage.py, tests/
- By Guillaume
- Weight: 1
- Ongoing project - started 02-03-2022, must end by 02-08-2022 (in 3 days) - you're done with 0% of tasks.
- Manual QA review must be done (request it when you are done with the project)
For this project, students are expected to look at these concepts:
Now that you have a command interpreter for managing your AirBnB objects, it's time to make them alive!
Before developing a big and complex web application, we will build the front end step-by-step.
The first step is to "design" / "sketch" / "prototype" each element:
- Create simple HTML static pages
- Style guide
- Fake contents
- No Javascript
- No data loaded from anything
During this project, you will learn how to manipulate HTML and CSS languages. HTML is the structure of your page, it should be the first thing to write. CSS is the styling of your page, the design. I really encourage you to fix your HTML part before starting the styling. Indeed, without any structure, you can't apply any design.
Before starting, please fork or clone the repository AirBnB_clone
from your partner if you were not the owner of the previous project.
Read or watch:
- Learn to Code HTML & CSS (until "Creating Lists" included)
- Inline Styles in HTML
- Specifics on CSS Specificity
- CSS SpeciFishity
- Introduction to HTML
- CSS
- MDN
- center boxes
At the end of this project, you are expected to be able to explain to anyone, without the help of Google:
- What is HTML
- How to create an HTML page
- What is a markup language
- What is the DOM
- What is an element / tag
- What is an attribute
- How does the browser load a webpage
- What is CSS
- How to add style to an element
- What is a class
- What is a selector
- How to compute CSS Specificity Value
- What are Box properties in CSS
- Allowed editors:
vi
,vim
,emacs
- All your files should end with a new line
- A
README.md
file, at the root of the folder of the project, is mandatory - Your code should be W3C compliant and validate with W3C-Validator
- All your CSS files should be in
styles
folder - All your images should be in
images
folder - You are not allowed to use
!important
andid
(#...
in the CSS file) - You are not allowed to use tags
img
,embed
andiframe
- You are not allowed to use Javascript
- Current screenshots have been done on
Chrome 56
or more. - No cross browsers
- You have to follow all requirements but some
margin
/padding
are missing - you should try to fit as much as you can to screenshots
Show
mandatory
Write an HTML page that displays a header and a footer.
Layout:
- Body:
- no margin
- no padding
- Header:
- color #FF0000 (red)
- height: 70px
- width: 100%
- Footer:
- color #00FF00 (green)
- height: 60px
- width: 100%
- text
Best School
center vertically and horizontally - always at the bottom at the page
Requirements:
- You must use the
header
andfooter
tags - You are not allowed to import any files
- You are not allowed to use the
style
tag in thehead
tag - Use inline styling for all your tags
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
0-index.html
mandatory
Write an HTML page that displays a header and a footer by using the style
tag in the head
tag (same as 0-index.html
)
Requirements:
- You must use the
header
andfooter
tags - You are not allowed to import any files
- No inline styling
- You must use the
style
tag in thehead
tag
The layout must be exactly the same as 0-index.html
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
1-index.html
mandatory
Write an HTML page that displays a header and a footer by using CSS files (same as 1-index.html
)
Requirements:
- You must use the
header
andfooter
tags - No inline styling
- You must have 3 CSS files:
styles/2-common.css
: for global style (i.e. thebody
style)styles/2-header.css
: for header stylestyles/2-footer.css
: for footer style
The layout must be exactly the same as 1-index.html
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
2-index.html, styles/2-common.css, styles/2-header.css, styles/2-footer.css
mandatory
Write an HTML page that displays a header and footer by using CSS files (same as 2-index.html
)
Layout:
- Common:
- no margin
- no padding
- font color: #484848
- font size: 14px
- font family:
Circular,"Helvetica Neue",Helvetica,Arial,sans-serif;
- icon in the browser tab
- Header:
- color: white
- height: 70px
- width: 100%
- border bottom 1px #CCCCCC
- logo align on left and center vertically (20px space at the left)
- Footer:
- color white
- height: 60px
- width: 100%
- border top 1px #CCCCCC
- text
Best School
center vertically and horizontally - always at the bottom at the page
Requirements:
- No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 3 CSS files:
styles/3-common.css
: for the global style (i.ebody
style)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
3-index.html, styles/3-common.css, styles/3-header.css, styles/3-footer.css, images/
mandatory
Write an HTML page that displays a header, footer and a filters box with a search button.
Layout: (based on 3-index.html
)
- Container:
- between
header
andfooter
tags, add adiv
:- classname:
container
- max width 1000px
- margin top and bottom 30px - it should be 30px under the bottom of the
header
(screenshot) - center horizontally
- classname:
- between
- Filter section:
- tag
section
- classname
filters
- inside the
.container
- color white
- height: 70px
- width: 100% of the container
- border 1px #DDDDDD with radius 4px
- tag
- Button search:
- tag
button
- text
Search
- font size: 18px
- inside the section filters
- background color #FF5A5F
- text color #FFFFFF
- height: 48px
- width: 20% of the section filters
- no borders
- border radius: 4px
- center vertically and at 30px of the right border
- change opacity to 90% when the mouse is on the button
- tag
Requirements:
- You must use:
header
,footer
,section
,button
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 4 CSS files:
styles/4-common.css
: for the global style (body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer stylestyles/4-filters.css
: for the filters style
4-index.html
won't be W3C valid, don't worry, it's temporary
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
4-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/4-filters.css, images/
mandatory
Write an HTML page that displays a header, footer and a filters box.
Layout: (based on 4-index.html
)
- Locations and Amenities filters:
- tag:
div
- classname:
locations
for location tag andamenities
for the other - inside the section filters (same level as the
button
Search) - height: 100% of the section filters
- width: 25% of the section filters
- border right #DDDDDD 1px only for the first left filter
- contains a title:
-
tag:
h3
-
font weight: 600
-
text
States
orAmenities
-
- contains a subtitle:
-
tag:
h4
-
font weight: 400
-
font size: 14px
-
text with fake contents
-
- tag:
Requirements:
- You must use:
header
,footer
,section
,button
,h3
,h4
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 4 CSS files:
styles/4-common.css
: for the global style (body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer stylestyles/5-filters.css
: for the filters style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
5-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/5-filters.css, images/
mandatory
Write an HTML page that displays a header, footer and a filters box with dropdown.
Layout: (based on 5-index.html
)
- Update Locations and Amenities filters to display a contextual dropdown when the mouse is on the filter
div
:- tag
ul
- classname
popover
- text should be fake now
- inside each
div
- not displayed by default
- color #FAFAFA
- width same as the
div
filter - border #DDDDDD 1px with border radius 4px
- no list display
- Location filter has 2 levels of
ul
/li
:- state -> cities
- state name must be display in a
h2
tag (font size 16px)
- tag
Requirements:
- You must use:
header
,footer
,section
,button
,h3
,h4
,ul
,li
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 4 CSS files:
styles/4-common.css
: for the global style (body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer stylestyles/6-filters.css
: for the filters style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
6-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/6-filters.css, images/
mandatory
Write an HTML page that displays a header, footer, a filters box with dropdown and results.
Layout: (based on 6-index.html
)
- Add Places section:
- tag:
section
- classname:
places
- same level as the filters section, inside
.container
- contains a title:
- tag:
h1
- text:
Places
- align in the top left
- font size: 30px
- tag:
- contains multiple "Places" as listing (horizontal or vertical) describe by:
- tag:
article
- width: 390px
- padding and margin 20px
- border #FF5A5F 1px with radius 4px
- contains the place name:
- tag:
h2
- font size: 30px
- center horizontally
- tag:
- tag:
- tag:
Requirements:
- You must use:
header
,footer
,section
,article
,button
,h1
,h2
,h3
,h4
,ul
,li
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 5 CSS files:
styles/4-common.css
: for the global style (i.e.body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for footer stylestyles/6-filters.css
: for the filters stylestyles/7-places.css
: for the places style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
7-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/6-filters.css, styles/7-places.css, images/
mandatory
Write an HTML page that displays a header, a footer, a filter box (dropdown list) and the result of the search.
Layout: (based on 7-index.html
)
Add more information to a Place article
:
- Price by night:
- tag:
div
- classname:
price_by_night
- same level as the place name
- font color: #FF5A5F
- border: #FF5A5F 4px rounded
- min width: 60px
- height: 60px
- font size: 30px
- align: the top right (with space)
- tag:
- Information section:
- tag:
div
- classname:
information
- height: 80px
- border: top and bottom #DDDDDD 1px
- contains (align vertically):
- tag:
- User section:
- tag:
div
- classname:
user
- text
Owner: <fake text>
Owner
text should be in bold
- tag:
- Description section:
- tag:
div
- classname:
description
- tag:
Requirements:
- You must use:
header
,footer
,section
,article
,button
,h1
,h2
,h3
,h4
,ul
,li
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 5 CSS files:
styles/4-common.css
: for the global style (i.e.body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer stylestyles/6-filters.css
: for the filters stylestyles/8-places.css
: for the places style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
8-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/6-filters.css, styles/8-places.css, images/
#advanced
Write an HTML page that displays a header, footer, a filters box with dropdown and results.
Layout: (based on 8-index.html
)
Add more information to a Place article
:
- List of Amenities:
- tag
div
- classname
amenities
- margin top 40px
- contains:
- title:
- tag
h2
- text
Amenities
- font size 16px
- border bottom #DDDDDD 1px
- tag
- list of amenities:
- tag
ul
/li
- no list style
- icons on the left: Pet friendly, TV, Wifi, etc... feel free to add more
- tag
- title:
- tag
- List of Reviews:
- tag
div
- classname
reviews
- margin top 40px
- contains:
- title:
- tag
h2
- text
Reviews
- font size 16px
- border bottom #DDDDDD 1px
- tag
- list of review:
- tag
ul
/li
- no list style
- a review is described by:
h3
tag for the user/date description (font size 14px). Ex: "From Bob Dylan the 27th January 2017"p
tag for the text (font size 12px)
- tag
- title:
- tag
Requirements:
- You must use:
header
,footer
,section
,article
,button
,h1
,h2
,h3
,h4
,ul
,li
tags - No inline style
- You are not allowed to use the
img
tag - You are not allowed to use the
style
tag in thehead
tag - All images must be stored in the
images
folder - You must have 5 CSS files:
styles/4-common.css
: for the global style (body
and.container
styles)styles/3-header.css
: for the header stylestyles/3-footer.css
: for the footer stylestyles/6-filters.css
: for the filters stylestyles/100-places.css
: for the places style
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
100-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/6-filters.css, styles/100-places.css, images/
#advanced
Improve the Places section by using Flexible boxes for all Place articles
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
101-index.html, styles/4-common.css, styles/3-header.css, styles/3-footer.css, styles/6-filters.css, styles/101-places.css, images/
#advanced
Improve the page by adding responsive design to display correctly in mobile or small screens.
Examples:
- no horizontal scrolling
- redesign search bar depending of the width
- etc.
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
102-index.html, styles/102-common.css, styles/102-header.css, styles/102-footer.css, styles/102-filters.css, styles/102-places.css, images/
#advanced
Improve the page by adding Accessibility support
Examples:
- Colors contrast
- Header tags
- etc.
Repo:
- GitHub repository:
AirBnB_clone
- Directory:
web_static
- File:
103-index.html, styles/103-common.css, styles/103-header.css, styles/103-footer.css, styles/103-filters.css, styles/103-places.css, images/