First Assignment - 832201115 - WenjingChen - Frontend and Backend Separation Contacts

832201115陈雯静 2024-10-23 23:23:03
Course for This Assignment2401_MU_SE_EE308
Student IDFZU:832201115 MU:22126678
Assignment RequirementsDesign a front-end and back-end separated contact
Objectives of This AssignmentExercise independent learning ability and learn the basic knowledge of software development
Other Referenceshttps://developer.aliyun.com/article/850913

目录

  • 1. Assignment Introduction
  • 1.1 Task Description
  • 1.2 Git Repository Link and Coding Standards Link
  • 1.3 PSP Table
  • 1.3.1 Development Time Record Sheet
  • 1.4 Cloud Server Access Link
  • 2. Finished Product Display
  • 3. Design and Implementation Process
  • 3.1 Project Background
  • 3.2 Project Significance
  • 3.3 Design Concept and Technology Selection
  • 3.4 Implementation Process
  • 3.5 Upload to the Cloud
  • 3.6 Testing and Debugging
  • 4. Challenges Encountered and Solutions
  • 5.Diagrams
  • 5.1 Functional Structure Diagram
  • 5.2 My Development Journey
  • 6. Code Description
  • 6.1 Part of HTML
  • 6.2 Part of Django
  • 7. Personal Learning Journey

1. Assignment Introduction

1.1 Task Description

The first assignment for Software Engineering requires the implementation of a front-end and back-end separated address book, which primarily includes three basic functions: first, the contact adding function, which requires adding information such as name and phone number, and storing it in the back-end database; second, when modifying contact information, it must be read from the back-end database, with caching prohibited; finally, when deleting contact information, it must also be processed from the back-end database. After completing the basic functions, the project needs to be deployed to a cloud server.

In this blog post, I will provide a detailed overview of my project, including the final product, code design, and implementation process. The code can be found in my repository. Please note that sensitive information, such as passwords, has been hidden, and the front-end code is located in the Front folder of the repository. You can find at 832201115_Concacts_GitHub Repository

img


img

Coding Standards Link and Useful Link:

1.3 PSP Table

I recorded the estimated and actual time to develop each module of the program in the PSP sheet.

1.3.1 Development Time Record Sheet

ModulesTask DescriptionEstimated TimeActual Time
Demand AnalysisDetermine the requirements of the web page and the functions that can be achieved2 hour2 hour
Database DesignDesign database schema, including contact information9 hours7 hours
Backend DevelopmentCreate a Spring Boot application and write an interface20 hours22 hours
Front-end DevelopmentPage design, front-end development using JS10 hours13 hours
TestTest whether the web page meets expectations2 hour5 hours
DeployDeploy the application to the server (Alibaba Cloud)2 hours4 hours
Total45 hours53 hours

After the project is successfully deployed to the cloud server, you can access the project through the following link: http://121.41.86.73/.

2. Finished Product Display

Next, I will demonstrate my project with pictures and text to show its functions.

Step 1:User Interface
When you visit http://121.41.86.73/, you will see this interface:

img

Step 2: Adding
You can add new student information by clicking the "Add" button in the upper right corner. You can enter information to save the contact.

img

img

Step 3: Deleting
You can delete a student's information by clicking the red "Delete" button on the far right of their information. Additionally, you can select multiple student records by checking the boxes in front of them and then clicking the "Batch Delete" button in the lower left corner to delete several records at once.

img

img

img

Step 4: Modifying
You can edit any student's information, including their name, phone number, email, and home address, by clicking the blue "Edit" button on the right.

img

Step 5: Querying
You can search for students that meet specific criteria by entering your query conditions at the top of the screen and clicking the button on the right. For example, you can input "Shandong Province" as a filter.

img

img

Step 6: Pagination Feature
After the query, you can return to all entries in the address book by clicking the "All" button. Additionally, you can navigate to other pages by clicking on the page numbers in the lower right corner. I've set it up to display 10 student records per page, with a total of 3 pages for 21 student records.

img

img

3. Design and Implementation Process

3.1 Project Background

My first assignment, the FZU Student Address Book aims to provide a convenient platform for managing student information, utilizing modern front-end and back-end separation technology. It enables the display of student data from the database on web pages, as well as the ability to add, modify, and delete information through the interface.

3.2 Project Significance

This project simplifies the process for administrators and students to manage student information through a user-friendly web interface. The use of a front-end and back-end separated architecture not only improves system responsiveness and user experience but also makes the system easier to maintain and expand.

3.3 Design Concept and Technology Selection

