diff --git a/app/inventory/views.py b/app/inventory/views.py
index 145766bcb1f6c60ee5e4d8f0d5c6db7353a1c9fc..053577f2ec68742fe5599af43dbedce9a14496a4 100644
--- a/app/inventory/views.py
+++ b/app/inventory/views.py
@@ -12,7 +12,7 @@ This module implements the inventory blueprint.
 import sqlalchemy as sa
 from flask import (Blueprint, render_template, jsonify, session,
                    request, redirect, url_for, flash, current_app)
-from flask_login import login_required
+from flask_login import login_required, current_user
 from .forms import AttributeForm, ItemForm, CommentForm
 from ..extensions import db
 from ..decorators import login_groups_accepted
@@ -205,6 +205,26 @@ def edit_item(ics_id):
     return render_template('inventory/edit_item.html', form=form)
 
 
+@bp.route('/attributes/favorites')
+@login_required
+def attributes_favorites():
+    return render_template('inventory/attributes_favorites.html')
+
+
+@bp.route('/_retrieve_attributes_favorites')
+@login_required
+def retrieve_attributes_favorites():
+    if current_user not in db.session:
+        # If the current user is cached, it won't be in the sqlalchemy session
+        # Add it to access the user favorite attributes relationship
+        db.session.add(current_user)
+    data = [(favorite.base64_image(),
+             type(favorite).__name__,
+             favorite.name,
+             favorite.description) for favorite in current_user.favorite_attributes()]
+    return jsonify(data=data)
+
+
 @bp.route('/attributes/<kind>', methods=('GET', 'POST'))
 @login_groups_accepted('admin', 'create')
 def attributes(kind):
@@ -233,10 +253,44 @@ def retrieve_attributes(kind):
     except AttributeError:
         raise utils.CSEntryError(f"Unknown model '{kind}'", status_code=422)
     items = db.session.query(model).order_by(model.name)
-    data = [(item.base64_image(), item.name, item.description) for item in items]
+    data = [({'id': item.id, 'favorite': item.is_user_favorite()},
+             item.base64_image(),
+             item.name,
+             item.description) for item in items]
     return jsonify(data=data)
 
 
+@bp.route('/_update_favorites/<kind>', methods=['POST'])
+@login_required
+def update_favorites(kind):
+    """Update the current user favorite attributes
+
+    Add or remove the attribute from the favorites when the
+    checkbox is checked/unchecked in the attributes table
+    """
+    if current_user not in db.session:
+        # If the current user is cached, it won't be in the sqlalchemy session
+        # Add it to access the user favorite attributes relationship
+        db.session.add(current_user)
+    try:
+        model = getattr(models, kind)
+    except AttributeError:
+        raise utils.CSEntryError(f"Unknown model '{kind}'", status_code=422)
+    data = request.get_json()
+    attribute = model.query.get(data['id'])
+    favorite_attributes_str = utils.pluralize(f'favorite_{kind.lower()}')
+    user_favorite_attributes = getattr(current_user, favorite_attributes_str)
+    if data['checked']:
+        user_favorite_attributes.append(attribute)
+        message = 'Attribute added to the favorites'
+    else:
+        user_favorite_attributes.remove(attribute)
+        message = 'Attribute removed from the favorites'
+    db.session.commit()
+    data = {'message': message}
+    return jsonify(data=data), 201
+
+
 @bp.route('/scanner')
 @login_required
 def scanner():
diff --git a/app/models.py b/app/models.py
index 2e52834c2b8aaba957cec6c66d1fc5fbca53ea7c..fada30a80ebea18ac708e0a1af910b03534dc48f 100644
--- a/app/models.py
+++ b/app/models.py
@@ -95,6 +95,34 @@ def save_user(dn, username, data, memberships):
     return user
 
 
