حلول الواجهة الخلفية
إجابات اختبار المعرفة
-
jsonify()تحوّل قاموس Python إلى استجابة JSON وتضبط ترويسةContent-Type: application/jsonالصحيحة. وبدونها، قد تُرجع Flask صيغًا أو أخطاء غير متوقعة. -
البيئة الافتراضية تعزل تبعيات مشروعك عن Python النظام، فتمنع تعارض الإصدارات بين المشاريع.
-
db.session.commit()تحفظ كل التغييرات المعلّقة في قاعدة البيانات. وبدونها تضيع التغييرات (الإضافات والتحديثات وعمليات الحذف) عند انتهاء الجلسة. -
nullable=Falseيعني أن العمود لا يمكن أن يكونNULLأو فارغًا في قاعدة البيانات. ويُرفع خطأ إذا حاولت حفظ سجل دون تقديم قيمة. -
ملفات
.envتحتوي على أسرار (مفاتيح API وكلمات المرور). إذا أُدرجت في commit ثم دُفعت إلى مستودع عام، استطاع أي شخص رؤية مفاتيحك وسرقتها.
حل التحدي 1
أضف إلى routes.py:
@api.route("/messages", methods=["DELETE"])
def delete_all_messages():
count = Message.query.delete()
db.session.commit()
return jsonify({"deleted": count})
اختبار:
curl -X DELETE http://localhost:5000/api/messages
# → {"deleted": 5}
حل التحدي 2
النهج في الذاكرة (بسيط):
أضف قرب أعلى routes.py:
CURRENT_SYSTEM_PROMPT = "You are a helpful assistant."
أضف مسارين جديدين:
@api.route("/system-prompt", methods=["GET"])
def get_system_prompt():
global CURRENT_SYSTEM_PROMPT
return jsonify({"current_prompt": CURRENT_SYSTEM_PROMPT})
@api.route("/system-prompt", methods=["POST"])
def set_system_prompt():
global CURRENT_SYSTEM_PROMPT
data = request.get_json()
CURRENT_SYSTEM_PROMPT = data.get("prompt", CURRENT_SYSTEM_PROMPT)
return jsonify({"current_prompt": CURRENT_SYSTEM_PROMPT})
ثم عدّل مسار chat ليستخدم CURRENT_SYSTEM_PROMPT:
messages = [
{"role": "system", "content": CURRENT_SYSTEM_PROMPT},
{"role": "user", "content": user_message},
]
اختبار:
curl -X POST http://localhost:5000/api/system-prompt \
-H "Content-Type: application/json" \
-d '{"prompt": "You speak like a pirate."}'
curl -X POST http://localhost:5000/api/chat \
-H "Content-Type: application/json" \
-d '{"message": "Hello!"}'
# → "Ahoy, matey!"
حل التحدي 3
عدّل مسار chat ليتضمن سجل المحادثة:
@api.route("/chat", methods=["POST"])
def chat():
data = request.get_json()
user_message = data.get("message", "")
if not user_message:
return jsonify({"error": "Message is required"}), 400
user_msg = Message(content=user_message, sender="user")
db.session.add(user_msg)
db.session.commit()
try:
# احصل على آخر 10 رسائل للسياق
recent = Message.query.order_by(Message.timestamp.desc()).limit(10).all()
recent.reverse()
messages = [{"role": "system", "content": "You are a helpful assistant."}]
for msg in recent:
role = "user" if msg.sender == "user" else "assistant"
messages.append({"role": role, "content": msg.content})
response = client.chat.completions.create(
model="gpt-4o-mini",
messages=messages,
)
ai_reply = response.choices[0].message.content
ai_msg = Message(content=ai_reply, sender="ai")
db.session.add(ai_msg)
db.session.commit()
return jsonify({
"user_message": user_msg.to_dict(),
"ai_message": ai_msg.to_dict(),
})
except Exception as e:
return jsonify({"error": str(e)}), 500
مشروع مفتوح: API لقائمة المهام
models.py — إضافة نموذج Todo
class Todo(db.Model):
id = db.Column(db.Integer, primary_key=True)
title = db.Column(db.String(200), nullable=False)
completed = db.Column(db.Boolean, default=False)
created_at = db.Column(db.DateTime, default=lambda: datetime.now(timezone.utc))
def to_dict(self):
return {
"id": self.id,
"title": self.title,
"completed": self.completed,
"created_at": self.created_at.isoformat() if self.created_at else None,
}
routes.py — إضافة مسارات المهام
@api.route("/todos", methods=["GET"])
def get_todos():
completed = request.args.get("completed")
sort = request.args.get("sort", "created_at")
order = request.args.get("order", "desc")
query = Todo.query
if completed is not None:
val = completed.lower() == "true"
query = query.filter_by(completed=val)
if order == "desc":
query = query.order_by(getattr(Todo, sort).desc())
else:
query = query.order_by(getattr(Todo, sort).asc())
todos = query.all()
return jsonify([t.to_dict() for t in todos])
@api.route("/todos", methods=["POST"])
def create_todo():
data = request.get_json()
if not data or not data.get("title"):
return jsonify({"error": "Title is required"}), 400
todo = Todo(title=data["title"])
db.session.add(todo)
db.session.commit()
return jsonify(todo.to_dict()), 201
@api.route("/todos/<int:todo_id>", methods=["PUT"])
def update_todo(todo_id):
todo = Todo.query.get(todo_id)
if not todo:
return jsonify({"error": "Not found"}), 404
data = request.get_json()
if "completed" in data:
todo.completed = data["completed"]
if "title" in data:
todo.title = data["title"]
db.session.commit()
return jsonify(todo.to_dict())
@api.route("/todos/<int:todo_id>", methods=["DELETE"])
def delete_todo(todo_id):
todo = Todo.query.get(todo_id)
if not todo:
return jsonify({"error": "Not found"}), 404
db.session.delete(todo)
db.session.commit()
return jsonify({"deleted": True})
اختبار المسار الكامل:
# إنشاء
curl -X POST http://localhost:5000/api/todos \
-H "Content-Type: application/json" \
-d '{"title": "Learn Flask"}'
# عرض
curl http://localhost:5000/api/todos
# إكمال
curl -X PUT http://localhost:5000/api/todos/1 \
-H "Content-Type: application/json" \
-d '{"completed": true}'
# حذف
curl -X DELETE http://localhost:5000/api/todos/1