When designing the address book application, I considered the following functional modules:

  • Front-end and Back-end Separation: The front end uses Vue and Element UI for page rendering, while the back end is implemented with Python Django to provide data interfaces.
  • Database Operations Based on the ORM Model: The 4 basic operations(adding,deleting,modifying,querying) on the database are performed using the ORM model.
  • Data Persistence: Use MySQL database to store contact information, ensuring data security and consistency.
  • Front-end and Back-end Interaction: The front end interacts with the back end through data exchanges using Axios for API communication.

3.4 Implementation Process

Environment Setup:

  • Configure the development environment, install Python-Django and MySQL.
  • Create a MySQL database and contact table.

Function1: Adding Student Information:

  • Demonstration: Click "Add" in the upper right corner to add student details, including student ID, name, gender, date of birth, phone number, email address, and home address.

img

img

  • Front End: Use Element UI to automatically display a pop-up form for entering student information when the "Add" button is clicked.
  • Back End: When adding a student ID, use a custom function to check if the ID already exists. The ID received from the front end is validated using a try-except block, and the result is returned to the front end via Axios.
  • Back End: Accept the values passed from the front end and add the new student record to the database.
  • Front End: After successful validation, execute the function to add the student data to the database.

Function2: Deleting Student Information:

  • Demonstration:

    img

img

  • Back End: Use the delete() function to remove the student record from the database.
  • Front End: Trigger a confirmation dialog using Element UI before deletion, and call the back-end API to proceed with the deletion if confirmed.

Function3: Modifying Student Information:

  • Demonstration:

img

img

img

  • Back End: Locate the student information that needs to be updated, similar to the process used for adding, and modify fields such as name, gender, and other details.
  • Front End: Follow a similar process to the "Add" functionality, with appropriate prompts indicating the modifications.

Function4: Querying Student Information:

  • Demonstration:

img

img

  • Implementation:Bind the query conditions to input fields, and send the input data to the back end using an Ajax POST request.

Extended Feature 1: Batch Deletion:

  • Demonstration:

img

img

img

  • Implementation: On the back end, iterate over the collection of selected records, look up each current record, and perform the deletion. On the front end, use checkboxes to select multiple records, effectively collecting them for batch deletion.

Extended Feature 2: Data Pagination on the Front End:

  • Demonstration:

img

img

  • Implementation: Add two variables to keep track of the current page number and the number of rows displayed per page. Write a custom function to fetch student data for the current page: first, clear the data from the previous pagination, then iterate through the new data to add it to the current page, ensuring it meets the per-page row limit. Stop once the row limit is reached.

3.5 Upload to the Cloud

