Colors make the world more beautiful.

Schermafdruk van webshop aan het einde van dit hoofdstuk.
In dit hoofdstuk ga je kleuren toevoegen aan elk product. Kleur en product hebben een n:m-relatie.
5.1Uitleg: Tabellen met n:m-relatie maken¶
5.2Opdracht: Voeg artikel-kleuren toe aan de database¶
In deze opdracht ga je kleuren (Engels: colors) toevoegen aan elk artikel in de database. Elk artikel heeft één of meer kleuren. Een kleur wordt gebruikt in één of meer artikelen.
De kleur wordt niet automatisch zichtbaar in je webshop, dat doen we in de volgende opdracht.
Tips
Zie de tips bij de opdracht merken-tabel toevoegen uit het vorige hoofdstuk.
Tips
Zie de tips bij de opdracht merken toevoegen aan de tabel uit het vorige hoofdstuk.
Tips
Voeg de verwijzende sleutels en de constraints toe aan de tabel
product_color
.De volgorde waarin je tabellen in je SQL-bestand zet doet ertoe. De tabel
product_color
moet je na de tabellenproducts
encolors
maken, anders dan kun je er niet naar verwijzen in je constraints in de tabelproduct_color
.Als je niet meer weet hoe je een constraint toevoegt, bekijk dan Uitleg SQL voorbeeld n:m-relatie
Tips
Maak een
INSERT INTO
-opdracht die deproduct_color
-tabel vult.Gebruik in de
INSERT INTO
-opdracht de veldenproduct_id
encolor_id
.Geef in je
INSERT INTO
-opdracht de nummers van de producten en kleuren die bij elkaar passen op. Elke conmbinatie is een nieuwe rij in de tabel.
5.3Uitleg: Query met n:m-relatie maken¶
5.4Uitleg: JSON¶
5.5Opdracht: Maak kleuren per artikel zichtbaar in de webshop¶
Je hebt in de vorige opdracht kleur-informatie aan alle artikelen toegevoegd in de database. Maar deze informatie is nog niet te zien op de webshop. Dat komt omdat de API de kleuren niet opvraagt uit de database. Omdat er meerdere kleuren per product kunnen zijn, moeten we de kleuren in een aparte query opvragen. In deze opdracht ga je de API aanpassen, zodat de informatie over kleuren wordt toegevoegd aan de informatie over artikelen die wordt opgestuurd naar de client. De client is zo gemaakt dat hij deze extra informatie automatisch toont.
Maak kleuren-query en voeg die toe aan artikel-informatie in JSON-formaat¶
De onderstaande code vraagt voor elk artikel de kleuren op uit de database en voegt deze toe aan de artikelinformatie (product_rows
). De API stuurt product_rows
in JSON-formaat naar de client.
Maak de query in de code af door op de plekken met <maak af>
de juiste stukje query in te vullen. De query eindigt met een vraagteken ?
. Op die plek wordt steeds het product_id
ingevuld van het product waarvan we de kleuren opvragen.
# Add values for n:m property (e.g., colors) to products
for product in product_rows:
# Fetch colors for the product
color_query = """
SELECT <maak af>
FROM <maak af>
JOIN <maak af>
WHERE product_id = ?
"""
color_query_params= [product["id"]] # what comes at the place of the questionmark in the query
# Execute the query to fetch colors for the current product
color_rows = db_connection.execute(color_query, color_query_params).fetchall()
# Add fetched colors to product
colors = []
for row in color_rows:
colors.append(row["name"])
product["kleur"] = colors
Kopieer de code op de juiste plek in de API en test of hij het doet.
Performance
In deze opdracht vraag je met een query de kleuren van één product uit de database op. Voor elk product voer je de query opnieuw uit. Dit is niet heel efficient, maar wel eenvoudig. In een webshop met veel meer artikelen zouden programmeurs ervoor kiezen om de kleuren van meerdere producten tegelijk in één query op te vragen.
Omdat we voor het product alleen product_id
nodig hebben om de kleuren uit de database op te vragen, hoeven we maar twee tabellen te gebruiken: product_color
en colors
. Die tabellen hebben een 1:n-relatie. Dit is vergelijkbaar met de manier waarop het staat in Uitleg SQL voorbeeld 1:n-relatie.
Wanneer je meerdere kleuren van meerdere producten opvraagt in één query, dan gebruik je de n:m-relatie tussen producten en kleuren. Daarvoor heb je drie tabellen nodig: products
, colors
en de koppeltabel product_color
. Dit is zoals het staat in Uitleg SQL voorbeeld n:m-relatie.
SQL-injection
In onze code wordt de execute
functie gebruikt om de query uit te voeren. De execute
-functie vult ook de parameters in, zoals product_id
. We hadden die parameter ook gewoon met +
aan de query kunnen toevoegen,maar dat doen we bewust niet.
Tijdens het invullen controleert de execute
-functie of er geen rare dingen in het product_id
staan. In deze code komt de waarde van product_id
uit de database waar alleen ontwikkelaars bij kunnen. Bij het hoofdstuk over filters zul je zien dat parameters ook door de client (de computer van bezoekers) opgestuurd kunnen worden. Deze parameters zouden bezoekers kunnen veranderen voordat ze ze opsturen.
Door de waarde van de parameter slim te kiezen kunnen gebruikers informatie uit de database halen die niet voor hen bedoeld is. Denk bijvoorbeeld aan een parameter product_id
met de waarde 1; SELECT * FROM passwords;
. De database denkt dan dat hij twee opdrachten moet uitvoeren waarvan de laatste de wachtwoorden geeft. Deze truuk heet SQL-injectie.
In de praktijk is het meestal niet zo gemakkelijk om een systeem te hacken met SQL-injectie, onder andere omdat wachtwoorden niet zomaar in een database worden gezet. Maar als je Googlet op SQL-injection, dan zie je dat het een veelvoorkomend probleem is. In onze database kan dit niet gebeuren, omdat we alle parameters door de execute
-functie laten controlere.
Tips
De aanpassing moet je doen in de API, in het bestand
/app/main.py
bij de functie voor het endpoint/api/products/
.Let op de commentaarregel om te zien naar welke plek je de code exact moet kopieren.
Voeg aan de query een
SELECT
toe met één veld, namelijk de naam van de kleur.Voeg aan de query een
JOIN
toe tussen de tabellenproduct_color
encolors
.Controleer wat de API opstuurt naar de client. Zet in je browser achter de hostname van je webshop
/api/products/
en laadt die webpagina. Het antwoord is hetzelfde antwoord als wat de client van de API zou krijgen. Je ziet de artikelinformatie in JSON-formaat.