پروژه فاز 4 – انجمن DEV

برای پروژه فاز 4 بوت کمپ مهندسی نرم افزار Flatiron خود، Trip Journal را توسعه دادم، اپلیکیشنی که برای کمک به کاربران در مستندسازی تجربیات سفرشان طراحی شده است. این اپلیکیشن به کاربران اجازه می دهد مکان هایی را که بازدید کرده اند، فعالیت هایی که در آن شرکت کرده اند و بازتاب کلی خود در سفرهایشان را ثبت کنند. این یک فرصت هیجان انگیز برای ترکیب یک باطن Flask API با یک فرانت اند React و کشف پیچیدگی های ساخت یک برنامه فول استک بود.
اهداف پروژه
این پروژه توسط مجموعه ای از الزامات فنی خاص هدایت شد:
- Flask Backend با React Frontend: برنامه باید از Flask برای API و React برای مشتری استفاده می کرد.
- مدل های پایگاه داده:
- حداقل سه مدل با دو رابطه یک به چند و یک رابطه چند به چند.
- ارتباط چند به چند به یک ویژگی قابل ارسال توسط کاربر اضافی نیاز داشت.
- اقدامات CRUD کامل برای حداقل یک منبع و اقدامات ایجاد/خواندن برای همه منابع.
- عملکرد سمت مشتری:
- از Formik برای مدیریت فرم و اعتبار سنجی استفاده کنید.
- با React Router مسیریابی سمت کلاینت را پیاده سازی کنید.
- فرانت اند و باطن را با استفاده از fetch() وصل کنید.
- تجربه کاربری: یک رابط پاسخگو و شهودی برای مدیریت سفرها، مکان ها و فعالیت ها ارائه دهید.
طراحی پایگاه داده
Backend با استفاده از Flask و SQLAlchemy، با سه مدل اصلی: Trip، Place و Activity ساخته شد. این مدل ها روابط بین یک سفر، مکان های بازدید شده و فعالیت های انجام شده را نشان می دهند.
Trip: The central model with attributes like name, start_date, end_date, and description. It includes a one-to-many relationship with Activity.
Place: Represents destinations. It shares a one-to-many relationship with Activity.
Activity: A join table connecting trips and places, forming a many-to-many relationship with user-submittable attributes like name and description.
در اینجا یک عکس فوری از آن است models.py
فایل برای زمینه:
class Trip(db.Model, SerializerMixin):
__tablename__ = 'trip'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
start_date = db.Column(db.Date, nullable=False)
end_date = db.Column(db.Date, nullable=False)
description = db.Column(db.Text)
activities = db.relationship('Activity', back_populates="trip", cascade="all, delete-orphan")
places = association_proxy('activities', 'place', creator=lambda place_obj: Activity(place=place_obj))
class Place(db.Model, SerializerMixin):
__tablename__ = 'places'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
activities = db.relationship('Activity', back_populates="place", cascade="all, delete-orphan")
trips = association_proxy('activity', 'trip', creator = lambda trip_obj : Activity(trip = trip_obj))
class Activity(db.Model, SerializerMixin):
__tablename__ = 'activity'
id = db.Column(db.Integer, primary_key=True)
name = db.Column(db.String(100), nullable=False)
description = db.Column(db.Text)
place_id = db.Column(db.Integer, db.ForeignKey('places.id'), nullable=False)
trip_id = db.Column(db.Integer, db.ForeignKey('trip.id'), nullable=False)
place = db.relationship('Place', back_populates="activities")
trip = db.relationship('Trip', back_populates="activities")
پیاده سازی API
Flask API نقاط پایانی را برای مدیریت سفرها، مکانها و فعالیتها ارائه میکند و از اقدامات کامل CRUD پشتیبانی میکند. در اینجا یک نمونه از طراحی API آورده شده است:
GET /trips
: همه سفرها را با مکانها و فعالیتهای مرتبط واکشی کنید.POST /trips
: یک سفر جدید ایجاد کنید و از اعتبارسنجی فیلدهای ضروری اطمینان حاصل کنید.PATCH /trips/:id
: زمینه های خاص یک سفر را به روز کنید.DELETE /trips/:id
: یک سفر و فعالیت های مرتبط با آن را حذف کنید.
من از flask-restful برای ساختار منابع استفاده کردم و کد را ماژولار و قابل نگهداری کردم.
یکی از چالشهای مهم حصول اطمینان از روابط صحیح بین سفرها، مکانها و فعالیتها هنگام ارسال دادهها به قسمت جلویی است. به عنوان مثال، اگر مکان A به سفر 1 و سفر 2 تعلق داشت، لیست فعالیت های مکان A باید بر اساس سفر فیلتر می شد. من و مربی من روی کد زیر در باطن کار کردیم تا این مشکل را برطرف کنیم:
class TripListResource(Resource):
def get(self):
trips = Trip.query.all()
result = []
for trip in trips:
trip_dict = trip.to_dict(only=('places', 'id', 'name', 'description', 'start_date', 'end_date'))
for place in trip_dict['places']:
place['activities'] = [
activity for activity in place['activities'] if activity['trip_id'] == trip.id
]
result.append(trip_dict)
return result, 200
این اطمینان حاصل کرد که هر سفر مجموعه صحیحی از فعالیت ها را برای مکان های مرتبط خود دریافت می کند.
React Frontend
در قسمت جلویی، من از React برای ایجاد یک رابط کاربری پویا و کاربرپسند استفاده کردم. این برنامه شامل ویژگی های کلیدی زیر بود:
Routing: Using React Router, users could navigate between the home page, trip journal entries, and activity logs seamlessly.
Forms and Validation:
Formik handled form validation with constraints like:
Data Type Validation: Ensuring date formats (e.g., YYYY-MM-DD) were correct.
String Validation: Restricting trip names to at least three characters.
Fetching Data: The fetch API connected the React frontend to the Flask backend, enabling data retrieval and manipulation.
علاوه بر این، من طرحبندیهای واکنشگرا را با استفاده از CSS Flexbox و Grid پیادهسازی کردم و اطمینان حاصل کردم که برنامه هم در دسکتاپ و هم در دستگاههای موبایل عالی به نظر میرسد. این برای شهودی کردن Trip Journal برای کاربرانی که ممکن است بخواهند تجربیات سفر خود را در حال حرکت ثبت کنند، بسیار مهم بود.
چالش ها و نتایج یادگیری
چالش ها:
Fixing Relationships in API Data: The biggest hurdle was ensuring that the relationships between trips, places, and activities were filtered correctly before sending the data to the frontend. Addressing this issue improved my understanding of how to manage complex relationships in SQLAlchemy.
Data Validation: Implementing robust validation for the models required careful thought, especially for relationships and date constraints.
Client-Server Communication: Debugging fetch calls and handling API error messages taught me the importance of clear and consistent data handling between the frontend and backend.
درس های آموخته شده:
ایجاد پروکسی های انجمن: کار بر روی روابط چند به چند، قدردانی من را برای انعطاف پذیری SQLAlchemy عمیق تر کرد.
قدرت Formik: استفاده از Formik مدیریت فرم را ساده می کند و در عین حال تجربه کاربری صیقلی را تضمین می کند.
هم افزایی Backend-Frontend: این پروژه بر اهمیت حصول اطمینان از برقراری ارتباط مؤثر هر دو قسمت باطن و فرانت اند تأکید کرد.
نتیجه گیری
توسعه Trip Journal یک تجربه ارزشمند بود که الزامات فنی را با خلاقیت ادغام کرد. این به من اجازه داد مفاهیمی را که در طول بوت کمپ یاد گرفتم در یک برنامه واقعی به کار ببرم. این پروژه نه تنها دانش من در مورد Flask و React را عمیق تر کرد، بلکه مهارت های حل مسئله من را در توسعه تمام پشته تقویت کرد.
این پروژه گواهی بر این است که چگونه مهندسی نرمافزار ما را قادر میسازد تا ابزارهایی ایجاد کنیم که تجارب شخصی را تقویت میکنند – مانند حفظ خاطرات یک ماجراجویی بزرگ.