您当前的位置:首页 > 电脑百科 > 程序开发 > 编程百科

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

时间:2022-07-12 14:22:23  来源:  作者:qaseven

在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastify 构建一个 Full-stack 应用程序。

在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastify 构建一个 Full-stack 应用程序。我们将建立一个考勤管理演示应用程序,管理员工的考勤。这个应用程序的流程很简单: 管理用户登录,创建当天的出勤表,然后每个员工在出勤表上进出。

什么是 Next.js?

Next.Js 是一个灵活的 React 框架,它为您提供了创建快速 Web 应用程序的构建块。它通常被称为全栈 React 框架,因为它可以让前端和后端应用程序在相同的代码基上使用无服务器函数来实现这一点。

什么是 Prisma?

Prisma 是一个开源的、 Node.js 和 Typecript ORM,它极大地简化了 SQL 数据库的数据建模、迁移和数据访问。在撰写本文时,Prisma 支持以下数据库管理系统: PostgreSQL、 MySQL、 MariaDB、 SQLite、 AWS Aurora、 Microsoft SQL Server、 Azure SQL 和 MongoDB。您可能还希望单击此处查看所有受支持的数据库管理系统的列表。

什么是 Postgres?

Postgres 也被称为 PostgreSQL,它是一个免费的开源关联式资料库管理系统。它是 SQL 语言的超集,具有许多特性,使开发人员能够安全地存储和扩展复杂的数据工作负载。

先决条件

本教程是一个实践演示教程。因此,最好在你的电脑上安装以下软件:

  • 安装在你的机器上
  • 数据库服务器正在运行

这个教程的代码可以在 Github 上找到,所以你可以克隆它,然后跟着学习。

https://github.com/Claradev32/attendance

项目设置

让我们从设置 Next.js 应用程序开始。

Shell

npx create-next-App@latest

 

等待安装完成,然后运行下面的命令来安装我们的依赖项。

Shell

yarn add fastify fastify-nextjs iron-session @prisma/clientbryarn add prisma nodemon --dev

 

等待安装完成。

设置 Next.js 和 Fastify

 

默认情况下,Next.js 不使用 Fastify 作为其服务器。要使用 Fastify 为我们的 Next.js 应用程序提供服务,请编辑 package.json 文件中的脚本字段,其代码片段如下所示。

JSON

scripts": {
	"dev": "nodemon server.js",
	"build": "next build",
	"start": "next start",
	"lint": "next lint"
}

 

创建我们的 Fastify 服务器

现在让我们创建一个 server.js 文件。这个文件是我们的应用程序的入口点,然后我们添加了一个需求(‘ fast tify-nextjs’)来包含一个插件,这个插件在 Fastify 公开了 Next.js API 来处理渲染。

打开 server.js 文件,并添加以下代码段:

const fastify = require('fastify')()
async function noOpParser(req, payload) {
return payload;
}
fastify.register(require('fastify-nextjs')).after(() => {
fastify.addContentTypeParser('text/plAIn', noOpParser);
fastify.addContentTypeParser('application/json', noOpParser);
fastify.next('/*')
fastify.next('/api/*', { method: 'ALL' });
})
fastify.listen(3000, err => {
if (err) throw err
console.log('Server listening on <http://localhost:3000>')
})

