اذهب إلى المحتوى

Mohamed Abu Abdo

الأعضاء
  • المساهمات

    31
  • تاريخ الانضمام

  • تاريخ آخر زيارة

1 متابع

آخر الزوار

لوحة آخر الزوار معطلة ولن تظهر للأعضاء

إنجازات Mohamed Abu Abdo

عضو مساهم

عضو مساهم (2/3)

23

السمعة بالموقع

22

إجابات الأسئلة

  1. من الممكن جعل المتغير المذكور عام Global ولكنه مع الوصول المتزامن للمستخدمين لن تتمكن من مراقبة أو إستخدام متغيراتك بشكل جيد,أو بوصف أدق عندما يقوم عدة مستخدمين في نفس اللحظة بتسجيل الدخول سيتم طباعة القيم في نفس اللحظة ,وإذا كنت تريد إستخدام هذا الرقم كتعريف لجلسة المستخدم فلن تتمكن من معرفة الرقم الخاص بكل مستخدم. لذلك فكر في أساليب أخرى علي سبيل المثال إذا كانت الدالتين يتجاوبان مع نفس صفحة html فيمكنك إرسال القيمة من الدالة الأولى إلى صفحة html حيث يتم الاحتفاظ بالمتغير هناك ضمن حقل نص أو text box, ثم تقوم الدالة الثانية بالحصول عليه عندما تستلم طلب Post عبر random_number = request.form['random_number'] إليك المثال الكامل: login.py <html> <body> <form action = "/login" method = "post"> <p>Enter Name0:</p> <p><input type = "text" name = "nm" /></p> <input type="text" style="display:none;" name="random_number" value="{{random_number}}"> <p><input type = "submit" value = "submit" /></p> </form> </body> </html> لاحظ هنا قمنا بإخفاء مربع النص Text box style="display:none;" وهذا إذا كنا لا نحتاج لعرضه على المستخدمين, main.py from flask import Flask, render_template, request import random app = Flask(__name__, template_folder='template') @app.route('/login', methods=['GET']) #وهي التي تعمل عند فتح الصفحةGETالدالتين يحملان نفس المسار بالفعل ولكن انتبه إحداهما def a(): random_number = random.random() return render_template("login.html", random_number=random_number)#إرسال المتغير أو بالأحرى قيمته @app.route('/login', methods=['POST'])#كتسجيل الدخول مثلا POSTوالثانية عند إرسال فورم عبر def b(): random_number = request.form['random_number'] #إستلام قيمة المتغير المنشود print("Random Number:{}".format(random_number)) return render_template('home.html') if __name__ == "__main__": app.run(debug=True) من المؤكد بأن هناك المزيد والمزيد من الطرق, وأذكر منهم أيضا شئ مما أشرت إليه في نهاية سؤالك وهو الاستفادة من الجلسات وcookie فالكوكيز هي ببساطة تشبه وحدة تخزين مرتبطة بموقعك داخل متصفح كل مستخدم, حيث يمكننا الإحتفاظ بالمتغيرات أو token أو غير ذلك بداخلها, بغاية إفادة المستخدمين وجعل تجربتهم لموقعك أفضل وبالطبع هى ليست مناسبة لكل شئ, ولكن لكل مقام مقال, وعادة ما تكون مضطراً لإختيار الأداة التى تناسب مشروعك أو التحدى الذي يواجهك.
  2. الصور تستهلك الكثير من الذاكرة ,وبوضعها داخل قاعدة البيانات سيتسبب هذا بمرور الوقت في ضرورة تكبير الحيز المتاح لقاعدة البيانات هذا أولاً, ثانياً سيتسبب هذا في تأخر طلبات الإستعلام من وإلي قاعدة البيانات, ثالثا كبر حجم الاستعلام نفسه فعلي سبيل المثال إذا كان المستخدم سيطلب عرض Slides يحتوي علي عدة صور وليكن أربعة صور كل صورة منهم حجمها يفوق 500 كيلوبايت ,مما يعني 2 ميغابايت حجم الصور الإجمالي أو أكثر , عوضاً عن باقي البيانات , في هذا الوضع تخيل أن سرعة الانترنت لدي مستخدمين هذا الموقع أقل من 100 كيلوبايت في الثانية الواحدة أو لنفرض 100, وهذا يعني أن زمن تنفيذ واستلام هذا الطلب يترواح بين 15 إلى 25 ثانية ,في حين أنك قد تكون مضطراً إلى ضبط إعدادات موقعك والسيرفر الذي يديره علي زمن انتظار أو timeOut أقل من هذا الحيز بكثير , مما عني في نهاية الأمر فشل الطلب وظهور رسالة Error time out للمستخدمين الذين يمتلكون سرعة اتصال بالانترنت أقل من 500 كيلوبايت , لا أخفي عليك القول أنني في هذه اللحظة لا يمكنني الدخول إلى موقعك هذا لأنني أمتلك سرعة اتصال أقل من جيدة. غير ذلك كبر حجم الطلبات المرسلة يستغرق الكثير من الموارد المخصصة لموقعك او تطبيقك, البديل لتلك الطريقة هو حفظ اسماء الصور فقط في قاعدة البيانات , بينما يتم حفظ الصور في مكان أخر أو ربما سيرفر أخر تماما وهذا ما يقوم به العديد من المواقع ,فمثلا يمكنك إنشاء موقعك علي أي استضافة ثم حفظ الصور او الملفات علي اسضافة أخري أقل تكلفة وأفضل ك Amazon S3 , وهنا حاول تخيل وضع المستخدم الذي يحاول تحميل موقع به العديد من الصور بالإضافة إلى Slides الموجود في رأس الصفحة الرئيسية, فمع حفظ جميع الصور في قاعدة البيانات مضغوطة بbase64 سيصبح من الصعب الوصول لموقعك. ولكن في حال وجود الصور بعيداً عن قاعدة البيانات سيكون تحميل كل صورة فقط عندما يحاول المستخدم عرضها , كأن يتحرك داخل Slides ,أو يحاول عرض اجزاء من الصفحة تحوي صوراً إلى أخره. ولكن نعود إلى نقطة مهمة ذكرتها في سؤالك"وهي إن كنا نقوم بتحويلها إلى base64 قبل الإرسال!" فأولاً من الأفضل تشفير الصور إلى base64 داخل frontend أو حتي عدم تشفيرها فذلك ليس ضرورياً, وربما في حالات معينة مثل محاولة اخفاء الخادم الذي يتم الاحتفاظ بالصور بداخله, حتي مع هذا الإجراء فأنت تقلل الاعتماد علي قاعدة البيانات في أمور بعينها , ولكن يظل هناك جانب مرهق واقع علي الخادم أو علي الجزء المعني بتحويل الصور وإرسالها للمستخدم. وإن لم يكن الجانب الأمني في اعتبارك فأنصح بإرسال url او لينك الصور بدلا من تحويلها, وبالتأكيد هناك الكثير من الأسباب التقنية التي لم أتطرق إليها. بالتوفيق
  3. لا تحتاج إلي كتابة المسار داخل render_template فقط يمكنك تغيير المسار الرئيسي من خلال template_folder , تابع التالي #main.py from flask import (Flask, render_template) app = Flask(__name__, template_folder='../frontend/template') @app.route('/notifications') def notifications(): return render_template("view_notifications.html") #إذا كان لديك مسارات فرعية فيمكنك إستخدامها بالشكل التالي @app.route('/page') def pages(): return render_template("post/page.html") وإذا كنت تشك في مسارك يمكنك كتابة المسار كاملاً بالشكل التالي app = Flask(__name__, template_folder=r'C:\Users\mohamed\project\frontend\template') لاتنسي حرف r مهم إذا كنت تستخدم نظام التشغيل ويندوز ومساره الكامل والذي يبدأ ب C:\Users أو D:\x وما شابه وإلا سيواجهك خطأ كهذا app = Flask(__name__, template_folder='C:\Users\mohamed\project\frontend\template') ^ SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in position 2-3: truncated \UXXXXXXXX escape موفق
  4. يمكن الحفظ بأكثر من طريقة مثلا من form.py او view.py أو models.py فيما يلي طريقتين للحفظ من خلال models.py def edit_path(instance, filename): """من الممكن ألا يعمل username ويكون البديل هو user""" users_media = 'users' #يرجي العلم بأن جميع المستخدمين سيتم إنشائهم بداخل هذا المسار الفرعي ويمكن استبداله return f'{users_media}/{instance.username}/{filename}' class Post(models.Model): title = models.CharField(max_length=200) user = models.ForeignKey(User) thumbnail = models.FileField(upload_to=edit_path) #يتم استبدال مسار الحفظ بالدالة أعلاه سيتم إنشاء مجلد أو مسار لكل مستخدم بداخل users وكل هذا بالطبع داخل المسار MEDIA_ROOT المعلن عنه في settings.py . 2: هو استخدام دالة save الموجودة في models ,تابع التالي from django.conf import settings from django.core.files.base import File import os class Post(models.Model): title = models.CharField(max_length=200) user = models.ForeignKey(User) thumbnail = models.FileField(upload_to='users/') def save(self, *args, **kwargs):#يتم تنفيذ هذه الدالة مباشرة عند إجراء حفظ بيانات جديدة لهذا الجدول if self.user: name = self.user.username #الحصول على أسم المستخدم #إنشاء مسار جديد لهذا المستخدم في مسار الوسائط new_directory = os.path.join(settings.MEDIA_ROOT, 'users', name) if not os.path.exists(new_directory): os.makedirs(new_directory) #قراءة الملف السابق with open(thumbnail.path) as f: #ثم حفظه في المسار الجديد وتسجيل التغيير في الحقل المنشود self.thumbnail.save(os.path.join(new_directory,thumbnail.filename), File(f)) return super(Post, self).save(*args, **kwargs) تعتبر الطريقة الأولي هي الأفضل ولكن الطريقة الثانية قد تكون مفيدة وأكثر مرونة في حالات عدة من بينها إستخدام إجراءات أكثر داخل الجدول Post من تغيير قيمة حقول أخري في نفس اللحظة, إلي أخره. موفقين
  5. تطبيقات Django تكون موجودة في عدة أماكن تحتاج منك إلي حذفها يدوياً, مثلا urls.py الرئيسي وINSTALLED_APPS وغيرها من الأماكن, بالنسبة لقاعدة البيانات قد يختلف إزالة التطبيقات بين إصدارات Django الأحدث والأقدم فمثلا في الإصدارات الأقدم من 1.7 يمكننا استخدام python manage.py sqlclear myapp python manage.py migrate وبالنسبة للإصدارات الأحدث يكفي إزالة التطبيق من INSTALLED_APPS وتنفيذ python manage.py migrate ------------- هناك طرق أخرى مثلا يمكن حذف الجداول المتعلقة بهذا التطبيق قبل إزالة التطبيق نفسه python manage.py makemigrations -n drop_all_tables myapp ثم إزالته بأمان من INSTALLED_APPS ,والمجلد الخاص به. ولكن يجب الانتباه جيداً فربما تكون تلك الجداول مستخدمه في تطبيقات أخري ,أو قد تكون هناك وظائف من التطبيق الحالي مستخدمة في باقي التطبيقات.
  6. لا يمكن الجزم بأمور تتعلق بالمستقبل فلا أحد يدري ما يخبأه غداً من تقنيات أو مفاجآت, ولكن Front-End برأيي مايزال موجود ومهم وربما الطلب كثيف حول العالم ولكن المسالة تتعلق بكثرة عدد مطوري الواجهة الأمامية Front-End , السبب الأخر والذي يجعل Front-End مهم وموجود هو التكامل بين أطر الويب و خدمات الويب web services أو API ,دعنا نعيد النظر قليلا في مهام مطور الواجهة الأمامية ونقسم عمله بشكل أعمق قليلاً, فمثلا التصميم هو جزء بسيط من العمل الموكل إلى مطور الFront-End ومن الممكن مؤخراً أن يتم إنجاز التصميم شخص أخر لا علاقة له بFrontEnd, نظراً لأنه مسؤول عن إرسال و إستلام الطلبات من وإلى الخادم أو api ,وربطه مع واجهة الموقع مثلا وعناصره المختلفة ,بالنظر إلى جزء هين من عمله وما يطلب منه يتضح أنه ليس من السهل الاستغناء عن كل شئ ,فمثلا تتنافس ريكآت وفيو react ,vue.js وغيرهم علي مكانة مميزة بين أطر الويب ,ولكن كلاهما يعتمد علي js وما يقدمانه هو مجرد تيسيير لعمل Front-End, إذا حدث واختفي أحد أطر الويب المهمة فمن المؤكد أن هناك بديل أفضل وأسهل منه قد ظهر ,وبالطبع يجب تعلم التنقل إلى الأدوات الأفضل و الأنسب لك والأنسب للعمل الذي تقوم به في كل زمان ومكان. وأيضا مسألة أخرى مهمة وهي عدد أطر الويب الموجودة حالياً والتنافس بينهم, وفي النهاية أعتقد بأن المجالات كافة تتغير بسرعة كبيرة للغاية ومن المؤكد أن مطور الواجهة الأمامية المتعارف عليه أصبح يمتلك وظائف ومهام مختلفة عن ذي قبل. ويجب علينا مواكبتها. بالتوفيق علي أي حال.
  7. يبدو الكود مكتمل بنسبة جيدة ولكن تحتاج إلى استيراد مكتبات أخرى في head أعني تحديداً jquery <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> ولكن أيضا لماذا تريد ان يتم إعادة توجيهك إلى صفحة أخري هنا؟ return render_template('start_page.html') لدي اقتراح آخر وهو استخدام صفحة واحدة فقط وإذا كان المستخدم يبحث فسيتم الرد ب json يحوي بداخله list المقترحات ,ويتم عرضها في جدول بسيط قابل للتحديث عند محاولة الكتابة في كل مرة وليس من خلال زر او Button, إليكم المثال التالي:ونبدأ ب main.py : #main.py from flask import (Flask, render_template, request, jsonify) from bs4 import BeautifulSoup import requests app = Flask(__name__, template_folder='template') @app.route('/search', methods=['GET', 'POST']) #إستلام الطلبات من جيت وبوست def suggest_data(): if request.method == 'GET' and request.args.get('jsdata'): #إذا كان هناك داتا في الطلب نفذ ما بداخل الشرط query = request.args.get('jsdata') if query == None: suggestions_list = ['',] else: suggestions_list = [] r = requests.get('http://suggestqueries.google.com/complete/search?output=toolbar&hl=ru&q={}&gl=in'.format(query), 'lxml') soup = BeautifulSoup(r.content) suggestions = soup.find_all('suggestion') for suggestion in suggestions: suggestions_list.append(suggestion.attrs['data']) return jsonify(data=suggestions_list) #إعادة الداتا كجسون وليس صفحة ويب آخري else: #إن لم يتحقق الشرط سيتم إعادة صفحة ويب وهي صفحة البحث return render_template('start_page.html') if __name__ == "__main__": app.run(debug = True) في كل الأحوال عند الدخول إلي الصفحة من خلال المتصفح سوف يرسلنا إلى render_template('start_page.html') والسبب هو عدم وجود jsdata إلا في حال تم الارسال من ajax. نأتي إلى صفحة start_page.html <!DOCTYPE HTML> <html> <head> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <!-->مهم إضافته</--> <title>Google Suggest Tool Flask</title> </head> <body> <h1>Search: Google Suggest Tool Flask</h1> <form action=""> <!--> من المهم إضاقة فورم لمستطيل البحث</--> <input id="search_input" type="text" name="typeing" placeholder="Country"> </form> <h1>Result</h1> <table id="myTable"></table> <!-->إنشاء جدول لعرض البيانات أو المقترحات</--> <script> $("#search_input").keyup(function(){ var some_var = $(this).val(); $.ajax({ url: "/search", //رابط دالة البحث type: "get", data:{jsdata: some_var}, success: function(response) { var res = response["data"]; //سحب المقترحات من الرد القادم من دالة البحث var table = document.getElementById("myTable"); / تهيئةالجدول لعرض الداتا //قبل العرض نقوم بحذف محتوي الجدول من عملية البحث السابقة while(table.rows.length > 0) { table.deleteRow(0); } //لووب علي المقترحات for (var a=0; a < res.length; a++) { //يتم إنشاء صف داخل الجدول لكل مقترح table.innerHTML += "<tr>"+"<td>"+a+"</td>"+"<td>"+res[a]+"</td>"+"</tr>"; } } }); }); </script> </body> </html> تابع النتائج التالية: كما ترى لا نحتاج إلى صفحة جديدة أو إعادة تحميل الصفحة الحالية لعرض البيانات القادمة. يمكنك التفكير في المزيد كعرض المقترحات ضمن text box وقائمة منسدلة تسهل عليك البحث ,انظر المثال التالي ستحتاج إلى مراجعة المصدر التالى "text box autocomplete" لمعرفة كيف يتم إنجاز بعض المهام من خلال css وقليل من js. موفقين.
  8. أجل يمكنك إضافة صفحات لعناوين url المجهولة والغير متاحة في مشروعك ,أو أي خطأ. تابع التالي أولا في ملف settings.py يجب إلغاء وضع التصحيح أو التطوير {Debugging}, من خلال تمرير False إلى DEBUG بدلا من True DEBUG = False ALLOWED_HOSTS = ['*'] # Application definition ثانيا يجب إنشاء ملفين html للأخطاء 404 و 500 في مجلد templates سنفترض أن أسمائهما كما يلى: 404.html 500.html لك كامل الحرية في محتوى تلك الصفحات ولكن إليك مثال بسيط لصفحة 404: <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title>CodePen - 404 Concept Page @property</title> </head> <body> <h1>404</h1> <div class="info"> <h1>Error: {{status}} </h1> <h2>We can't find that page</h2> <a href="/app" target="_blank">Go To Home</a> <!-->اذهب إلى الصفحة الرئيسية </--> </div> </body> </html> ثالثا إضافة دالتين إلي ملف views.py from django.shortcuts import render # Create your views here. def index(request): """دالة الصفحة الرئيسية """ return render(request, 'index.html') def error_404(request, exception): """دالة يتم تنفيذها في حال وجود خطأ404""" return render(request,'404.html', status=404) def error_500(request, *args, **argv): """نفس الدالة السابقة ولكن يتم تنفيذها في حال وجود خطأ يشير إلى الكود500""" return render(request, '500.html', status=500) #تأكد من كتابة اسم الملف أو القالب بشكل صحيح أخيرا ستقوم بإستدعاء هاتين الدالتين بداخل ملف urls.py الخاص بمشروعك ,أو تطبيقك ولكنه في كل الأحوال سيعمل. فيما يلي التعديل المطلوب في ملف urls.py from django.contrib import admin from django.urls import path from django.conf.urls import include, handler404 ,handler500 #إستدعاء لدوال مهم from myapp import views #استدعاء الفيو التي بداخلها الدوال التي أنشأنها urlpatterns = [ path('admin/', admin.site.urls), path('app/', include('myapp.urls')), ] #السطور المهمة handler404 = views.error_404 #يتم اسناد قيم الخطأ إلي الدالة 404 handler500 = views.error_500 #نفس الأمر ولكن لدالة 500 يمكن تجربة تخصيص صفحتي 404 و 500 بطرق مختلفة لكن هذه ربما الأقل تعقيداً, ومن المهم جداً أن تتذكر بأن صفحاتك المخصصة لن تظهر ومشروعك في وضع DEBUG يجب عليك تعطيله هكذا DEBUG = False من ملف الإعدادات كما وضحنا في البداية, وقد يطلب منك إعداد العناوين المسموح لها بزيارة موقعك ALLOWED_HOSTS , على أي حال قم بضبطها إلى ALLOWED_HOSTS = ['*'] النتائج ستكون كما يلي, بالتوفيق.
  9. بداية تعد session قاموس عادي أو Dictionary يمكنك التعامل مع محتواه علي هذا الأساس , فمثلا للوصول إلى request.session["name"] = "your Name" يمكنك تنفيذ print(request.session["name"]) ولكن بداخل القالب أو template سيتغير الحال قليلا إلى الشكل التالي: <h2> {{ request.session.name }} </h2> قد تواجه مشكلة عدم ظهور request بشكل عام داخل مشروع Django الخاص بك وهذا وارد في بعض إصدارات Django والسبب عدم التصريح بإستعمال request داخل template ولكن يمكنك حلها من خلال إضافة 'django.template.context_processors.request' إلي TEMPLATES بملف settings.py الخاص بك لتبدو مثلا هكذا settings.py TEMPLATES = [ { 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'APP_DIRS': True, 'OPTIONS': { 'context_processors': [ .... بالتأكيد هناك خيارات أخري 'django.template.context_processors.request', السطر الذي نريد اضافته 'django.contrib.auth.context_processors.auth', ..... ], }, }, ] ثم اعد تجربة <h2> {{ request.session.name }} </h2>
  10. افتراضيا تقوم flask بدعم ASCII في الطلبات الخاصة بها وهو المتسبب في ظهور بعض اللغات التي تكتب من اليمين لليسار بالشكل الذي أشرت إليه في سؤالك, لذا إذا كنا نريد استخدم jsonify من flask فكل ما علينا فعله هو تعطيل استخدام ASCII , من خلال app.config['JSON_AS_ASCII'] = False ثم إكمال كودك كما تريد علي سبيل المثال , from flask import (Flask, render_template, jsonify) app = Flask(__name__, template_folder='template') app.config['JSON_AS_ASCII'] = False @app.route('/test', methods = ['POST']) def test_fun(): req = 'მოითხოვეთ' return jsonify(data=req) if __name__ == "__main__": app.run(debug = True) لن تكون هناك مشكلة سواء أضفت u إلي السلسة النصية أو لا فالنتيجة علي اي حال ستكون { "data": "მოითხოვეთ" } استخدم PostMan او curl فالنتيجة ذاتها, curl -X POST http://localhost:5000/test
  11. بداية السؤال مشتت لماذا تسلك طريق معقد لشرح ما تريد في حين يمكنك استبدال السؤال بأخر بسيط وهو: الإجابة هنا أنت لست بحاجة إلى مشاركته فإذا عدنا إلى الشرط المعروف والذي نكتبه عادة في المشاريع للتأكد من تنفيذ شئ ما أثناء تشغيل ملف بعينه وهو: if __name__ == "__main__": #app.run(debug = True) يتضح لنا أن الملف الرئيسي يظهر دائما تحت المسمى __main__ مما يعني أن بالإمكان استيراد اي شئ من الملف الرئيسي داخل ملفات المشروع الفرعية, علي سبيل المثال سيكون app موجود داخل الملف الرئيسي دائما فيمكننا إستيراده من خلال: from __main__ import app ثم تعيد استيراد الملفات من داخل الكود الرئيسي , ولكن بعد الإعلان: app = Flask(__name__) فيما يلي مثال لمشروع يحتوي على ملفين منفصلين عن الملف الرئيسي 1- error_app.py #error_app.py from flask import (request, jsonify) from __main__ import app app.config['TRAP_HTTP_EXCEPTIONS']=True def error_Response(code, name): shortname = name.lower().replace(' ', '_') error = {'error':{}} error['error']['title'] = 'App | {0}'.format(name) error['error']['page'] = request.url error['error']['name'] = name error['error']['code'] = code return jsonify(error) @app.errorhandler(Exception) def handle_error(e): try: if e.code < 400: return flask.Response.force_type(e, flask.request.environ) elif e.code == 404: return error_Response("Page Not Found", "The page you're looking for was not found") raise e except: return error_Response("Error", "Something went wrong") 2- ajax_req.py #ajax_req.py from flask import (request, jsonify) import requests from __main__ import app URL = 'https://example.com/test' @app.route('/from_ajax', methods = ['POST']) def ajax_request(): req = requests.get(URL).text return jsonify(data=req) 3-main.py #main.py from flask import (Flask, render_template) app = Flask(__name__, template_folder='template') #يجب إضافة الملفات بعد الاعلان عن الكائن الذي يتم استخدامه بداخلها #اقصد app #وجود الإستدعاء قبل ذلك سيؤدي لظهور اخطاء import error_app import ajax_req @app.route('/') def index(): return render_template('send_from_ajax.html') if __name__ == "__main__": app.run(debug = True) لذا أنت لست بحاجة لأي إجراء أخر للتعامل مع مشروع مترامي الأطراف والذي يمكن أن يحتوي على شجرة ملفات متعددة ,فقط أليات بسيطة تكون كافية. بالتوفيق
  12. يمكنك تحويل جميع الأخطاء داخل flask إلي دالة تتحكم في شكل ومحتوي الرد أو Response , يتم انشاء دالة او Function لهذه المهمة @app.errorhandler(Exception) علي شكل استثناء يظهر في حال الدخول إلي عناوين خاطئة أو حدوث مشكلة جوهرية بأي وظيفة داخل مشروعك, في البداية ستبني دالة يتم تنفيذها مباشرة عند الاستثناء @app.errorhandler(Exception) def handle_error(e): try: if e.code < 400: return flask.Response.force_type(e, flask.request.environ) elif e.code == 404: return error_Response("Page Not Found", "The page you're looking for was not found") raise e except: return error_Response("Error", "Something went wrong") ثم دالة اخري تقوم بصياخة الخطأ الذي يتم اظهاره أو ارساله وهي error_Response, يمكنك التحكم في كل ما بها بحسب ما تريد, def error_Response(code, name): error = {'error':{}} error['error']['title'] = 'App | {0}'.format(name) error['error']['page'] = request.url error['error']['name'] = name error['error']['code'] = code return jsonify(error) ستبدو رسالة الخطأ كما يلي في حال صفحة خاطئة أو url غير موجود, وفيما يلي شكل الخطأ في حال وجود مشكلة في دالة أو وظيفة ما, لا تنسى إضافة TRAP_HTTP_EXCEPTIONS إلي app.config بالشكل التالي , app.config['TRAP_HTTP_EXCEPTIONS']=True سيبدو دمج الدالتين في مشروع حقيقي بالشكل التالي,, from flask import (Flask, render_template, request, jsonify) import requests URL = 'https://mm.com/test' app = Flask(__name__, template_folder='template') app.config['TRAP_HTTP_EXCEPTIONS']=True def error_Response(code, name): shortname = name.lower().replace(' ', '_') error = {'error':{}} error['error']['title'] = 'App | {0}'.format(name) error['error']['page'] = request.url error['error']['name'] = name error['error']['code'] = code return jsonify(error) @app.errorhandler(Exception) def handle_error(e): try: if e.code < 400: return flask.Response.force_type(e, flask.request.environ) elif e.code == 404: return error_Response("Page Not Found", "The page you're looking for was not found") raise e except: return error_Response("Error", "Something went wrong") @app.route('/') def index(): return render_template('send_from_ajax.html') @app.route('/from_ajax', methods = ['POST']) def ajax_request(): req = requests.get(URL).text return jsonify(data=req) if __name__ == "__main__": app.run(debug = True) يمكنك دائما إجراء تغيرات علي دالة error_Response لكي تفسر الخطأ القادم إليك من flask دون الحاجة إلي الوصول لخط التشغيل او command flask ,هذه كانت فقط بذرة,, بالتوفيق إن شاء الله
  13. علامة الزائد أو + ليس لها علاقة بكود أو استعلام sql الذي تم تحويله إلى js ولكن سبب وجودها هو دمج السطر الأول مع السطر الثاني ,فبرمجيا يمكن جمع السلاسل النصية دون مشكلة كما في المثال التالي: var text_A = 'one day'; var text_B = 'from any week'; let total = text_A + text_B; والناتج one dayfrom any week ولا مشكلة من تكرار ذلك عدة مرات أو حتي عدم استخدام var في الاعلام يمكن جمع السلاسل النصية بالشكل التالي: فالسبب وراء كتابته + أنه اراد تقسيم الاستعلام أو كود sql الطويل نسبيا على عدة سطور, وجعله سهل القراءة دون الحاجة إلي التمرير افقيا مع السطور الطويلة, بإختصار ما تقوم به + هي دمج السلسلتين معاً, ويمكنك تقسيمه إلى أكثر من ذلك لاحظ المثال التالي: db.all('Comments.flame, Comnents.Content,' + ' rticle.ArticleName,Article.Date' + ' from Coments inner join Article' + ' on Connents.ArticleId = Article.ArticleId', function(err, teble){ if(err){ return console.log(err.message); } console.log(table); } ); فقط ركز علي المسافات وتجنب مثلا ان يتم كتابة التالي نلاحظ أن Datefrom تم دمجهما في حين أنه يجب وجود مسافة بينهما Date from, لهذا في بداية كل سلسلة تجد أننا نضيف مسافة فارغة داخل علامتي التنصيص ,وبالطبع تختلف الحالات بإختلاف الشئ الذي نريد القيام به. وايضا لا فرق إن كتبت السطر كاملا: db.all('Comments.flame, Comnents.Content,rticle.ArticleName,Article.Date from Coments inner join Article on Connents.ArticleId = Article.ArticleId', function(err, teble){ if(err){ return console.log(err.message); } console.log(table); } ); الكود المستخدم في الصور يمكن رؤيته واختباره هنا https://jsfiddle.net/v9oa68r1/
  14. بدلا من ذلك فكر في حل المشكلة المتعلقة ب ajax فكر في اختصار تلك الحلقة وزمن تنفيذها , قد تكون المشكلة متعلقة بنوع البيانات dataType المعلن عنها في طلبك على سبيل المثال يمكنك إرفاق التالي: dataType: 'json' //OR dataType: 'jsonp' إلى الطلب الخاص بك. أيضا تحتاج إلي إضافة CORS لطلبك وربما إلى: "Access-Control-Allow-Origin" ولا تزال هناك خيارات وحلول أخرى, وبالطبع لا يمكننا معرفة الحل الأمثل بدون رؤية الطلب الذي تقوم بإرساله,والخطأ الذي يواجهك. ومع ذلك قد تكون الأخطاء التي تواجهك عن ارسال طلب إلي موقع او خادم آمن https من خلال عنوان غير آمن,, تعد CORS مهمة في هذا الشأن, بإختصار تدعم آلية CORS الطلبات عبر المصدر الآمن ونقل البيانات بين المتصفحات والخوادم. أما عن تنفيذ الفكرة التي تفكر بها ,ففيما يلي مثال على تنفيذها, 1-: send_from_ajax.html <!DOCTYPE HTML> <html> <head> <title>Send from AJAX Teo Flaskt</title> <script> function getData() { var req = new XMLHttpRequest() req.onreadystatechange = function() { if (req.readyState == 4) { if (req.status != 200) { //error handling code here } else { var response = JSON.parse(req.responseText)//يمكنك الاستفادة من الرد في اي شئ اخر document.getElementById('testdiv').innerHTML = response.data } } } req.open('POST', '/from_ajax') req.setRequestHeader("Content-type", "application/x-www-form-urlencoded") req.send('test') return false } </script> </head> <body> <h1>Send from AJAX Teo Flask</h1> <form action="" method="POST"> <input type="button" value="Send request" onclick="return getData()"> </form> <h1>Result</h1> <div id="testdiv"></div> </body> </html> 2-: main.py from flask import (Flask, render_template, jsonify) import requests app = Flask(__name__, template_folder='template') URL = 'https://example.com/test' @app.route('/') def index(): return render_template('send_from_ajax.html') @app.route('/from_ajax', methods = ['POST']) def ajax_request(): req = requests.get(URL).text return jsonify(data=req) if __name__ == "__main__": app.run(debug = True) وستجد في المرفقات صوراً للنتيجة ويمكن استخدام response الموجودة في طلب ajax في اي عملية اخرى,او اختبار آخر والعكس صحيح اي إرسال url من خلال طلب اجاكس يتم معالجته من خلال flask واعادة ارسال الناتج إلي ajax والذي يتولى مسؤولية عرضه داخل الصفحة الخاصة بنا.. ومع هذا قد لا تكون طريقة منطقية او مناسبة اللهم في حالات مختلفة تتشابه مع مفاهيم vpn أو بالأحري Proxy, بمعنى أننا قد نحتاج الى إرسال طلب ما إلي خادم او موقع محظور على مستخدمينا الوصول إليه ,فهنا يمكن تثبيت flask على خادم مسموح له بالوصول إلى الموقع أو الخادم المحظور بينما نرسل نحن أو المستخدمين فقط إلى flask ونتلقى النتائج من خلاله ذات الصفحة على المتصفح دون الحاجة إلى proxy وما شابه. بالتوفيق
  15. المشكلة تكمن حول الرد الذي يعود بعد تنفيذ requests.post حيث تعيد post كائن من النوع ```requests.models.response``` ,بينما يجب أن يكون الرد النهائي للدالة hi person والتى نخاطبها إما str أي سلسلة نصية او json ,يمكننا اعادة أي منهما ولكن التعديل التالي يعيد string من خلال إضافة .text للرد القادم من post. from flask import Flask, url_for, request import requests app = Flask(__name__) @app.route("/<name>/hello", methods=["POST", "GET"])#يسمح لك بالتجربة من المتصفح GET هذه ليست ضرورية لكن اضافة def hi_person(name): result = requests.post(url_for("hello", _external=True), data={"name": name}) return result.text #.text يجب ان يكون الرد اما سلسة نصية أو جسون لهذا أضفنا @app.route("/hello", methods=["POST"]) def hello(): return 'Hi, ' + request.form["name"] if __name__ == "__main__": app.run(debug=True) أما عن سبب إضافة GET فهو إذا أردت تجربة الطلب من خلال المتصفح , ويمكن إجراء الطلب GET و POST من خلال postman أو curl GET curl -X GET http://localhost:5000/ahmed/hello POST curl -X POST http://localhost:5000/glal/hello موفق
×
×
  • أضف...