Författare: Maria

  • Gott Nytt År 2026!

    Gott Nytt År 2026!

    Nytt år nya tag. Igen.

    Inga nyårslöften i år heller. Jag kör på som vanligt med många olika projekt efter lust och behag.

    Året som gick var ett bra år.

    • Jag sydde en overall som jag kan ha när jag är ute i naturen i Tiveden. Enkelt att hitta fästingar som kryper
    • Jag sydde en massa påsar som är bra att ha saker i, istället för plastlådor
    • Jag sydde ännu fler julklappspåsar, att ha julklappar i, istället för en massa papper och plast
    • Jag lade om ena sidan av taket på stugan
    • Jag röjde sly utefter vägen vid stugan
    • Jag släktforskade
    • Jag programmerade, se min portfolio
    • Jag kombinerade programmering och släktforskning, det ska jag fortsätta med.
    • Jag ordnade i trädgården, både i stugan och hemma. Odlade potatis, cirka 30 kilo blev det. Tomater och gurka trivdes inte så bra i år.
    • Jag vandrade och fotograferade men lite mindre under 2025.
    • Jag fick nya arbetsuppgifter på jobbet

    Jag har säkert glömt något. Det är lättast att komma ihåg det jag gjorde sist såklart.

  • Tips från IT-supporten Julupplaga: God jul från supporten

    Tips från IT-supporten Julupplaga: God jul från supporten

    Att jobba med människor kan vara otroligt slitsamt men också roligt och energigivande. Som detta svar på ett ärende jag gjorde klart några dagar innan jul ett år:

    Tusen tack för snabb service ⭐
    Önskar er alla en god jul och gott nytt år ☃️

    Detsamma önskar jag er som hittat hit!

  • Tips från IT-supporten del 6: Läs svaret

    Tips från IT-supporten del 6: Läs svaret

    Ganska ofta skickar vi med en instruktion där vi beskriver hur d kan lösa ditt problem på egen hand. Ibland blir det tyvärr ganska mycket text och är det stressigt på jobbet finns inte alltid förmågan att ta in och processa ny information. Been there done that.

    Anledningen till att du får en instruktion för att lösa ett problem kan vara att det är ett ganska vanligt problem som är lätt att fixa bara en vet hur en ska göra. Fördelen med att få det i skrift är att meddelandet (oftast i mailform eller mail med länk till en webbsida) kan letas på och användas nästa gång problemet uppstår eller skickas vidare till någon kollega som fastnar på samma sak.

    För ett tag sedan gick jag igenom och rensade i min egen mail, ärendehanteringssystemet skickar mail till handläggaren när någon skrivit i ärendet så att vi kan gå in och fortsätta arbeta med ärendet. Då blev jag påmind om att det är ganska ofta som vi skickar en instruktion, så kommer det en följdfråga som vi svarar på och så fortsätter det så ett tag tills vi kommer tillbaka till: läs instruktionen som jag skickade första gången. I många fall löser det även följdproblem som vi får lägga tid på att felsöka innan det kommer fram att första steget hoppats över för att det verkade onödigt.

  • Tips från IT-supporten del 5: Fråga en vän

    Tips från IT-supporten del 5: Fråga en vän

    Ibland blir jag lite nedslagen när jag får in ärenden till supporten. Finns det ingen i din närhet som du kan fråga först, innan du tar dig tiden att leta på support-formuläret och sätta ihop din frågeställning? Om du inte kan be dina kollegor om hjälp, hur har du det på jobbet egentligen?

    Det finns två stora fördelar med att be en kollega eller vän om hjälp först. Dels så känns det bra att få förtroendet att hjälpa någon annan, att någon tror att jag kan fast jag egentligen inte vet något. Dels så har kollegor förhoppningsvis koll på lokala rutiner som vi i supporten inte har en aning om – vi kan hur systemet fungerar men vet inte vad ni ska skriva och ibland inte var det ska skrivas heller eftersom det kan bero på i vilket sammanhang det ska dokumenteras.

    En bonus är att när du har någon som står över axeln och försöker förstå ditt problem medan du förklarar så brukar det klarna av sig själv! Jag vet inte hur många gånger jag stått bredvid och tittat på (eller haft någon bredvid mig som tittat på) och så har det plötsligt klarnat och knappen som nyss inte fungerar har plötsligt kommit igång. Det troligaste är väl att stress eller annat gjort att saker klickats på i fel ordning eller missats, men det kan vara en liten aning magi också.

  • Tips från IT-supporten del 4: Positiv feedback

    Tips från IT-supporten del 4: Positiv feedback

    När en sitter där ensam i sin lilla bubbla och jobbar på med ärenden kan en känna sig ganska sårbar för kritik. Vid lite närmare eftertanke kanske det inte var så illa ment som en tolkade det först. Ett par tankevändor till när en kommer på att personen jobbar på en klinik med underbemanning och själv har hunnit skicka ett antal ärenden av varierande kvalitet så kanske det faktiskt bara berott på stress att vi inte lyckas nå varandra.

    Då har jag som arbetar i supporten en viktig roll att fylla genom att andas in och ut, titta på ärendet från början utifrån den information jag samlat in och tänka att vi arbetar mot samma mål. Ofta är det bästa i de lägena, om konversationen skett skriftligt, att ringa upp kund och gå igenom problemet tillsammans, helst också genom att koppla upp sig på kundens dator så att en ser vad som händer och varför.

    Efter sådana duster känns det ganska bra att få tillbaka ett ”Fantastiskt, tack! :-)”. Då har det blivit ett bra samarbete.

    Glöm inte att ge positiv feedback när du känner att någon gjort ett bra jobb, oavsett vad du jobbar med eller vem som berörs!

  • Tips från IT-supporten del 3: Skjut inte budbäraren

    Tips från IT-supporten del 3: Skjut inte budbäraren

    Vi har nog alla hamnat i kläm mellan personer som borde kommunicera direkt med varandra någon gång. Som sjuksköterske- och barnmorskestudent var det vanligt att jag ombads fråga läkaren eller patienten om något som uppstått sedan senast. ”Fråga patienten om den fortfarande har ont i benet”. Ja, det hade den och den undrade om det gick att få smärtstillande. ”Nej, det är två timmar kvar för att vi inte ska överdosera. Är smärtan skärande, stickande eller molande?”. Dags att kuta tillbaka till patienten och förmedla de nedslående nyheterna att jag inte kan hjälpa till genast att lindra smärtan och ställa kompletterande frågor som sedan skulle förmedlas till handledaren som kanske hade ytterligare följdfrågor.

    Ännu värre känns det de gångerna där ena parten har en fråga som jag inte förstår för att jag inte har hela bilden, då kommer jag tillbaka med en fråga som jag inte riktigt vet hur jag ska ställa (jag kanske inte kan eller förstår orden som används).

    Så är det ganska ofta i supporten. Oftast är det en sekreterare som får ställa fråga till oss som en läkare inte har tid att ringa eller skriva till oss om. Eftersom sekreteraren inte riktigt förstår vad läkaren menar blir frågan otydlig, vi ställer följdfrågor som sekreteraren får förmedla och sedan återkomma med svar. Om ni anade vilken tid det tar att hålla på på det sättet! Tänk om den som hade problem kunde hära av sig själv! Då hade problemet blivit löst över ett telefonsamtal i de flesta fallen istället för att bolla fram och tillbaka i värsta fall i veckovis.

    Dagens tips

    Om du har ett problem där du behöver hjälp av support: Ring eller skriv själv! I slutändan spar det en massa tid för både dig och mig. Plus att vi båda slipper bli irriterad på stackaren i mitten som kommer med en massa orediga svar.

  • Tips från IT-supporten del 2: Var nåbar

    Tips från IT-supporten del 2: Var nåbar

    Visst är det skönt att kunna slänga iväg ett ärende till IT-supporten innan en går hem på fredagen, eller ännu bättre precis innan semestern börjar så de får lite tid på sig. Schysst!

    NEJ!
    Hur hade du tänkt att vi skulle kunna få tag på dig om vi behöver ställa följdfrågor? Även om problemet skulle vara perfekt formulerat kanske vi behöver få komma in i datorn medan du är inloggad för att kunna felsöka.

    TIPS:
    Jag förstår att det är skönt att kunna bocka av en sak på listan, har själv varit där, men räkna inte med att problemet är löst tills du kommer tillbaka. Risken är att ärendet avslutas utan åtgärd, särskilt om du glömmer att lägga in frånvaromeddelande på mailen och telefon.

  • Skillnad mellan emojis och bootstrap- eller Font Awesome-ikoner

    Skillnad mellan emojis och bootstrap- eller Font Awesome-ikoner

    När jag byggt min sida har jag ibland tagit hjälp av AI för att skynda på tråkiga och repetetiva uppgifter eller för att kontrollera koden. Jag bygger min sida med bootstrap men började blanda in Font Awesome för bullets och liknande. När jag fick hjälp av AI började den blanda in smiley-bilder. Det blir ju inte enhetligt så när jag skulle börja få ihop allt frågade jag AI och fick detta svar (jag har renskrivit texten så att den blir ”min”.

    Jag gjorde två sökningar, först en generell, sedan en mer programmerings-inriktad sökning som gav lite olika svar.

    Summan är att om du använder Bootstrap är rekommendationen att hålla sig till det

    En enkel jämförelse

    EgenskapEmojis (som nu)Font AwesomeBootstrap Icons
    Enkel att användaJaKräver inkludering via CDNKräver inkludering via CDN
    Anpassningsbar med CSSNej (begränsat)Ja (storlek, färg, animering)Ja
    Visuell konsistensBeror på OS/browserAlltid sammaAlltid samma
    TillgänglighetOfta bra, men varierarBättre kontroll via ariaBättre kontroll
    BrowserstödMycket braMycket braMycket bra
    LaddningstidIngen extraKräver laddning av CSS/fontsKräver laddning av SVG
    Antal tillgängliga ikonerBegränsatMycket stortStort, men mindre än FA

    Rekommendation

    För snabb prototyp eller enklare sidor:

    Emojis är snabba, fungerar utan externa beroenden och ger sidan en charmig personlighet.

    För mer professionellt, enhetligt resultat:

    Använd Font Awesome eller Bootstrap Icons – du får då:

    • Enhetliga ikoner oavsett plattform
    • Möjlighet att styla ikoner som du vill (färg, storlek, placering)
    • Tillgänglighetsfördelar (via aria-hidden, title etc.)

    En mer genomgående jämförelse

    EgenskapFont AwesomeBootstrap IconsLättviktiga alternativ (Feather, Heroicons)
    Omfattning> 8 000 ikoner (free+pro)~1 200 ikoner~200–300 ikoner
    IntegrationEnkel med CDN eller npm, bred community-supportIngår i Bootstrap-ekosystemet, enkel via CDN/npmKräver oftast npm/build-verktyg eller SVG-inkludering
    FilstorlekTyngre (många ikoner packade, men du kan plocka ut subset)Mellanstor (SVG-sprite eller en och en SVG-fil)Mycket lätt (enskilda SVG-filer, inga extra typsnitt)
    LicensFree + kommersiell Pro-licensMIT-licens (helt gratis)MIT-licens (helt gratis)
    AnpassningFärger, storlek, animationer via CSS/JSFärger, storlek via CSS; enklare än Font AwesomeFull kontroll över varje SVG; lätt att skräddarsy i kod/editorn

    Rekommendation

    För en ren, Bootstrap-baserad sida där du vill behålla minimalt krångel bör du välja Bootstrap Icons:

    • De följer samma stilguide som resten av Bootstrap
    • Snabbt att installera och använda utan extra byggerier
    • MIT-licens utan begränsningar

    Om du däremot redan har ett Font Awesome Pro-konto eller om du tror att du behöver en mycket större ikon-portfolio i framtiden är Font Awesome ett starkt alternativ. Vill du istället hålla nere paketet riktigt litet och bara ladda exakt de ikoner du använder, titta på till exempel Feather Icons eller Heroicons.


    När du väljer:

    1. Tänk igenom hur många olika ikoner du faktiskt behöver.
    2. Prioritera stil- och licenskompatibilitet med dina övriga verktyg.
    3. Se över om du vill kunna anpassa ikoner i CSS (t.ex. färg, hover-effekter) utan extra JavaScript.

    Hoppas det hjälper dig att hitta rätt när du vill välja ikonbibliotek!

  • Åtgärda Alembic-fel i Flask: En steg-för-steg-guide

    Åtgärda Alembic-fel i Flask: En steg-för-steg-guide

    Nu när jag nästan var klar med min nya hemsida, bara lite puts kvar så började plötsligt mina databasmigreringar att strula.

    Please edit configuration/connection/logging settings in 'C:\\Users\\maria\\Documents\\PyCharmProjects\\MittProjekt\\migrations\\alembic.ini' before proceeding.

    Detta är vad jag fann för att rätta till problemet:

    Varför visas felet ”Please edit configuration/connection/logging settings…”?

    Det meddelande som visas (”Please edit configuration/connection/logging settings in ’…/migrations/alembic.ini’ before proceeding.”) är Alembics generella uppmaning efter att man initierat en ny migrationsmiljö. Alembic påminner om att man måste ange vissa inställningar (framförallt databasens URL) i konfigurationsfilen alembic.ini innan man går vidare (alembic.sqlalchemy.org). Om man inte har justerat denna fil (eller på annat sätt försett Alembic med databasens anslutningssträng) kommer Alembic att varna om att standardinställningarna fortfarande är ogiltiga.

    I en Flask-applikation som följer application factory-mönstret (där appen skapas via en funktion create_app), definieras databasens URL oftast i app-konfigurationen (app.config['SQLALCHEMY_DATABASE_URI']). När man kör flask db init skapas en alembic.ini med en platshållar-URL (t.ex. driver://user:pass@localhost/dbname). Om denna inte ersätts eller överskrivs får man ovanstående meddelande. Felet orsakas alltså av att Alembic ännu inte vet vilken databas den ska koppla upp mot. I praktiken är det ingen kraschande bugg, utan en uppmaning att konfigurera Alembic korrekt. Om Flask-Migrate används korrekt kan man ofta ignorera meddelandet och fortsätta med t.ex. flask db migrate – Flask-Migrate kommer då att hämta databas-URL:en från Flask-appen automatiskt (stackoverflow.com). Men för att undvika förvirring bör man se till att Alembic-konfigurationen ställs in rätt.

    Anpassa alembic.ini och env.py för att fungera med create_app

    För att Alembic ska fungera ihop med en Flask-app som skapas dynamiskt via create_app behöver man justera både alembic.ini och migrations/env.py:

    • alembic.ini: Här kan man ange databasens URL direkt under sektionen [alembic] med nyckeln sqlalchemy.url. Till exempel för MySQL:
    sqlalchemy.url = mysql+pymysql://<user>:<password>@<host>/<databasename>

    Detta hårdkodar anslutningssträngen. Alternativt kan man låta denna rad vara en dummy (eller använda en miljövariabelsreferens) och istället sätta URL:en via env.py – vilket är vanligare när man använder Flask-Migrate för att hämta appens konfiguration i stället för att duplicera den i alembic.ini.
    Övriga viktiga rader i alembic.ini är normalt: script_location (som ska peka på migrationskatalogen, t.ex. migrations) och eventuellt inställningar för loggning. Standardvärdena som genererats av flask db init brukar redan vara korrekta för dessa, men bekräfta att script_location = migrations matchar din projektstruktur. För MySQL kan man även försäkra sig om att uppsättningar som encoding (t.ex. utf8mb4) är korrekta om de förekommer.

    • migrations/env.py: Denna fil körs vid varje migrationskommando och här behöver vi koppla in Flask-applikationen så att Alembic får tillgång till appens konfiguration (databas-URL) och modeller. I en application factory-arkitektur måste env.py antingen:

    Använda Flask CLI:s app-kontekst (current_app): Om man kör kommandona via flask db ... och har talat om för Flask hur appen ska skapas (t.ex. genom att sätta miljövariabeln FLASK_APP till "app:create_app"), då kommer Flask att skapa appen och pusha en app context åt Alembic. I env.py kan man då nå appen via flask.current_app. Exempelvis:

    from flask import current_app
    config.set_main_option('sqlalchemy.url', current_app.config.get('SQLALCHEMY_DATABASE_URI'))
    target_metadata = current_app.extensions['migrate'].db.metadata

    Här hämtar vi databasens URL från appens konfiguration och sätter den i Alembics config, samt tar ut target_metadata (d.v.s. metadata för alla modeller) från SQLAlchemy-objektet som Flask-Migrate registreratstackoverflow.com. Flask-Migrate extension ser till att current_app.extensions['migrate'].db hänvisar till din SQLAlchemy-instans. (Notera: om din databas-URL innehåller procenttecken % kan du behöva ersätta dem med %% för att configparser inte ska misstolka dem (stackoverflow.com, stackoverflow.com.)

    Skapa appen manuellt: Om current_app inte är tillgänglig (t.ex. om man kör Alembic direkt utan Flask CLI), kan man importera och initiera applikationen inom env.py. Då anropar man create_app() själv, och pushar en app context manuellt. På så vis får Alembic samma konfiguration som din applikation. Du måste också importera dina modeller så att de registreras i metadata. Exempel på de relevanta delarna i ett env.py anpassat för application factory:

    from alembic import context
    from logging.config import fileConfig
    import logging

    # Konfiguration från alembic.ini
    config = context.config
    fileConfig(config.config_file_name)
    logger = logging.getLogger('alembic.env')

    # Importera appen och dess databas
    from app import create_app, db
    flask_app = create_app() # skapa applikationen
    flask_app.app_context().push() # pusha app context för att få current_app

    # Importera modelldefinitionerna så att de registreras i metadata
    import app.models

    # Sätt databaskoppling (URL) dynamiskt från appens config
    db_url = flask_app.config['SQLALCHEMY_DATABASE_URI']
    config.set_main_option('sqlalchemy.url', db_url)

    # Hämta SQLAlchemy-metadata som beskriver modellerna
    target_metadata = db.Model.metadata # alternativt db.metadata

    def run_migrations_offline():
    """Kör migrationer utan att koppla upp (offline-läge)."""
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
    url=url,
    target_metadata=target_metadata,
    literal_binds=True
    )
    with context.begin_transaction():
    context.run_migrations()

    def run_migrations_online():
    """Kör migrationer i online-läge, med databaskoppling."""
    connectable = db.engine
    with connectable.connect() as connection:
    context.configure(
    connection=connection,
    target_metadata=target_metadata,
    process_revision_directives=... # ev. utelämnat eller anpassat
    )
    with context.begin_transaction():
    context.run_migrations()

    # Avgör läge
    if context.is_offline_mode():
    run_migrations_offline()
    else:
    run_migrations_online()

    I koden ovan skapas appen via factory-funktionen och appens konfiguration (inklusive databas-URL) läses in i Alembic. Vi hämtar target_metadata från vår SQLAlchemy-instans (här antas att db = SQLAlchemy() i app/init.py, och att modellerna är definierade som subklasser av db.Model i app/models.py). Det är viktigt att importera modulpaketet app.models efter att app-context har skapats – detta säkerställer att alla modelldefinitioner faktiskt laddas och registreras. Om man missar att importera modellerna kan Alembic tro att det inte finns några ändringar, eftersom target_metadata då är tomt (innehåller inga tabeller) trots att de finns definierade i koden.

    Säkerställ att rätt databas-URL och modeller används

    För att verifiera att Alembic/Flask-Migrate verkligen använder korrekt databas och inkluderar modellerna kan man göra följande:

    • Kontrollera databas-URL: Kör en migrationskommando (t.ex. flask db migrate eller alembic revision --autogenerate) med debug/info-loggning på. I terminalens output bör du se att Alembic kopplar upp mot MySQL och inte t.ex. SQLite. Alembic loggar vilken ”Context impl” som används. För MySQL skulle det stå något i stil med ”Context impl MySQLImpl” (för SQLite står det SQLiteImplblog.miguelgrinberg.com). Om du ser MySQL nämnas vet du att den använder rätt driver/databas. Dessutom, om anslutningen misslyckas eller URL:en är felaktig, kommer Alembic att kasta ett fel direkt – då behöver du dubbelkolla SQLALCHEMY_DATABASE_URI i appen eller i alembic.ini.
    • Kontrollera att modellerna laddas: Efter att ha kört flask db migrate (autogenerering), öppna den genererade revisionsfilen under migrations/versions/. Där bör du se skapandet av tabeller och kolumner som matchar dina modellklasser. Om Alembic rapporterar ”No changes in schema detected.” trots att du har oaplicerade modeller, tyder det på att env.py inte lyckades ladda in modelldefinitionerna eller att den jämför mot fel databasblog.miguelgrinberg.com. Säkerställ då att du importerat rätt moduler och att target_metadata faktiskt refererar till all metadata (t.ex. via db.Model.metadata). I vårt exempel importerar vi app.models manuellt i env.py för att undvika detta problem.
    • Testa migrationerna: Kör flask db upgrade för att applicera migrationerna på databasen. Om allt är rätt konfigurerat ska dina tabeller nu skapas/uppdateras i MySQL utan fel. Du kan även köra flask db current för att se aktuell migrationsversion i databasen, vilket bekräftar att Alembic kan kommunicera med databasen.

    Rekommenderat arbetssätt med Flask-Migrate och Alembic

    • Initiera migrationsrepositoryt: För en ny app gör man normalt flask db init en gång (det verkar användaren redan ha gjort, vilket skapade mappen migrations/ i projektroten och en alembic.ini). Se till att FLASK_APP är korrekt satt till din factory (t.ex. export FLASK_APP="app:create_app" i Unix, eller motsvarande i Windows) innan du kör init, så att Flask vet hur appen ska skapas vid migrationskommandon.
    • Skapa migrations (autogenerera): När du har definierat eller ändrat dina modeller, kör flask db migrate -m "Beskrivning av ändring" för att låta Alembic jämföra target_metadata (dina modeller) med databasen och generera en ny migrationsfil. Tack vare konfigurationen ovan kommer Alembic att använda appens MySQL-URL och inkludera alla modeller i jämförelsen. (Observera att första gången i ett projekt med befintlig databas kan Alembic tro att inget behöver göras om databasen redan har dessa tabeller. I så fall kan man behöva använda flask db stamp head för att markera databasen som uppdaterad, eller köra migrationskommandot mot en tom databaskopiablog.miguelgrinberg.comblog.miguelgrinberg.com.)
    • Applicera migrationer: Använd flask db upgrade för att köra migrationerna och uppdatera databasschemat till senaste version. Detta kommando kommer under huven att anropa Alembic och köra env.py med online-läget. Återigen används create_app-funktionen i vår konfiguration för att koppla upp mot rätt databas.
    • Använd Flask-Migrate i utvecklingsflödet: I och med att du har integrerat Alembic med Flask via Flask-Migrate, bör du fortsättningsvis använda flask db ...-kommandona (snarare än att köra alembic direkt) för att hantera migrationerna. Flask-Migrate sköter kopplingen till appen och kontexten åt dig. Som påpekats av utvecklare är Flask-Migrate enklare att använda i Flask-projekt eftersom det automatiserar mycket av konfigurationenstackoverflow.com. Se till att extensions initieras korrekt i create_app (d.v.s. db.init_app(app) och Migrate(app, db) om du inte redan gjort det).
  • Skapa Databasmigreringar med Alembic i Python

    Skapa Databasmigreringar med Alembic i Python

    Jag går en kurs i Python, programmeringsspråket. En av de sista uppgifterna är att skapa en hemsida, egentligen en portfolio med program jag skapat och länkar till Github med flera ställen där jag har något jag vill visa upp. I kursen använde vi SQLite som databas men eftersom jag använd MySql mycket i mina andra projekt så ville jag göra det här med. Plus att det blev en liten utmaning att göra om databaskopplingar.

    För att på ett enkelt sätt kunna göra databasmigreringar när jag uppgraderar mitt program hittade jag Alembic som fungerar bra för det. Sökvägarna behöver rättas utifrån varje projekt, förstås men gången är denna:


    1. Installera Alembic

    Om du inte redan har det:

    pip install alembic

    2. Initiera Alembic

    I roten av ditt projekt (där din app/-mapp och run.py eller liknande ligger):

    alembic init migrations

    Det skapar en migrations/-mapp och en alembic.ini-fil.


    3. Konfigurera alembic.ini

    Öppna alembic.ini och ändra denna rad:

    sqlalchemy.url = driver://user:pass@localhost/dbname

    Byt ut den mot din databas-url, t.ex.:

    sqlalchemy.url = mysql+pymysql://root:password@localhost/portfolio-db

    Eller om du använder en .env-fil – då ändrar vi detta i steg 5 istället via Python.


    4. Peka Alembic till din SQLAlchemy-modell

    Öppna migrations/env.py och leta upp detta block:

    from logging.config import fileConfig
    from sqlalchemy import engine_from_config, pool
    from alembic import context

    Lägg till din models.py-import (efter importerna ovan):

    import sys
    import os
    sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
    from app.models import db # Lägg till detta

    Byt ut denna rad:

    target_metadata = None

    mot:

    target_metadata = db.metadata

    5. (Valfritt) Använd din DATABASE_URL från .env

    Om du vill använda os.getenv("DATABASE_URL"):

    Byt ut i migrations/env.py (under config = context.config):

    from dotenv import load_dotenv
    load_dotenv()
    from sqlalchemy.engine.url import URL
    config.set_main_option("sqlalchemy.url", os.getenv("DATABASE_URL"))

    6. Skapa en migrering

    När du ändrar en modell (t.ex. la till description i PortfolioItem), kör:

    alembic revision --autogenerate -m "Add description to portfolio item"

    Det skapar en versionsfil i migrations/versions/.


    7. Kör migreringen

    alembic upgrade head

    Nu har kolumnen description skapats i databasen utan att radera något!


    alembic.ini

    Byt ut din befintliga alembic.ini med denna:

    [alembic]
    script_location = migrations
    sqlalchemy.url = mysql+pymysql://root:password@localhost/portfolio-db

    [loggers]
    keys = root,sqlalchemy,alembic

    [handlers]
    keys = console

    [formatters]
    keys = generic

    [logger_root]
    level = WARN
    handlers = console

    [logger_sqlalchemy]
    level = WARN
    handlers =
    qualname = sqlalchemy.engine

    [logger_alembic]
    level = INFO
    handlers =
    qualname = alembic

    [handler_console]
    class = StreamHandler
    args = (sys.stdout,)
    level = NOTSET
    formatter = generic

    [formatter_generic]
    format = %(levelname)-5.5s [%(name)s] %(message)s

    Byt root:password om du har en annan användare eller databas.


    migrations/env.py

    Byt ut hela innehållet i migrations/env.py med detta:

    from __future__ import with_statement

    import sys
    import os
    from logging.config import fileConfig
    from sqlalchemy import engine_from_config, pool
    from alembic import context

    # Lägg till appens rot till sys.path
    sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))

    # Importera extensions och modeller
    from app.extensions import db
    from app.models import *

    # Load environment variables
    from dotenv import load_dotenv
    load_dotenv()

    # Alembic Config
    config = context.config

    # Sätt databas-URL från .env
    config.set_main_option('sqlalchemy.url', os.getenv("DATABASE_URL"))

    # Loggkonfiguration
    fileConfig(config.config_file_name)

    # Metadata från modellerna
    target_metadata = db.metadata

    def run_migrations_offline():
    """Kör migreringar utan en DB-anslutning."""
    url = config.get_main_option("sqlalchemy.url")
    context.configure(
    url=url,
    target_metadata=target_metadata,
    literal_binds=True,
    dialect_opts={"paramstyle": "named"},
    )

    with context.begin_transaction():
    context.run_migrations()

    def run_migrations_online():
    """Kör migreringar med en DB-anslutning."""
    connectable = engine_from_config(
    config.get_section(config.config_ini_section),
    prefix="sqlalchemy.",
    poolclass=pool.NullPool,
    )

    with connectable.connect() as connection:
    context.configure(
    connection=connection,
    target_metadata=target_metadata
    )

    with context.begin_transaction():
    context.run_migrations()

    if context.is_offline_mode():
    run_migrations_offline()
    else:
    run_migrations_online()

    Klar att köra:

    Nu kan du köra:

    alembic revision --autogenerate -m "Add description field"
    alembic upgrade head