在上面的代码片段中,我们使用了 fast-nextjs 插件,它在 Fastify 公开了处理呈现的 Next.js API。然后,我们使用 noopParser 函数解析传入的请求,这使得请求体可用于我们的 Next.js API 路由处理程序,我们使用[ fasttify.next ](< http://fastify.next > 命令)为我们的应用定义两个路由。然后我们创建 Fastify 服务器,让它监听端口3000。

现在继续并使用纱线 dev 命令运行应用程序: 应用程序将在 localhost: 3000上运行。

Prisma 设置

首先,运行以下命令来获得一个基本的 Prisma 设置:

Shell

npx prisma init

 

上面的命令将创建一个包含 schema.Prisma 文件的 Prisma 目录。这是您的主 Prisma 配置文件,它将包含您的数据库模式。还有。Env 文件将被添加到项目的根目录中。打开。Env 文件,并用 PostgreSQL 数据库的连接 URL 替换虚拟连接 URL。

将 prisma/schema.prisma 文件中的代码替换为以下内容:

Properties files 属性文件

datasource db {
	url = env("DATABASE_URL")
	provider="postgresql"
}
generator client {
	provider = "prisma-client-js"
}
model User {
	id        Int      @id @default(autoincrement())
	createdAt DateTime @default(now())
	email     String   @unique
	name      String
	password  String
	role      Role     @default(EMPLOYEE)
	attendance     Attendance[]
	AttendanceSheet AttendanceSheet[]
}
model AttendanceSheet {
	id        Int      @id @default(autoincrement())
	createdAt DateTime @default(now())
	updatedAt DateTime @updatedAt
	createdBy    User?    @relation(fields: [userId], references: [id])
	userId  Int?
}
model Attendance {
	id        Int      @id @default(autoincrement())
	createdAt DateTime @default(now())
	updatedAt DateTime @updatedAt
	signIn    Boolean @default(true)
	signOut   Boolean
	signInTime    DateTime @default(now())
	signOutTime   DateTime
	user    User?    @relation(fields: [userId], references: [id])
	userId  Int?
}
enum Role {
	EMPLOYEE
	ADMIN
}

 

在上面的代码片段中,我们创建了 User、 AttendanceSheet 和 Attendance Model,定义了每个模型之间的关系。

接下来,在数据库中创建这些表:

Shell

npx prisma db push

 

在运行上面的命令之后,您应该可以在终端中看到如下截图所示的输出:

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

创建实用程序函数

完成 Prisma 设置后,让我们创建三个实用函数,它们将在我们的应用程序中不时使用。

打开 lib/parseBody.js 文件并添加以下代码片段:

JAVAScript

export const parseBody = (body) => {
	if (typeof body === "string") return JSON.parse(body)
	return body
}

 

打开 lib/request.js 文件并添加以下代码片段。

JavaScript

export const sessionCookie = () => {
	return ({
		cookieName: "auth",
		password: process.env.SESSION_PASSWORD,
		// secure: true should be used in production (HTTPS) but can't be used in development (HTTP)
		cookieOptions: {
			secure: process.env.NODE_ENV === "production",
		},
	})
}

 

打开/lib/request.js 文件并添加以下代码片段。此函数返回铁会话铁会话的会话属性对象。

JavaScript

export const sessionCookie = () => {
	return ({
		cookieName: "auth",
		password: process.env.SESSION_PASSWORD,
		// secure: true should be used in production (HTTPS) but can't be used in development (HTTP)
		cookieOptions: {
			secure: process.env.NODE_ENV === "production",
		},
	})
}

 

接下来,将 SESSION_PASSWORD 添加到. env 文件: 它应该是一个至少有32个字符的字符串。

应用程序的样式

完成我们的实用程序功能后,让我们给应用程序添加一些样式。我们正在为这个应用程序使用 css 模块,所以打开 style/Home.modules.CSS 文件并添加以下代码片段:

CSS

.container {
	padding: 0 2rem;
}
.man {
	min-height: 100vh;
	padding: 4rem 0;
	flex: 1;
	display: flex;
	flex-direction: column;
	justify-content: center;
	align-items: center;
}
.login {
	width: 450px;
}
.login input {
	width: 100%;
	height: 50px;
	margin: 4px;
}
.login button {
	width: 100%;
	height: 50px;
	margin: 4px;
}
.dashboard {
	display: grid;
	grid-template-columns: 3fr 9fr;
	grid-template-rows: 1fr;
	grid-column-gap: 0px;
	grid-row-gap: 0px;
	height: calc(100vh - 60px);
}
.navbar {
	height: 60px;
	background-color: black;
}

 

创建侧边栏组件

 

设计完成后,让我们创建侧边栏组件来帮助我们在应用程序仪表板上导航到不同的页面。打开 Component/SideBar.js 文件,并粘贴下面的代码片段。

JavaScript

import Link from 'next/link'
import { useRouter } from 'next/router'
import styles from '../styles/SideBar.module.css'

const SideBar = () => {

    const router = useRouter()

    const logout = async () => {

        try {

            const response = await fetch('/api/logout', {
                method: 'GET', 
                credentials: 'same-origin', 
            });

            if(response.status === 200)  router.push('/')

        } catch (e) {
            alert(e)
        }
  
    }
      

    return (
        <nav className={styles.sidebar}>

            <ul>

                <li> <Link href="/dashboard"> Dashboard</Link> </li>

                <li> <Link href="/dashboard/attendance"> Attendance </Link> </li>

                <li> <Link href="/dashboard/attendance-sheet"> Attendance Sheet </Link> </li>

                <li onClick={logout}> Logout </li>

            </ul>

        </nav>
    )

}

export default SideBar

登入网页

现在打开 page/index.js 文件,删除其中的所有代码,并添加以下代码段。下面的代码通过表单向 localhost: 3000/api/login 路由发送包含电子邮件和密码的发送请求。一旦验证了凭据,它就调用 router.push (’/dashboard’)方法将用户重定向到 localhost: 3000/api/dashboard:

JavaScript

import Head from 'next/head'
import { postData } from '../lib/request';
import styles from '../styles/Home.module.css'
import { useState } from 'react';
import { useRouter } from 'next/router'

export default function Home({posts}) {

  const [data, setData] = useState({email: null, password: null});

  const router = useRouter()

  const submit = (e) => {
    e.preventDefault()

    if(data.email && data.password) {
      postData('/api/login', data).then(data => {
        console.log(data); 

        if (data.status === "success") router.push('/dashboard')
      
      });
    }

  }

  return (
    <div className={styles.container}>
      <Head>
        <title>Login</title>
        <meta name="description" content="Login" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>

        <form  className={styles.login}>

          <input 
            type={"text"} 
            placeholder="Enter Your Email" 
            onChange={(e) => setData({...data, email: e.target.value})} />

          <input 
            type={"password"}  
            placeholder="Enter Your Password"
            onChange={(e) => setData({...data, password: e.target.value})} />

          <button onClick={submit}>Login</button>

        </form>
        
      </main>

    </div>
  )
}

 

设置登录 API 路由

现在打开页面/api/login.js 文件并添加以下代码片段。我们将使用 Prismaclient 进行数据库查询,IronSessionApiRoute 是用于处理 RESTful 应用程序中的用户会话的铁会话函数。

此路由处理对 localhost: 3000/api/login 的登录 POST 请求,并在用户通过身份验证后生成身份验证 Cookie。

JavaScript

import { PrismaClient } from '@prisma/client'
import { withIronSessionApiRoute } from "iron-session/next";
import { parseBody } from '../../lib/parseBody';
import { sessionCookie } from '../../lib/session';

export default withIronSessionApiRoute(
    async function loginRoute(req, res) {

      const { email, password } = parseBody(req.body)

      const prisma = new PrismaClient()

      // By unique identifier
      const user = await prisma.user.findUnique({
        where: {
        email
      },})

      if(user.password === password) {

        // get user from database then:
        user.password = undefined
        req.session.user = user
        await req.session.save();

        return res.send({ status: 'success', data: user });

      };

    res.send({ status: 'error', message: "incorrect email or password" });

  },
  sessionCookie(),
);

设置注销 API 路由

打开/page/api/logout 文件并添加下面的代码段。此路由处理对 localhost 的 GET 请求: 3000/api/logout,该请求通过销毁会话 cookie 将用户注销。

JavaScript

import { withIronSessionApiRoute } from "iron-session/next";
import { sessionCookie } from "../../lib/session";

export default withIronSessionApiRoute(
  function logoutRoute(req, res, session) {
    req.session.destroy();
    res.send({ status: "success" });
  },
  sessionCookie()
);

创建仪表板页

此页面为用户提供了登录和退出考勤表的界面。管理员还可以创建考勤表。打开 page/dashboard/index.js 文件并添加下面的代码片段。

JavaScript

import { withIronSessionSsr } from "iron-session/next";
import Head from 'next/head'
import { useState, useCallback } from "react";
import { PrismaClient } from '@prisma/client'
import SideBar from '../../components/SideBar'
import styles from '../../styles/Home.module.css'
import dashboard from '../../styles/Dashboard.module.css'
import { sessionCookie } from "../../lib/session";
import { postData } from "../../lib/request";

export default function Page(props) {

  const [attendanceSheet, setState] = useState(JSON.parse(props.attendanceSheet));

  const sign = useCallback((action="") => {

    const body = {
      attendanceSheetId: attendanceSheet[0]?.id,
      action
    }

    postData("/api/sign-attendance", body).then(data => {

      if (data.status === "success") {

        setState(prevState => {

          const newState = [...prevState]

          newState[0].attendance[0] = data.data

          return newState

        })
     
      }

    })

  }, [attendanceSheet])

  const createAttendance = useCallback(() => {

    postData("/api/create-attendance").then(data => {

      if (data.status === "success") {
        alert("New Attendance Sheet Created")
        setState([{...data.data, attendance:[]}])
      }

    })

  }, [])

  return (
    <div>

      <Head>
        <title>Attendance Management Dashboard</title>
        <meta name="description" content="dashboard" />
      </Head>

      <div className={styles.navbar}></div>

      <main className={styles.dashboard}>

        <SideBar />

        <div className={dashboard.users}>

          {
            props.isAdmin && <button className={dashboard.create} onClick={createAttendance}>Create Attendance Sheet</button>
          }
            
          { attendanceSheet.length > 0 &&

            <table className={dashboard.table}>
              <thead>
                <tr> 
                  <th>Id</th> <th>Created At</th> <th>Sign In</th> <th>Sign Out</th> 
                </tr>
              </thead>

              <tbody>
                <tr>
                  <td>{attendanceSheet[0]?.id}</td>
                  <td>{attendanceSheet[0]?.createdAt}</td>

                  {
                    attendanceSheet[0]?.attendance.length != 0 ? 
                      <>
                        <td>{attendanceSheet[0]?.attendance[0]?.signInTime}</td>
                        <td>{
                          attendanceSheet[0]?.attendance[0]?.signOut ? 
                          attendanceSheet[0]?.attendance[0]?.signOutTime: <button onClick={() => sign("sign-out")}> Sign Out </button> }</td>
                      </>
                      :
                      <>
                        <td> <button onClick={() => sign()}> Sign In </button> </td>
                        <td>{""}</td>
                      </>
                  }
                </tr>
              </tbody>

            </table>

          }
          
        </div>

      </main>

    </div>
  )
}

 

我们使用 getServerSideProps 来生成页面数据,而 IronSessionSsr 是用于处理服务器端呈现页面的 Iron-session 函数。在下面的代码片段中,我们使用考勤表中的一行查询考勤表的最后一行,其中 userId 等于存储在用户会话上的 User id。我们还检查用户是否是 ADMIN。

JavaScript

export const getServerSideProps = withIronSessionSsr( async ({req}) => {

  const user = req.session.user

  const prisma = new PrismaClient()

  const attendanceSheet = await prisma.attendanceSheet.findMany({  
    take: 1,
    orderBy: {
      id: 'desc',
    },
    include: { 
      attendance: {
        where: {
          userId: user.id
        },
      }
    }
  })

  return {
    props: {
      attendanceSheet: JSON.stringify(attendanceSheet),
      isAdmin: user.role === "ADMIN"
    }
  }

}, sessionCookie())

设置创建出勤 API 路由

打开页面/api/create-around. js 文件并添加下面的代码片段。

JavaScript

import { PrismaClient } from '@prisma/client'
import { withIronSessionApiRoute } from "iron-session/next";
import { sessionCookie } from '../../lib/session';

  
export default withIronSessionApiRoute( async function handler(req, res) {

    const prisma = new PrismaClient()

    const user = req.session.user

    const attendanceShe

设置签到 API 路由

此路由处理我们对 localhost 的 API POST 请求:
3000/API/sign-publications。该路由接受 POST 请求,而 attanceSheetId 和 action 用于登录和退出 attancesheet。

打开/page/api/sign-around. js 文件并添加下面的代码片段。

JavaScript

import { PrismaClient } from '@prisma/client'
import { withIronSessionApiRoute } from "iron-session/next";
import { parseBody } from '../../lib/parseBody';
import { sessionCookie } from '../../lib/session';

  
export default withIronSessionApiRoute( async function handler(req, res) {

    const prisma = new PrismaClient()

    const {attendanceSheetId, action} = parseBody(req.body)

    const user = req.session.user

    const attendance = await prisma.attendance.findMany({
        where: {
            userId: user.id,
            attendanceSheetId: attendanceSheetId
        }
    })

    //check if atendance have been created
    if (attendance.length === 0) {
        const attendance = await prisma.attendance.create({
            data: {
                userId: user.id,
                attendanceSheetId: attendanceSheetId,
                signIn: true,
                signOut: false,
                signOutTime: new Date()
            },
        })   

        return res.json({status: "success", data: attendance});

    } else if (action === "sign-out") {
        await prisma.attendance.updateMany({
            where: {
                userId: user.id,
                attendanceSheetId: attendanceSheetId
            },
            data: {
              signOut: true,
              signOutTime: new Date()
            },
        })

        return res.json({status: "success", data: { ...attendance[0], signOut: true, signOutTime: new Date()}});
    }

    res.json({status: "success", data: attendance});
    
}, sessionCookie())

创建出勤页面

此服务器端呈现的页面显示了登录用户的所有出勤表。打开
/page/dashboard/attance.js 文件并添加下面的代码片段。

JavaScript

import { withIronSessionSsr } from "iron-session/next";
import Head from 'next/head'
import { PrismaClient } from '@prisma/client'
import SideBar from '../../components/SideBar'
import styles from '../../styles/Home.module.css'
import dashboard from '../../styles/Dashboard.module.css'
import { sessionCookie } from "../../lib/session";

export default function Page(props) {

  const data = JSON.parse(props.attendanceSheet)

  return (
    <div>

      <Head>
        <title>Attendance Management Dashboard</title>
        <meta name="description" content="dashboard" />
      </Head>

      <div className={styles.navbar}></div>

      <main className={styles.dashboard}>

        <SideBar />

        <div className={dashboard.users}>

        <table className={dashboard.table}>

          <thead>

            <tr> 
              <th> Attendance Id</th> <th>Date</th> 
              <th>Sign In Time</th> <th>Sign Out Time</th> 
            </tr> 

          </thead>

            <tbody>

              {
                data.map(data =>   {

                  const {id, createdAt, attendance } = data

  
                  return (
                    <tr key={id}> 

                      <td>{id}</td> <td>{createdAt}</td>  

                      { attendance.length === 0 ? 
                      
                        (
                          <>
                            <td>You did not Sign In</td>
                            <td>You did not Sign Out</td>
                          </>
                        )
                        :
                        (
                          <>
                            <td>{attendance[0]?.signInTime}</td>
                            <td>{attendance[0]?.signOut ? attendance[0]?.signOutTime : "You did not Sign Out"}</td>
                          </>
                        )
                        
                      }
              
                    </tr>
                  )

                })

              }  

            </tbody>

          </table>

        </div>

      </main>

    </div>
  )
}
In the code snippet below, we query for all the rows from the attendanceSheet table and also fetch the attendance where the userId is equal to the user id stored in the user session.

export const getServerSideProps = withIronSessionSsr( async ({req}) => {

  const user = req.session.user

  const prisma = new PrismaClient()
  
  const attendanceSheet = await prisma.attendanceSheet.findMany({
    orderBy: {
      id: 'desc',
    },
    include: { 
      attendance: {
        where: {
          userId: user.id
        },
      }
    }
  })

  return {
    props: {
      attendanceSheet: JSON.stringify(attendanceSheet),
    }
  }

}, sessionCookie())

创建出勤单页

这个服务器端呈现的页面显示了所有的考勤表以及在该考勤表上签名的员工。打开
/page/dashboard/attance.js 文件并添加下面的代码片段。

JavaScript

import { withIronSessionSsr } from "iron-session/next";
import Head from 'next/head'
import { PrismaClient } from '@prisma/client'
import SideBar from '../../components/SideBar'
import styles from '../../styles/Home.module.css'
import dashboard from '../../styles/Dashboard.module.css'
import { sessionCookie } from "../../lib/session";

export default function Page(props) {

  const data = JSON.parse(props.attendanceSheet)

  return (
    <div>

      <Head>
        <title>Attendance Management Dashboard</title>
        <meta name="description" content="dashboard" />
      </Head>

      <div className={styles.navbar}></div>

      <main className={styles.dashboard}>

        <SideBar />

        <div className={dashboard.users}>

        {
          data?.map(data => {

            const {id, createdAt, attendance } = data

            return (
              <>

                <table key={data.id} className={dashboard.table}>

                  <thead>
                    
                    <tr> 
                      <th> Attendance Id</th> <th>Date</th> 
                      <th> Name </th> <th> Email </th> <th> Role </th>
                      <th>Sign In Time</th> <th>Sign Out Time</th> 
                    </tr> 

                  </thead>

                  <tbody>

                    {
                      (attendance.length === 0)  &&
                      (
                        <>
                        <tr><td> {id} </td> <td>{createdAt}</td> <td colSpan={5}> No User signed this sheet</td></tr>
                        </>
                      )
                    }

                    {
                      attendance.map(data => {

                        const {name, email, role} = data.user

                      
                        return (
                          <tr key={id}> 

                            <td>{id}</td> <td>{createdAt}</td>  

                            <td>{name}</td> <td>{email}</td>

                            <td>{role}</td>

                            <td>{data.signInTime}</td>

                            <td>{data.signOut ? attendance[0]?.signOutTime: "User did not Sign Out"}</td>  
                    
                          </tr>
                        )

                      })

                    }  

                  </tbody>
                  
                </table>
              </>
            )
          })
          
          }

        </div>

      </main>

    </div>
  )
}

 

在下面的代码片段中,我们将查询 attancesheet 表中的所有行,并通过选择姓名、电子邮件和角色来获取出席率。

JavaScript

export const getServerSideProps = withIronSessionSsr(async () => {

  const prisma = new PrismaClient()

  const attendanceSheet = await prisma.attendanceSheet.findMany({
    orderBy: {
      id: 'desc',
    },
    include: { 
      attendance: {
        include: { 
          user: {
            select: {
              name: true, 
              email: true, 
              role: true
            }
          }
        }
      },
    },

  })

  return {
    props: {
      attendanceSheet: JSON.stringify(attendanceSheet),
    }
  }

}, sessionCookie())

测试应用程序

首先,我们必须将用户添加到数据库中。我们要用Prisma做这个。要启动 Prisma ,请运行以下命令:

Shell

npx prisma studio

 

Prisma 索引页面如下:

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

要创建一个具有 ADMIN 角色的数据库用户和多个具有 EMPLOYEE 角色的用户,请访问以下页面:

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

单击 Add record,然后填写所需的字段: password、 name、 email 和 role。完成后,单击绿色的 Save 1 change 按钮。注意,为了简单起见,我们没有散列密码。

 

用yarn dev启动服务器。这将启动服务器并在[ localhost: 3000](< http://localhost:3000)上运行应用程序,登录页面如下所示。

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

使用具有 ADMIN 角色的用户登录,因为只有管理用户可以创建考勤表。一旦登录成功,应用程序将重定向到您的仪表板。

单击 CreateAtnatureShet 按钮创建考勤表,然后等待请求完成,考勤表将出现。用户仪表板如下所示。

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

出勤表如下所示,单击“登录”按钮即可登录。登录成功后,将显示登录时间,并且可以看到 Sign Out 按钮。单击“登出”按钮登出,并与不同的用户多次重复此过程。

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

接下来点击侧边栏中的出席链接,查看用户的出席情况。结果应与下列结果相符:

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

接下来点击侧边栏上的出勤表链接,查看所有用户的出勤情况。结果如下:

如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序

 

结论

在本文中,您学习了如何在 Next.js 中使用自定义 Fastify 服务器。您还了解了 Prisma 和 Prisma 工作室。我已经向您介绍了如何将 Prisma 连接到 Postgres 数据库,以及如何使用 Prisma 客户端和 Prisma studio创建、读取和更新数据库。

您还学习了如何使用铁会话对用户进行身份验证。在本教程中,我们构建了一个完整的应用程序,它使用 Next.js、 Prisma、 Postgres 和 Fastify 管理员工出勤率。请继续收听,下次再见。



Tags:全栈   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,不构成投资建议。投资者据此操作,风险自担。如有任何标注错误或版权侵犯请与我们联系,我们将及时更正、删除。
▌相关推荐
花 15 分钟把 Express.js 搞明白,全栈没有那么难
Express 是老牌的 Node.js 框架,以简单和轻量著称,几行代码就可以启动一个 HTTP 服务器。市面上主流的 Node.js 框架,如 Egg.js、Nest.js 等都与 Express 息息相关。Express 框...【详细内容】
2024-01-16  Search: 全栈  点击:(91)  评论:(0)  加入收藏
从零开始学Reflex框架:打造自己的全栈应用!
Python作为一门广泛应用于Web开发的编程语言,拥有众多优秀的框架。其中,Reflex作为一个全栈框架,提供了一种简单而强大的方式来构建Web应用程序。本文将深入探讨Reflex的原理,并...【详细内容】
2023-12-06  Search: 全栈  点击:(171)  评论:(0)  加入收藏
Next.js的崛起:为什么它是现代网站的首选全栈框架
在选择前端框架时,可靠性对我的客户至关重要。尽管我研究了诸如SvelteKit等选项,但"为什么选择Next.js?"仍然是一个经常被问到的问题。在这篇文章中,我将详细解释为什么Next.js...【详细内容】
2023-11-02  Search: 全栈  点击:(289)  评论:(0)  加入收藏
解码全栈!
作者 | Ivan Novak编译 | 徐杰承你想成为一名全栈工程师吗?在如今这个大兴降本增效的时代,“全栈”似乎被动的成为了大部分开发者的最终归宿。在一部分人眼中,全栈代表着更快的...【详细内容】
2023-08-21  Search: 全栈  点击:(261)  评论:(0)  加入收藏
Wasp框架开源:最快的 React + Node 全栈应用开发!
什么是 WaspWasp(Web 应用程序规范)是一个类似 Rails 的 React、Node.js 和 Prisma 框架,借助于该框架开发者可以快速构建应用程序并使用单个 CLI 命令进行应用部署。Wasp 的典...【详细内容】
2023-08-09  Search: 全栈  点击:(319)  评论:(0)  加入收藏
黄仁勋的野心:英伟达纵横AI软硬件全栈式布局
南方财经全媒体记者江月 上海报道 北京时间8月8日晚间,英伟达创始人兼首席执行官黄仁勋在SIGGRAPH年会上发表了主题演讲。SIGGRAPH 由 ACM SIGGRAPH(计算机协会计算机图形图像...【详细内容】
2023-08-09  Search: 全栈  点击:(128)  评论:(0)  加入收藏
全栈框架 Remix 大火?v1.16 发布,全力备战2.0!
今天给大家带来的主题是全栈框架 Remix,同时介绍了Remix v1.16的诸多新特性,话不多说,直接进入正题。前言如今,当想要基于 React 创建一个新的 Web 项目时,有许多不同的框架可以...【详细内容】
2023-05-17  Search: 全栈  点击:(506)  评论:(0)  加入收藏
一文了解前端、后端、全栈都学什么?薪资前景如何?
随着信息产业的迅猛发展,IT行业人才需求量也在逐年扩大。据国内权威数据统计,未来五年,我国信息化人才总需求量高达1500万&mdash;2000万人。其中“软件开发”、“网络工程”等...【详细内容】
2023-03-27  Search: 全栈  点击:(110)  评论:(0)  加入收藏
我可能永远也没办法成为全栈工程师了,看看你还差多少?
前言写过很多技术贴,今天换个维度写点别的话题,来聊聊程序员的职业发展。不管是对于大厂还是其他软件公司,都会有全栈工程师这个职位,而且这个职位的薪资待遇明显比其他同等级的...【详细内容】
2022-10-08  Search: 全栈  点击:(301)  评论:(0)  加入收藏
如何使用 Next.js、 Prisma、Postgres 和 Fastify 构建全栈应用程序
在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastify 构建一个 Full-stack 应用程序。在本文中,我们将学习如何使用 Next.js、 Prisma、 Postgres 和 Fastif...【详细内容】
2022-07-12  Search: 全栈  点击:(717)  评论:(0)  加入收藏
▌简易百科推荐
Meta如何将缓存一致性提高到99.99999999%
介绍缓存是一种强大的技术,广泛应用于计算机系统的各个方面,从硬件缓存到操作系统、网络浏览器,尤其是后端开发。对于Meta这样的公司来说,缓存尤为重要,因为它有助于减少延迟、扩...【详细内容】
2024-04-15    dbaplus社群  Tags:Meta   点击:(3)  评论:(0)  加入收藏
SELECT COUNT(*) 会造成全表扫描?回去等通知吧
前言SELECT COUNT(*)会不会导致全表扫描引起慢查询呢?SELECT COUNT(*) FROM SomeTable网上有一种说法,针对无 where_clause 的 COUNT(*),MySQL 是有优化的,优化器会选择成本最小...【详细内容】
2024-04-11  dbaplus社群    Tags:SELECT   点击:(3)  评论:(0)  加入收藏
10年架构师感悟:从问题出发,而非技术
这些感悟并非来自于具体的技术实现,而是关于我在架构设计和实施过程中所体会到的一些软性经验和领悟。我希望通过这些分享,能够激发大家对于架构设计和技术实践的思考,帮助大家...【详细内容】
2024-04-11  dbaplus社群    Tags:架构师   点击:(2)  评论:(0)  加入收藏
Netflix 是如何管理 2.38 亿会员的
作者 | Surabhi Diwan译者 | 明知山策划 | TinaNetflix 高级软件工程师 Surabhi Diwan 在 2023 年旧金山 QCon 大会上发表了题为管理 Netflix 的 2.38 亿会员 的演讲。她在...【详细内容】
2024-04-08    InfoQ  Tags:Netflix   点击:(5)  评论:(0)  加入收藏
即将过时的 5 种软件开发技能!
作者 | Eran Yahav编译 | 言征出品 | 51CTO技术栈(微信号:blog51cto) 时至今日,AI编码工具已经进化到足够强大了吗?这未必好回答,但从2023 年 Stack Overflow 上的调查数据来看,44%...【详细内容】
2024-04-03    51CTO  Tags:软件开发   点击:(9)  评论:(0)  加入收藏
跳转链接代码怎么写?
在网页开发中,跳转链接是一项常见的功能。然而,对于非技术人员来说,编写跳转链接代码可能会显得有些困难。不用担心!我们可以借助外链平台来简化操作,即使没有编程经验,也能轻松实...【详细内容】
2024-03-27  蓝色天纪    Tags:跳转链接   点击:(16)  评论:(0)  加入收藏
中台亡了,问题到底出在哪里?
曾几何时,中台一度被当做“变革灵药”,嫁接在“前台作战单元”和“后台资源部门”之间,实现企业各业务线的“打通”和全域业务能力集成,提高开发和服务效率。但在中台如火如荼之...【详细内容】
2024-03-27  dbaplus社群    Tags:中台   点击:(14)  评论:(0)  加入收藏
员工写了个比删库更可怕的Bug!
想必大家都听说过删库跑路吧,我之前一直把它当一个段子来看。可万万没想到,就在昨天,我们公司的某位员工,竟然写了一个比删库更可怕的 Bug!给大家分享一下(不是公开处刑),希望朋友们...【详细内容】
2024-03-26  dbaplus社群    Tags:Bug   点击:(9)  评论:(0)  加入收藏
我们一起聊聊什么是正向代理和反向代理
从字面意思上看,代理就是代替处理的意思,一个对象有能力代替另一个对象处理某一件事。代理,这个词在我们的日常生活中也不陌生,比如在购物、旅游等场景中,我们经常会委托别人代替...【详细内容】
2024-03-26  萤火架构  微信公众号  Tags:正向代理   点击:(15)  评论:(0)  加入收藏
看一遍就理解:IO模型详解
前言大家好,我是程序员田螺。今天我们一起来学习IO模型。在本文开始前呢,先问问大家几个问题哈~什么是IO呢?什么是阻塞非阻塞IO?什么是同步异步IO?什么是IO多路复用?select/epoll...【详细内容】
2024-03-26  捡田螺的小男孩  微信公众号  Tags:IO模型   点击:(10)  评论:(0)  加入收藏
站内最新
站内热门
站内头条