Rent an Alibaba Cloud server to deploy the web page, use the LAMP stack, and develop on port 8080 as a platform for running the web page. Upload files, configure the Spring Boot framework on the server, and run the Spring Boot application.

  • Step 1: First, I signed a free Alibaba cloud server and chose the Linux system (Ubuntu).

  • Step 2: Checked the public IP of my cloud server.

  • Step 3: Used an SSH connection tool; I used Xshell to connect to the cloud server.

  • Step 4: Installed Nginx.

  • Step 5: Installed Xftp (for file uploads).

  • Step 6: Added the Nginx configuration file with vim /etc/nginx/conf.d/xxx.conf, containing the following:

  • server {
    listen 80;
    server_name 121.41.86.73
    root /apps/student;
    index index.html;
    }

  • Step 7: Restarted Nginx and checked if the configuration took effect: systemctl restart nginx. (Access via browser at http://. If it fails, check if the cloud server's security group allows port 80, and if the firewall is enabled, ensure the port is open.)

  • Step 8: Installed Python 3; since Ubuntu 22 comes with Python 3.10, I didn't install it separately.

  • Step 9: Installed the built-in Python 3 venv environment with apt install python3.10-venv.

  • Step 10: Created a virtual environment using python3 -m venv .

  • Step 11: Activated the virtual environment with source /bin/activate.

  • Step 12: Installed Python third-party packages: pip install -r requirements.txt.

  • Step 13: Installed MySQL: apt install mysql-server.

  • Step 14: Set the root password for MySQL, following instructions from https://zhuanlan.zhihu.com/p/698532008.

  • Step 15: Created a database in MySQL: create database .

  • Step 16: Migrated the database to generate the corresponding tables: python manage.py migrate.

  • Step 17: Imported contact database records.

  • Step 18: Started the server with python manage.py runserver 0.0.0.0:8080.

3.6 Testing and Debugging

Perform unit and integration tests on the API to ensure the correctness of each module.

4. Challenges Encountered and Solutions

One of the main difficulties I faced was my lack of experience in deploying projects to the cloud. The methods I found online for network penetration were not functional, leaving me feeling lost.
To resolve this, I took the following steps:

  1. I actively sought help from Professor Lin and teaching assistants Wu, Kong, and Liu, asking questions in person on multiple occasions.
  2. I installed an Alibaba Cloud server, and the specific deployment steps have been detailed earlier in this report.
  3. When I encountered runtime errors during the deployment, I copied the error messages and searched for solutions on platforms like CSDN and Zhihu, diligently looking for tutorials and leveraging the knowledge of others.

5.Diagrams

5.1 Functional Structure Diagram

img

5.2 My Development Journey

img

6. Code Description

6.1 Part of HTML


<body>
    <div id="app">
        <el-container>
            <el-header style="height: 80px;">福大学生通讯录</el-header>
            <el-container>
                <!-- 侧边栏 -->
                <el-aside width="200px">
                    <el-menu default-active="2" class="el-menu-vertical-demo">
                        <el-menu-item index="1">
                            <i class="el-icon-menu"></i>
                            <span slot="title">所属学院</span>
                        </el-menu-item>
                        <el-menu-item index="2">
                            <i class="el-icon-user"></i>
                            <span slot="title">学生信息</span>
                        </el-menu-item>
                        <el-menu-item index="3">
                            <i class="el-icon-s-custom"></i>
                            <span slot="title">老师信息</span>
                        </el-menu-item>
                        <el-menu-item index="4">
                            <i class="el-icon-document"></i>
                            <span slot="title">其他</span>
                        </el-menu-item>
                    </el-menu>
                </el-aside>
                <el-container>
                    <!-- 主窗体 -->
                    <el-main>
                        <!-- 面包屑导航 -->
                        <el-breadcrumb separator-class="el-icon-arrow-right">
                            <el-breadcrumb-item>首页</el-breadcrumb-item>
                            <el-breadcrumb-item>学生管理</el-breadcrumb-item>
                        </el-breadcrumb>
                        <!-- 表单 -->
                        <el-form :inline="true" style="margin-top:30px;">
                            <el-row>
                                <el-col :span="12">
                                    <el-form-item label="查询学生条件:">
                                        <el-input v-model="inputStr" placeholder="输入查询条件" style="width: 420px;">
                                        </el-input>
                                    </el-form-item>
                                </el-col>
                                <el-col :span="8" style="text-align: right;padding-right:10px;">
                                    <el-button-group>
                                        <el-button type="primary" icon="el-icon-search" @click="queryStudents()">查询
                                        </el-button>
                                        <el-button type="primary" icon="el-icon-tickets" @click="getAllStudents()">全部
                                        </el-button>
                                        <el-button type="primary" icon="el-icon-circle-plus-outline"
                                            @click="addStudent()">添加</el-button>
                                    </el-button-group>
                                </el-col>
                                <el-col :span="2">
                                    <el-upload :show-file-list="false" :http-request="uploadExcelPost">
                                        <el-button type="primary">导入Excel</el-button>
                                    </el-upload>
                                </el-col>
                                <el-col :span="2">
                                    <el-button type="primary" @click="exportToExcel()">导出Excel</el-button>
                                </el-col>
                            </el-row>
                        </el-form>
                        <!-- 表格 -->
                        <el-table :data="pageStudents" border style="width: 100%" size="mini"
                            @selection-change="handleSelectionChange">
                            <el-table-column type="selection">
                            </el-table-column>
                            <el-table-column type="index" label="序号" align="center" width="60">
                            </el-table-column>
                            <el-table-column prop="sno" label="学号" width="80">
                            </el-table-column>
                            <el-table-column prop="name" label="姓名" width="80">
                            </el-table-column>
                            <el-table-column prop="gender" label="性别" width="60">
                            </el-table-column>
                            <el-table-column prop="birthday" label="出生日期" align="center" width="100">
                            </el-table-column>
                            <el-table-column prop="mobile" label="电话" align="center" width="120">
                            </el-table-column>
                            <el-table-column prop="email" label="邮箱" align="center" width="220">
                            </el-table-column>
                            <el-table-column prop="address" label="地址" align="center">
                            </el-table-column>
                            <el-table-column label="操作" width="180" align="center">
                                <template slot-scope="scope">
                                    <el-button type="success" icon="el-icon-more" size="mini" circle
                                        @click="viewStudent(scope.row)"></el-button>
                                    <el-button type="primary" icon="el-icon-edit" size="mini" circle
                                        @click="updateStudent(scope.row)"></el-button>
                                    <el-button type="danger" icon="el-icon-delete" size="mini" circle
                                        @click="deleteStudent(scope.row)"></el-button>
                                </template>
                            </el-table-column>
                        </el-table>
                        <!-- 分页 -->
                        <el-row style="margin-top: 20px;">
                            <el-col :span="8" style="text-align: left">
                                <el-button type="danger" icon="el-icon-delete" size="mini" @click="deleteStudents()">
                                    批量删除</el-button>
                            </el-col>
                            <el-col :span="16" style="text-align: right">
                                <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
                                    :current-page="currentpage" :page-sizes="[5, 10, 50, 100]" :page-size="pagesize"
                                    layout="total, sizes, prev, pager, next, jumper" :total="total">
                                </el-pagination>
                            </el-col>
                        </el-row>
                        <!-- 弹出框的学生明细表单 -->
                        <el-dialog :title="dialogTitle" :visible.sync="dialogVisible" width="50%"
                            @close="closeDialogForm('studentForm')">
                            <el-form :model="studentForm" :rules="rules" ref="studentForm" :inline="true"
                                style="margin-left: 20px;" label-width="110px" label-position="right" size="mini">
                                <el-upload class="avatar-uploader" 
                                    :show-file-list="false" :http-request="uploadPicturePost" :disabled="isView"  style="text-align: center;margin:20px;" >
                                    <img v-if="studentForm.image" :src="studentForm.imageUrl" class="avatar">
                                    <i v-else class="el-icon-plus avatar-uploader-icon"></i>
                                </el-upload>
                                <el-form-item label="学号:" prop="sno">
                                    <el-input v-model="studentForm.sno" :disabled="isEdit||isView"
                                        suffix-icon="el-icon-edit"></el-input>
                                </el-form-item>
                                <el-form-item label="姓名:" prop="name">
                                    <el-input v-model="studentForm.name" :disabled="isView" suffix-icon="el-icon-edit">
                                    </el-input>
                                </el-form-item>
                                <el-form-item label="性别:" prop="gender">
                                    <el-select v-model="studentForm.gender" :disabled="isView" placeholder="请选择性别">
                                        <el-option value="男"></el-option>
                                        <el-option value="女"></el-option>
                                    </el-select>
                                </el-form-item>
                                <el-form-item label="出生日期:" prop="birthday">
                                    <el-date-picker v-model="studentForm.birthday" value-format="yyyy-MM-dd"
                                        :disabled="isView" type="date" placeholder="选择日期" style="width:93% ">
                                    </el-date-picker>
                                </el-form-item>
                                <el-form-item label="手机号码:" prop="mobile">
                                    <el-input v-model="studentForm.mobile" :disabled="isView"
                                        suffix-icon="el-icon-edit"></el-input>
                                </el-form-item>
                                <el-form-item label="邮箱地址:" prop="email">
                                    <el-input v-model="studentForm.email" :disabled="isView" suffix-icon="el-icon-edit">
                                    </el-input>
                                </el-form-item>
                                <el-form-item label="家庭住址:" prop="address">
                                    <el-input v-model="studentForm.address" :disabled="isView"
                                        suffix-icon="el-icon-edit" style="width:262%"></el-input>
                                </el-form-item>
                            </el-form>
                            <span slot="footer" class="dialog-footer">
                                <el-button type="primary" size="mini" v-show="!isView"
                                    @click="submitStudentForm('studentForm')">确 定</el-button>

                                <el-button type="info" size="mini" @click="closeDialogForm('studentForm')">取 消
                                </el-button>
                            </span>
                        </el-dialog>
                    </el-main>
                    <el-footer style="height: 30px;">福大学生通讯录 | 832201115陈雯静Assignment 2024-10-20</el-footer>
                </el-container>
            </el-container>
        </el-container>
    </div>
</body>

6.2 Part of Django

def get_students(request):
    """获取所有学生的信息"""
    try:
        # 使用ORM获取所有学生信息 并把对象转为字典格式
        obj_students = Student.objects.all().values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code':1, 'data':students})
    except Exception as e:
        # 如果出现异常,返回
        return JsonResponse({'code': 0, 'msg': "获取学生信息出现异常,具体错误:" + str(e)})


def query_students(request):
    """查询学生信息"""
    # 接收传递过来的查询条件--- axios默认是json --- 字典类型('inputstr')-- data['inputstr']
    data = json.loads(request.body.decode('utf-8'))
    try:
        # 使用ORM获取满足条件的学生信息 并把对象转为字典格式
        obj_students = Student.objects.filter(Q(sno__icontains=data['inputstr']) | Q(name__icontains=data['inputstr']) |
                                              Q(gender__icontains=data['inputstr']) | Q(mobile__icontains=data['inputstr'])
                                              | Q(email__icontains=data['inputstr']) | Q(address__icontains=data['inputstr'])).values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code': 1, 'data': students})
    except Exception as e:
        # 如果出现异常,返回
        return JsonResponse({'code': 0, 'msg': "查询学生信息出现异常,具体错误:" + str(e)})

def add_student(request):
    """添加学生到数据库"""
    # 接收前端传递过来的值
    data = json.loads(request.body.decode("utf-8"))
    try:
        # 添加到数据库
        obj_student = Student(sno=data['sno'],name=data['name'],gender=data['gender'],
                              birthday=data['birthday'],mobile=data['mobile'],
                              email= data['email'], address=data['address'],image=data['image'])
        # 执行添加
        obj_student.save()
        # 使用ORM获取所有学生信息 并把对象转为字典格式
        obj_students = Student.objects.all().values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code': 1, 'data': students})
    except Exception as e:
        return JsonResponse({'code':0 , 'msg': "添加到数据库出现异常,具体原因:" + str(e)})


def update_student(request):
    """修改学生到数据库"""
    # 接收前端传递过来的值
    data = json.loads(request.body.decode("utf-8"))
    try:
        # 查找到要修改的学生信息
        obj_student = Student.objects.get(sno=data['sno'])
        # 依次修改
        obj_student.name = data['name']
        obj_student.gender = data['gender']
        obj_student.birthday = data['birthday']
        obj_student.mobile = data['mobile']
        obj_student.email = data['email']
        obj_student.address = data['address']
        obj_student.image = data['image']
        # 保存
        obj_student.save()
        # 使用ORM获取所有学生信息 并把对象转为字典格式
        obj_students = Student.objects.all().values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code': 1, 'data': students})
    except Exception as e:
        return JsonResponse({'code':0 , 'msg': "修改保存到数据库出现异常,具体原因:" + str(e)})


def delete_student(request):
    """删除一条学生信息"""
    # 接收前端传递过来的值
    data = json.loads(request.body.decode("utf-8"))
    try:
        # 查找到要修改的学生信息
        obj_student = Student.objects.get(sno=data['sno'])
        # 删除
        obj_student.delete()
        # 使用ORM获取所有学生信息 并把对象转为字典格式
        obj_students = Student.objects.all().values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code': 1, 'data': students})
    except Exception as e:
        return JsonResponse({'code': 0, 'msg': "删除学生信息写入数据库出现异常,具体原因:" + str(e)})


def delete_students(request):
    """批量删除学生信息"""
    # 接收前端传递过来的值
    data = json.loads(request.body.decode("utf-8"))
    try:
        # 遍历传递的集合
        for one_student in data['student']:
            # 查询当前记录
            obj_student = Student.objects.get(sno=one_student['sno'])
            # 执行删除
            obj_student.delete()
        # 使用ORM获取所有学生信息 并把对象转为字典格式
        obj_students = Student.objects.all().values()
        # 把外层的容器转为List
        students = list(obj_students)
        # 返回
        return JsonResponse({'code': 1, 'data': students})
    except Exception as e:
        return JsonResponse({'code': 0, 'msg': "批量删除学生信息写入数据库出现异常,具体原因:" + str(e)})

Provides CRUD operations: add contact (POST), get all contacts (GET), update contact (PUT), and delete contact (DELETE).

7. Personal Learning Journey

In this assignment, I have learned:

  • Implement the most basic front-end and back-end separation interaction.
  • Improve information retrieval ability.
  • Learn how to deploy cloud servers.
  • Back End:
    Gained a preliminary understanding of various Python statements and developed a foundational proficiency in the Django web framework.
  • Front End:
    Systematically learned the structure and fundamental applications of Vue, applying this knowledge to practical examples. Gradually became familiar with the use of Element UI and Vue, mastering the creation of pop-up forms, the layout of page structures, the implementation of sidebar functionality, the organization of form layouts, the display of data in tables, and the realization of pagination features.

Thanks to our tutors, Professor Lin and teaching assistants Wu, Kong, and Liu for their patient explanation and guidance!!!
Thank you for reaching this point! Feel free to share any valuable feedback or suggestions at any time.

...全文
263 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

170

社区成员

发帖
与我相关
我的任务
社区描述
2401_MU_SE_FZU
软件工程 高校
社区管理员
  • FZU_SE_TeacherL
  • 助教-吴可仪
  • 助教-孔志豪
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