article

Thursday, April 11, 2024

Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI

Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI

https://python-guide-es.readthedocs.io/es/guide-es/dev/virtualenvs.html

Create an environment
ednalan@Cairocoders myapp % pip install virtualenv
ednalan@Cairocoders myapp % pip install virtualenv

Activate the environment
ednalan@Cairocoders myapp % source venv/bin/activate
(venv) ednalan@Cairocoders myapp %

Install Flask
https://pypi.org/project/Flask/
(venv) ednalan@Cairocoders myapp % pip install -U Flask
(venv) ednalan@Cairocoders myapp % flask run

Install requirements
pip install -U flask-cors
https://pypi.org/project/Flask-Cors/

Flask-SQLAlchemy
Flask-SQLAlchemy is an extension for Flask that adds support for SQLAlchemy to your application.
https://flask-sqlalchemy.palletsprojects.com/en/3.0.x/

(venv) PS C:\flask_dev\myapp>pip install -U Flask-SQLAlchemy

python3 -m pip install
https://pypi.org/project/pymysql/
app.py
//app.py
from flask import Flask, request, jsonify
from flask_cors import CORS, cross_origin #ModuleNotFoundError: No module named 'flask_cors' = pip install Flask-Cors
   
from models import db, Products

app = Flask(__name__)
   
app.config['SECRET_KEY'] = 'cairocoders-ednalan'
#app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///flaskdb.db'
# Databse configuration mysql                             Username:password@hostname/databasename
app.config['SQLALCHEMY_DATABASE_URI'] = 'mysql+pymysql://root:root@localhost:8889/nextjsdb'
   
SQLALCHEMY_TRACK_MODIFICATIONS = False
SQLALCHEMY_ECHO = True
   
CORS(app, supports_credentials=True)
   
db.init_app(app)
      
with app.app_context():
    db.create_all()
   
@app.route("/")
def hello_world():
    return "Hello, World!"
   
@app.route('/products/<int:page>/<int:per_page>', methods=['GET']) #http://127.0.0.1:5000/products/1/4
def products(page=1, per_page=3):
    
    nextpage = page + 1
    prevpage = page - 1
         
    total = Products.query.count()
     
    productdata = Products.query.order_by(Products.id.asc())  
    products = productdata.paginate(page=page, per_page=per_page)
     
    #print(products.next_num)
    #print(products.prev_num)
     
    nextnumber = products.next_num
    if nextnumber == None:
        next_page_url = ""
    else:
        next_page_url = f"http://127.0.0.1:5000/products/{nextpage}/{per_page}"
        
    prev_number = products.prev_num
    if prev_number == None:
        prev_page = ""
    else:
        prev_page = f"http://127.0.0.1:5000/products/{prevpage}/{per_page}"
         
    return jsonify({
        'total': total,
        'next_page_url': next_page_url,
        'prev_page_url': prev_page,
        'results': [{
            'id': rs.id,
            'name': rs.name,
            'image': rs.image,
            'price': rs.price
        } for rs in products.items]
    })
   
if __name__ == "__main__":
    app.run(debug=True)
models.py
//models.py
from flask_sqlalchemy import SQLAlchemy
       
db = SQLAlchemy()
       
class Products(db.Model):
    __tablename__ = "products"
    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(150), index=True)
    image = db.Column(db.String(150), index=True)
    price = db.Column(db.Integer,default=0)
run (venv) C:\flask_dev\myapp>flask run

Next.js
Install requirements
npm install axios
https://www.npmjs.com/package/axios

app\page.tsx
//app\page.tsx
import Link from "next/link";
import TableData from "@/components/tabledata";
import { Suspense } from "react";
import { Spinner } from "@/components/spinner";
 
export default function Home() {
  return (
    <div className="w-screen py-20 flex justify-center flex-col items-center bg-gray-300">
      <div className="flex items-center justify-between gap-1 mb-5">
        <h1 className="text-4xl font-bold">Next.js 14 Python Flask Mysql Pagination Next Prev | TailwindCSS DaisyUI</h1>
      </div>    
      <Suspense fallback={<Spinner />}>
        <TableData/>
      </Suspense>
    </div>
  );
}
components\tabledata.tsx
//components\tabledata.tsx
"use client";

import React, { useEffect, useState } from "react";
import axios from 'axios' //npm install axios https://www.npmjs.com/package/axios
import Image from 'next/image' 

export default function Users() {
    const [products, setProducts] = useState([]);
    const [info, setInfo] = useState({});

    const url = "http://127.0.0.1:5000/products/1/3";

    useEffect(() => {
        fetchProducts(url);
    }, []);

    const fetchProducts = (url) => {
        axios
        .get(url)
        .then((data) => {
            setProducts(data.data.results);
            //console.log(data.data.results);
            setInfo(data.data);
            //console.log(data.data);
        })
        .catch((error) => {
            console.log(error);
        });
    };

    const handleNextPage = () => {
        fetchProducts(info.next_page_url);
        window.scrollTo(0, 0);
    };
    
    const handlePreviousPage = () => {
        fetchProducts(info.prev_page_url);
        window.scrollTo(0, 0);
    };

    return (
            <div className="py-16">
            <div className="container mx-auto px-4">
                <h2 className="text-3xl font-bold text-white mb-8">Introducing Our Latest Product</h2>
                <div className="grid grid-cols-1 md:grid-cols-3 gap-8">
                
                {products.map((item, index) => (
                <div key={index} className="bg-white rounded-lg shadow-lg p-8">
                    <div className="relative overflow-hidden">
                        <Image
                        src={`http://127.0.0.1:5000/static/images/${item.image}`}
                        width={400}
                        height={400}
                        alt="Photo"
                        />
                    <div className="absolute inset-0 bg-black opacity-40" />
                    <div className="absolute inset-0 flex items-center justify-center">
                        <button className="bg-white text-gray-900 py-2 px-6 rounded-full font-bold hover:bg-gray-300">View Product</button>
                    </div>
                    </div>
                    <h3 className="text-xl font-bold text-gray-900 mt-4">{item.name}</h3>
                    <p className="text-gray-500 text-sm mt-2">Description: {item.name}</p>
                    <div className="flex items-center justify-between mt-4">
                    <span className="text-gray-900 font-bold text-lg">${item.price}.99</span>
                    <button className="bg-gray-900 text-white py-2 px-4 rounded-full font-bold hover:bg-gray-800">Add to Cart</button>
                    </div>
                </div>
                ))}

                </div>
                <div className="w-1/2 items-center px-4 mt-6">   
                    <div className="join grid grid-cols-2">
                        {info.prev_page_url ? (
                            <button className="join-item btn btn-primary btn-outline" onClick={handlePreviousPage}>
                            Previous
                            </button>
                        ) : null}
                        {info.next_page_url ? (
                            <button className="join-item btn btn-primary btn-outline" onClick={handleNextPage}>
                            Next
                            </button>
                        ) : null}
                    </div>
                </div> 
            </div>
            </div>
  );
}
components\spinner.tsx
//components\spinner.tsx
export const Spinner = () => {
  return (
    <span className="loading loading-spinner loading-lg"></span>
  );
};
run C:\nextjs>npm run dev
https://github.com/cairocodes/Next.js-14-Python-Flask-Mysql-Pagination-Next-Prev-TailwindCSS-DaisyUI

Related Post