+# Tables required for Many-to-Many relationships between users and favorites attributes
+favorite_manufacturers_table = db.Table(
+    'favorite_manufacturers',
+    db.Column('user_id', db.Integer, db.ForeignKey('user_account.id'), primary_key=True),
+    db.Column('manufacturer_id', db.Integer, db.ForeignKey('manufacturer.id'), primary_key=True)
+)
+favorite_models_table = db.Table(
+    'favorite_models',
+    db.Column('user_id', db.Integer, db.ForeignKey('user_account.id'), primary_key=True),
+    db.Column('model_id', db.Integer, db.ForeignKey('model.id'), primary_key=True)
+)
+favorite_locations_table = db.Table(
+    'favorite_locations',
+    db.Column('user_id', db.Integer, db.ForeignKey('user_account.id'), primary_key=True),
+    db.Column('location_id', db.Integer, db.ForeignKey('location.id'), primary_key=True)
+)
+favorite_statuses_table = db.Table(
+    'favorite_statuses',
+    db.Column('user_id', db.Integer, db.ForeignKey('user_account.id'), primary_key=True),
+    db.Column('status_id', db.Integer, db.ForeignKey('status.id'), primary_key=True)
+)
+favorite_actions_table = db.Table(
+    'favorite_actions',
+    db.Column('user_id', db.Integer, db.ForeignKey('user_account.id'), primary_key=True),
+    db.Column('action_id', db.Integer, db.ForeignKey('action.id'), primary_key=True)
+)
+
+
 class User(db.Model, UserMixin):
     # "user" is a reserved word in postgresql
     # so let's use another name
@@ -106,6 +134,33 @@ class User(db.Model, UserMixin):
     email = db.Column(db.Text)
     groups = db.Column(postgresql.ARRAY(db.Text), default=[])
     tokens = db.relationship("Token", backref="user")
+    # The favorites won't be accessed very often so we load them
+    # only when necessary (lazy=True)
+    favorite_manufacturers = db.relationship(
+        'Manufacturer',
+        secondary=favorite_manufacturers_table,
+        lazy=True,
+        backref=db.backref('favorite_users', lazy=True))
+    favorite_models = db.relationship(
+        'Model',
+        secondary=favorite_models_table,
+        lazy=True,
+        backref=db.backref('favorite_users', lazy=True))
+    favorite_locations = db.relationship(
+        'Location',
+        secondary=favorite_locations_table,
+        lazy=True,
+        backref=db.backref('favorite_users', lazy=True))
+    favorite_statuses = db.relationship(
+        'Status',
+        secondary=favorite_statuses_table,
+        lazy=True,
+        backref=db.backref('favorite_users', lazy=True))
+    favorite_actions = db.relationship(
+        'Action',
+        secondary=favorite_actions_table,
+        lazy=True,
+        backref=db.backref('favorite_users', lazy=True))
 
     def get_id(self):
         """Return the user id as unicode
@@ -137,6 +192,13 @@ class User(db.Model, UserMixin):
             names.extend(current_app.config['CSENTRY_LDAP_GROUPS'].get(group))
         return bool(set(self.groups) & set(names))
 
+    def favorite_attributes(self):
+        """Return all user's favorite attributes"""
+        favorites_list = [self.favorite_manufacturers, self.favorite_models,
+                          self.favorite_locations, self.favorite_statuses,
+                          self.favorite_actions]
+        return [favorite for favorites in favorites_list for favorite in favorites]
+
     def __str__(self):
         return self.username
 
@@ -190,6 +252,11 @@ class QRCodeMixin:
         """Return the QRCode image as base64 string"""
         return utils.image_to_base64(self.image())
 
+    def is_user_favorite(self):
+        """Return True if the attribute is part of the current user favorites"""
+        user = utils.cse_current_user()
+        return user in self.favorite_users
+
     def __str__(self):
         return self.name
 
diff --git a/app/static/js/attributes.js b/app/static/js/attributes.js
index 7836228ab31168f66b2c7fef5fd610899f053252..4764121ab86e7254827506efa4319f14f55052a7 100644
--- a/app/static/js/attributes.js
+++ b/app/static/js/attributes.js
@@ -9,6 +9,54 @@ $(document).ready(function() {
           callback(json);
         });
     },
+    "order": [[2, 'asc']],
+    "columnDefs": [
+      {
+        "targets": [0],
+        "orderable": false,
+        'className': 'text-center align-middle',
+        "render": function(data, type, row) {
+          // render a checkbox to add/remove the attribute to the user's favorites
+          var checked = data.favorite ? "checked" : ""
+          return '<input type="checkbox" value="' + data.id + '" ' + checked + '>'
+        },
+        "width": "5%",
+      },
+      {
+        "targets": [1],
+        "orderable": false,
+        "render": function(data, type, row) {
+          // render QR code from base64 string
+          return '<img class="img-fluid" src="data:image/png;base64,' + data + '">';
+        },
+        "width": "10%",
+      }
+    ],
+    "paging": false
+  });
+
+  // update the user favorites
+  $("#attributes_table").on('change', 'input[type="checkbox"]', function() {
+    var kind = $('li a.nav-link.active').text();
+    $.ajax({
+      type: "POST",
+      url: $SCRIPT_ROOT + "/inventory/_update_favorites/" + kind ,
+      data: JSON.stringify({
+        id: $(this).val(),
+        checked: this.checked
+      }),
+      contentType : 'application/json'
+    });
+  });
+
+  var attributes_favorites_table =  $("#attributes_favorites_table").DataTable({
+    "ajax": function(data, callback, settings) {
+      $.getJSON(
+        $SCRIPT_ROOT + "/inventory/_retrieve_attributes_favorites",
+        function(json) {
+          callback(json);
+        });
+    },
     "order": [[1, 'asc']],
     "columnDefs": [
       {
diff --git a/app/templates/inventory/attributes.html b/app/templates/inventory/attributes.html
index 36f15f68c43ea0df3257ba303161e12ad7841cad..2779a3775f9fdfd30f23f103ddfed7e37f76e60d 100644
--- a/app/templates/inventory/attributes.html
+++ b/app/templates/inventory/attributes.html
@@ -10,10 +10,14 @@
       <a class="nav-link {% if attribute == kind %}active{% endif %}" href="{{ url_for('inventory.attributes', kind=attribute) }}">{{ attribute }}</a>
     </li>
     {% endfor %}
+    <li class="nav-item">
+      <a class="nav-link {{ is_active(request.path.startswith("/inventory/attributes/favorites")) }}" href="{{ url_for('inventory.attributes_favorites') }}">Favorites</a>
+    </li>
   </ul>
 
   <br>
 
+  {% block attributes_main %}
   {% if kind in ('Manufacturer', 'Model', 'Location') or (current_user.is_authenticated and current_user.is_admin and kind != 'Action') %}
     <form id="attributeForm" method="POST">
       {{ form.hidden_tag() }}
@@ -32,12 +36,14 @@
   <table id="attributes_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
     <thead>
       <tr>
-        <th></th>
+        <th>Favorite</th>
+        <th>QRCode</th>
         <th>Name</th>
         <th>Description</th>
       </tr>
     </thead>
   </table>
+  {%- endblock %}
 {%- endblock %}
 
 {% block csentry_scripts %}
diff --git a/app/templates/inventory/attributes_favorites.html b/app/templates/inventory/attributes_favorites.html
new file mode 100644
index 0000000000000000000000000000000000000000..cdb16b5bb36f9eca7d0507aa680650969a0d0f37
--- /dev/null
+++ b/app/templates/inventory/attributes_favorites.html
@@ -0,0 +1,16 @@
+{% extends "inventory/attributes.html" %}
+
+{% block title %}Attributes favorites - CSEntry{% endblock %}
+
+{% block attributes_main %}
+  <table id="attributes_favorites_table" class="table table-bordered table-hover table-sm" cellspacing="0" width="100%">
+    <thead>
+      <tr>
+        <th>QRCode</th>
+        <th>Kind</th>
+        <th>Name</th>
+        <th>Description</th>
+      </tr>
+    </thead>
+  </table>
+{%- endblock %}
diff --git a/app/utils.py b/app/utils.py
index 991676109f670a9644c0b480597a81078bddbe77..a5c2e06e183a3dd9407939fdc3652f4cea7b9589 100644
--- a/app/utils.py
+++ b/app/utils.py
@@ -198,3 +198,14 @@ def random_mac():
               random.randint(0x00, 0xFF)]
     octets = [f'{nb:02x}' for nb in octets]
     return ':'.join((current_app.config['MAC_OUI'], *octets))
+
+
+def pluralize(singular):
+    """Return the plural form of the given word
+
+    Used to pluralize API endpoints (not any given english word)
+    """
+    if not singular.endswith('s'):
+        return singular + 's'
+    else:
+        return singular + 'es'
diff --git a/migrations/versions/a73eeb144fa1_add_user_favorite_attributes_tables.py b/migrations/versions/a73eeb144fa1_add_user_favorite_attributes_tables.py
new file mode 100644
index 0000000000000000000000000000000000000000..1594017d295b3cb394a4d3f42afa6d00dfb60d17
--- /dev/null
+++ b/migrations/versions/a73eeb144fa1_add_user_favorite_attributes_tables.py
@@ -0,0 +1,67 @@
+"""Add user favorite attributes tables
+
+Revision ID: a73eeb144fa1
+Revises: ac6b3c416b07
+Create Date: 2018-04-07 21:23:33.337335
+
+"""
+from alembic import op
+import sqlalchemy as sa
+
+
+# revision identifiers, used by Alembic.
+revision = 'a73eeb144fa1'
+down_revision = 'ac6b3c416b07'
+branch_labels = None
+depends_on = None
+
+
+def upgrade():
+    op.create_table(
+        'favorite_actions',
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('action_id', sa.Integer(), nullable=False),
+        sa.ForeignKeyConstraint(['action_id'], ['action.id'], name=op.f('fk_favorite_actions_action_id_action')),
+        sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], name=op.f('fk_favorite_actions_user_id_user_account')),
+        sa.PrimaryKeyConstraint('user_id', 'action_id', name=op.f('pk_favorite_actions'))
+    )
+    op.create_table(
+        'favorite_locations',
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('location_id', sa.Integer(), nullable=False),
+        sa.ForeignKeyConstraint(['location_id'], ['location.id'], name=op.f('fk_favorite_locations_location_id_location')),
+        sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], name=op.f('fk_favorite_locations_user_id_user_account')),
+        sa.PrimaryKeyConstraint('user_id', 'location_id', name=op.f('pk_favorite_locations'))
+    )
+    op.create_table(
+        'favorite_manufacturers',
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('manufacturer_id', sa.Integer(), nullable=False),
+        sa.ForeignKeyConstraint(['manufacturer_id'], ['manufacturer.id'], name=op.f('fk_favorite_manufacturers_manufacturer_id_manufacturer')),
+        sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], name=op.f('fk_favorite_manufacturers_user_id_user_account')),
+        sa.PrimaryKeyConstraint('user_id', 'manufacturer_id', name=op.f('pk_favorite_manufacturers'))
+    )
+    op.create_table(
+        'favorite_models',
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('model_id', sa.Integer(), nullable=False),
+        sa.ForeignKeyConstraint(['model_id'], ['model.id'], name=op.f('fk_favorite_models_model_id_model')),
+        sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], name=op.f('fk_favorite_models_user_id_user_account')),
+        sa.PrimaryKeyConstraint('user_id', 'model_id', name=op.f('pk_favorite_models'))
+    )
+    op.create_table(
+        'favorite_statuses',
+        sa.Column('user_id', sa.Integer(), nullable=False),
+        sa.Column('status_id', sa.Integer(), nullable=False),
+        sa.ForeignKeyConstraint(['status_id'], ['status.id'], name=op.f('fk_favorite_statuses_status_id_status')),
+        sa.ForeignKeyConstraint(['user_id'], ['user_account.id'], name=op.f('fk_favorite_statuses_user_id_user_account')),
+        sa.PrimaryKeyConstraint('user_id', 'status_id', name=op.f('pk_favorite_statuses'))
+    )
+
+
+def downgrade():
+    op.drop_table('favorite_statuses')
+    op.drop_table('favorite_models')
+    op.drop_table('favorite_manufacturers')
+    op.drop_table('favorite_locations')
+    op.drop_table('favorite_actions')
diff --git a/tests/functional/test_models.py b/tests/functional/test_models.py
index b96c16222757ab91fdfd92b5c6cbbb22913dabd7..bb84d7c1f01dd69cceec499a46270de061b7e04e 100644
--- a/tests/functional/test_models.py
+++ b/tests/functional/test_models.py
@@ -104,3 +104,20 @@ def test_mac_address_validation(mac_factory):
     with pytest.raises(ValidationError) as excinfo:
         mac = mac_factory(address='F4A73915DA')
     assert "'F4A73915DA' does not appear to be a MAC address" in str(excinfo.value)
+
+
+def test_manufacturer_favorite_users(user_factory, manufacturer_factory):
+    user1 = user_factory()
+    user2 = user_factory()
+    user3 = user_factory()
+    manufacturer1 = manufacturer_factory()
+    manufacturer2 = manufacturer_factory()
+    user1.favorite_manufacturers.append(manufacturer2)
+    assert manufacturer1.favorite_users == []
+    assert manufacturer2.favorite_users == [user1]
+    user2.favorite_manufacturers.append(manufacturer2)
+    user3.favorite_manufacturers.append(manufacturer1)
+    assert manufacturer2.favorite_users == [user1, user2]
+    assert user2 in manufacturer2.favorite_users
+    assert user2 not in manufacturer1.favorite_users
+    assert user3 in manufacturer1.favorite_users