
English: 
[MUSIC PLAYING]
DAVID MALAN: All right.
This CS50 and this is
lecture 7 wherein we pick up
where we left off last time
in talking more about Python,

Arabic: 
[MUSIC PLAYING]
ديفيد مالان: حسنًا.
هذه هي دورة CS50 وهذه هي
المحاضرة 7 حيث نستكمل
ما توقفنا عنده آخر مرة
في حديثنا بشكل أكبر عن Python،

Arabic: 
لكن هذه المرة باستخدام Python
لأغراض قوية أكثر،
جناس لم أكن أعنيه
حتى قلته هناك فقط.
لكن الهدف من Python
هنا الآن هو استخدام هذه
اللغة بالفعل لإنشاء لغة
أخرى، وتحديدًا HTML.
وما سنقوم به هو البدء في توفير
كل ما هو موجود بدرجة أكبر عن النموذج العقلي
لما تطلقون عليه
فصل المخاوف، حيث إنكم
عندما تقومون بتصميم موقع ويب تم إنشاؤه
بشكل أكثر تعقيدًا، أو بالأحرى عندنا تصممون
برنامجًا أكثر تعقيدًا، فأنتم
تحاولون تبنّي أنماط تصميم معينة حتى
لا تقوموا فقط بكتابة كل شيء 
في ملف واحد كبير الأمر الذي
يصبح مربكًا قليلاً، وغير عملي
للاحتفاظ به وللإضافة إليه مع مرور الوقت.
ولكنكم تبدؤون في فصل
المخاوف، وخاصية الدالة،
والميزات الخاصة بكم، 
وعمل المتعاونين
في ملفات مختلفة
ومنهجيات مختلفة.
ولذلك سنحاول تقديم بعض
هذه النُهج القياسية في مجالاتها اليوم
والسبب وراء أنها تقوم بحل المشاكل بالفعل.
لكن، بالطبع، كيف وصلنا إلى هنا؟
منذ بضعة أسابيع، تحدثنا
عن هذا الشيء،
هذا الظرف الافتراضي
الذي يمثل تحديدًا
حِزم المعلومات، الأصفار والواحدات،
التي تمر عبر الإنترنت من النقطة أ
إلى النقطة ب. وبين الرسائل
الموجودة في هذه الأظرف
قد يكون هناك لأجل طلبات الويب.

English: 
but this time using Python for
even more powerful purposes,
an alliteration I didn't intend
until I just said it there.
But the goal here with
Python now is to actually use
this language to generate another
language, in particular HTML.
And what we'll do is start to provide
all the more of a mental model
for what you would call
separation of concerns, whereby
when you design more complicated
web based, or rather when you design
more complicated software, you tend to
try to adopt certain design patterns so
that you're not just writing
everything in one big file that
gets a little confusing, unwieldy
to maintain and to add to over time.
But you start to separate your
concerns, and your functionality,
and your features, and
your collaborators' work
into different files and
different methodologies.
So we'll try to give you some of these
industry standard approaches today
and why they actually solved problems.
But, of course, how did we get here?
A few weeks ago, we
talked about this thing,
this virtual envelope
that just represents
packets of information, zeros and ones,
going across the internet from point A
to point B. And among the
messages in these envelopes
might be for web requests.

Arabic: 
وتحدثنا عن بروتوكول HTTP،
بروتوكول نقل النص التشعبي،
الذي يقوم بإرسال رسالة
كهذه داخل الظرف.
وهذا، بالطبع، يطلب من
الصفحة الافتراضية
لموقع ويب حسبما يلمّح الخط المائل.
وفي كثير من الحالات، ولكن
ليس دائمًا، يشير هذا إلى
اسم ملف افتراضي يُدعى index.html.
ولكن هذا تقليد
بشري، وليس مطلوبًا.
يستجيب الخادم، كما نأمل، 
بتعليمة برمجية رقمية تساوي أي عدد صحيح؟
200، كما نأمل، رقم
لم نره مطلقًا في الواقع
ما لم تصبحوا
أكثر اعتيادًا عليه
وتبدؤوا في التدقيق بحثًا
في مركز تحكم Chrome
وتلقوا نظرة على حركة بيانات الشبكة الخاصة بكم.
حسنًا.
إذن توجد هنا استجابة 
ناجحة فعلية،
وهي تعني أن كل شيء على ما يرام بالفعل.
وإذا كان المتصفح يبدو متجهًا للأسفل
قليلاً في الظرف الافتراضي،
إذا صح التعبير، فسترون لغة
أخرى تُسمى HTML، لغة ترميز النص
التشعبي، وهي المجموعة
التي كتبناها منذ أسبوعين
وستستمرون في كتابته هذا الأسبوع كما
تقومون الآن بإنشاء مواقع ويب بشكل ديناميكي.
ولكن ما سنقوم بتقديمه اليوم هو
ما يُعرف أيضًا بإطار عمل،
أو، على وجه أكثر دقة، إطار عمل صغير،
لأننا سنرى بعد بضع دقائق فقط

English: 
And we talked about HTTP, a protocol,
hypertext transfer protocol,
that just sends message like
this inside of the envelope.
And this is requesting, of
course, the default page
of a website as implied by the slash.
And in many cases, but
not always, this implies
a default file name of index.html.
But that's a human
convention, not a requirement.
Hopefully, the server responds with
a numeric code equal to what integer?
200, hopefully, a number
that we never actually
really see unless you
get more comfortable
and start poking around
Chrome's inspector
and you look at your network traffic.
Right.
So here is an actual
successful response,
which means everything is indeed OK.
And if the browser looks a little
farther down in the virtual envelope,
if you will, it will see another
language called HTML, HyperText Markup
Language, which is the stuff
we wrote a couple of weeks ago
and you'll continue writing this week as
you now dynamically generate websites.
But what we'll introduce today is
what's also known as a framework,
or, more precisely, a microframework,
because we'll see in just a few minutes

English: 
time that it can actually be
really annoying and really tedious
to generate websites
automatically using Python
if you have to write Python code alone.
And so humans, over
the past several years,
have noticed, wow, every time I
make a web application using Python,
I find myself typing
the same lines of code
again and again just to get started,
or when I'm collaborating with someone
else, I find that, ooh, it's
a little hard to collaborate
if we're all working in the same file.
So humans have invented
what are called frameworks.
And this is an example
of code written in Python
but using a framework called Flask.
So whereas Bootstrap, which
you've played with a little bit,
is a framework for CSS and JavaScript,
they have some dynamic features
as well, Flask is a
framework for Python that
just gives you some library
code that you can use freely
in your own applications.
And it just makes it, ultimately, a
little easier to get your work done
and build the thing you
want to build as opposed
to having to reinvent the wheel again
and again like people before you.

Arabic: 
أنه يمكن أن يكون الأمر في الواقع 
مزعجًا ومملاً حقًا
لإنشاء مواقع ويب
بشكل تلقائي باستخدام Python
إذا تعيّن عليكم كتابة تعليمة Python البرمجية فقط.
وهكذا لاحظ الأشخاص، خلال
السنوات العديدة الماضية،
ويا للدهشة، في كل مرة أقوم فيها
بإنشاء تطبيق ويب باستخدام Python،
أجد نفسي أكتب
سطور التعليمة البرمجية نفسها
مرارًا وتكرارًا فقط لكي أبدأ،
أو عندما أتعاون مع شخص
آخر، أكتشف أنه، أوه، من
الصعب قليلاً التعاون
إذا كنا نعمل جميعًا في نفس الملف.
لذلك فقد اخترع أشخاص
ما يُسمى بأُطُر العمل.
وهذا مثال عن تعليمة
برمجية مكتوبة في Python
ولكن باستخدام إطار عمل يُسمى Flask.
إذن فبينما يعدّ Bootstrap، الذي
قمتم بتشغيله منذ قليل،
عبارة عن إطار عمل للغتي CSS وJavaScript،
وهما تحتويان على بعض الميزات الديناميكية
أيضًا، فإن Flask عبارة عن إطار
عمل من Python
يمنحكم فقط تعليمة برمجية معينة للمكتبة
التي يمكنكم استخدامها بحرية
في التطبيقات الخاصة بكم.
وهو تحديدًا يسهّل قليلاً، في نهاية المطاف، 
إنجاز عملكم
وإنشاء الشيء الذي
تريدون إنشاءه بدلاً من
الحاجة إلى إعادة اختراع العجلة مرارًا
وتكرارًا مثل الأشخاص الذين كانوا من قبلكم.

Arabic: 
وإذن فإليكم هنا منهجية
أشرتُ إليها ﻓﻲ وقت سابق ليكون لديكم
تحديدًا نموذج عقلي للأسابيع القادمة.
لذلك فإلى الآن، يبدو إلى حد
كبير أن كل برنامج
قمنا بكتابته في لغة C 
وحديثًا جدًا في Python
يمكنك تسميته كتعليمة وحدة التحكم البرمجية
أو منطق وحدة التحكم أو منطق العمل.
حسنًا.
يتعلق الأمر كله بالحصول على
شيء تم إنهاؤه بشكل منطقي،
عادةً في ملف واحد، وربما ملفين إذا
كان لديكم helpers.ce أو ملف
رأس أو أي شيء.
لكن لقد كنا نكتب المنطق.
ولكن اليوم ومنذ أسبوعين
عندما ركزنا
على برمجة الويب في HTML وCSS،
يوجد الجزء الثاني من عالمنا.
يوجد المنطق الذي يُنهي
العمل المثير للاهتمام باستخدام التكرارات الحلقية،
والشروط، وكل ذلك.
ولكن توجد أشياء ستصبح أيضًا
الآن من الجماليات،
الشيء الذي يشاهده المستخدم بالفعل
والطريقة التي تعرض بها بياناتك.
لذلك سنقوم فقط بتقديم 
حرفين من اختصار
اليوم وننتقل بعد ذلك.
في أي وقت تبدأون فيه بكتابة
تعليمة برمجية منطقية في Python،
ستقوم باستدعاء وحدة التحكم الخاصة بك.
إنها مثل الآلة التي تُشغّل
تطبيق الويب الخاص بك بالكامل،
ولكن في أي وقت تفعل فيه
شيء جمالي أكثر،

English: 
And so here is a methodology to
which I alluded earlier just to have
a mental model for the coming weeks.
So up until now, pretty
much every program
we've written in C and
most recently in Python
you could call like controller code
or controller logic or business logic.
Right.
It's all about getting
something done logically,
usually in one file, maybe two files if
you have another helpers.ce or header
file or whatnot.
But we've been writing logic.
But today and two weeks
ago when we will focus
on web programming in HTML and CSS,
there's the second part of our world.
There's like the logic that gets the
interesting work done with loops,
and conditions, and all that.
But there's also now going
to be the aesthetics,
the stuff that the user actually sees
and the way you present your data.
So we're going to just introduce
two letters of an acronym
today moving forward.
Anytime you start writing
logical code in Python,
it's going to be called your controller.
It's sort of like the machine that
operates your entire web application,
but anytime you do
something more aesthetic,

English: 
we're going to call that your view
code, so C and V being the letters here.
And this just refers to
a separation of concerns.
Your logic goes in this file.
And your aesthetics and
formatting go in this other file.
Next week, we'll introduce databases
in SQL, structured query language.
And we'll introduce an M here,
because the acronym that's
in vogue for quite some time
now is MVC, though there
are alternatives to this mental model.
And that just means there
are three different types
of things you should be thinking
about when building an application.
But today we're going to focus on
these two, controller and view.
And up until now, we've pretty much
been doing entirely controller stuff
when writing code.
So the motivation, ultimately, will
be to get to the point of building,
essentially, this, the freshman
intramural sports website,
which I was the first one to
make back in 1996 as a sophomore,
maybe 1997 as a junior, after
having only taken CS50 and a follow
on class CS51.
And even though this is horrifying
to see nowadays, underneath the hood
was a whole bunch of controller logic
and a whole bunch of model code,

Arabic: 
سنقوم باستدعاء تعليمة عرضك البرمجية،
إذن C وV هما الحرفان هنا.
وهذا يشير فقط إلى
فصل المخاوف.
سينتقل منطقك إلى هذا الملف.
والجماليات والتنسيق
في هذا الملف الآخر.
في الأسبوع القادم، سنقدم قواعد البيانات
في SQL، لغة استعلام محدّدة.
وسنقدم M هنا
لأن الاختصار الرائج
لبعض الوقت إلى حد كبير
الآن هو MVC، على الرغم من وجود
بدائل لهذا النموذج العقلي.
وهذا يعني فقط وجود
ثلاثة أنواع مختلفة
من الأشياء التي يجب أن تفكروا 
فيها عند إعداد تطبيق.
ولكننا اليوم سنركز على
هذين الأمرين، وحدة التحكم والعرض.
وحتى الآن، قمنا بإجراء
أشياء كثيرة خاصة بوحدة التحكم بالكامل
عند كتابة تعليمة برمجية.
إذن الدافع، في النهاية، سيكون
الوصول إلى المغزى من الإنشاء،
بشكل أساسي، هذا، موقع الويب
للرياضات الداخلية للطلاب الجدد،
حيث كنت أول شخص قام بإعادة الإنشاء
في عام 1996 كطالب في السنة الثانية الجامعية،
ربما 1997 كطالب في السنة الثالثة الجامعية،
بعد الحصول على دورة CS50 فقط ومتابعة
صف CS51.
وعلى الرغم من أنه من المروع
رؤية ذلك هذه الأيام، وبشكل غير ظاهر
كانت توجد مجموعة كاملة من منطق وحدة التحكم
ومجموعة كاملة من تعليمة النموذج البرمجية،

English: 
even though I don't think
MVC existed as an acronym
back then till humans
figured out the pattern.
But what it did have via the menu up
here was a whole lot of functionality.
So no longer did you have to walk
across campus filling out a form
and drop off a sheet of paper in
an RA or a proctor's dorm room.
You can instead just go on the web,
which all of us surely take for granted
today, fill out a web-based form.
And then at the time, the
proctor in charge of froshims
would get an email confirming who
had actually registered for a sport.
And eventually we added CSV
files, comma separated values
files like spreadsheets, in
which the data was saved.
Then we had this really
cool tournament bracket
thing, which was all very dynamic
and impressive I'm sure at the time.
But we'll focus on really
just the fundamentals today.
So how do we get there?
Well, let me go ahead
and open up CS50 IDE
and propose that if we want
to make a website, a web
application really, and by application
I mean something that does have logic.
By website, it's generally
something that's static.
So that's what a web app is.
It's something that changes based on
who's using it, when you're using it,
and what you're doing with it.

Arabic: 
حتى على الرغم من أنني لا أعتقد أن
MVC موجودة كاختصار
في ذلك الوقت حتى
اكتشف أشخاص النمط.
ولكن ما كانت تحتويه خلال القائمة في
الأعلى هنا هو مجموعة كاملة من الدالات.
إذن لا يجب أن تسيروا بعد الآن
في الحرم الجامعي لملء نموذج
وتسليم ورقة في
RA أو غرفة سكن المراقب.
يمكنكم بدلاً من ذلك الانتقال فقط إلى الويب،
الذي نعتبره جميعًا أمرًا مسلمًا به بالتأكيد
اليوم، املأ نموذجًا قائم uلى الويب.
ثم بعد ذلك، سيتلقى
المراقب المسؤول من froshims
رسالة بريد إلكتروني تؤكد مَن
الذي قام بالتسجيل للرياضة بالفعل.
وأخيرًا قمنا بإضافة ملفات
CSV، ملفات قيم مفصولة
بفاصلة مثل جداول البيانات، حيث
يتم حفظ البيانات.
ثم كان لدينا أمر
قوس الجولة الرائع،
الذي كان ديناميكيًا ومثيرًا
للإعجاب جدًا أنا متأكد أنه كان كذلك.
لكننا سنركز بالفعل على
الأساسيات فقط اليوم.
إذن كيف توصلنا لذلك؟
حسنًا، دعوني أمضي
قدمًا وأفتح CS50 IDE
وأقتراح أننا إذا كنا نريد
إعداد موقع ويب، تطبيق
ويب حقًا، وبقول تطبيق
أعني به شيئًا يحوي على منطق.
وبقول موقع ويب، إنه
شيء ثابت بشكل عام.
إذن هذا ما يكون عليه تطبيق الويب.
إنه شيء يتغير بناء على
مَن يستخدمه، ومتى تستخدمه،
وماذا تفعل باستخدامه.

Arabic: 
دعوني أمضي قدمًا، وبأكثر
طريقة مملة ومزعجة ممكنة،
أقوم بتنفيذ تطبيق الويب
باستخدام Python.
إذن سأمضي قدمًا وأفتح ملف
يسمى serve.pie لتقديم موقع ويب.
وسأمضي قدمًا وأقوم باستيراد
بعض تعليمة المكتبة البرمجية.
إذن من خادم HTTP، قم باستيراد شيء
يُسمى معالج طلب HTTP الأساسي
وشيء يُسمى خادم HTTP أيضًا.
ومن ثم سأمضي قدمًا واستخدم
فئة الكلمة الأساسية هذه، وهي
خادم HTTP، طلب الخادم، معالج
الطلب، معالج طلب HTTP الأساسي--
معالج.
ثم سأمضي قدمًا
وأقوم هنا بتنفيذ
دالة تُسمى def
do_GET، والتي تشير إلى--
هذه هي دالة في Python حيث يجب أن
يتم استدعاؤها في أي وقت يقوم فيه
مستخدم بزيارة خادم الويب الخاص بي عبر
GET، نوع الفعل
الذي تحدثنا عنه
في سياق الويب.
إذن لنفترض أن هدفي
الوحيد هنا هو إنشاء

English: 
Let me go ahead, and in the most
annoying tedious way possible,
implement a web
application using Python.
So I'm going to go ahead and open a file
called serve.pie to serve up a website.
And I'm going to go ahead
and import some library code.
So from HTTP server, import something
called base HTTP request handler
and also something called HTTP server.
And then I'm going to go ahead
and use this keyword class, which
is HTTP server, server request, request
handler, base HTTP request handler--
handler.
Then I'm going to go ahead
and in here implement
a function called def
do_GET, which implies--
this is a function in Python that
should be called anytime a user
visits my web server via
GET, the type of verb
that we've talked about
in the context of the web.
So suppose that my only
goal here is to make

English: 
a web-based application that for
the moment just says hello world.
We know how to do this with HTML,
but with HTML that's just a file.
Let's write a program that
not just prints hello world,
but generates a web page
containing hello world.
So the way I might do this is this.
I can literally say self, because self
refers to the web server in this case.
And I can go ahead and send
a response code of 200,
just kind of presumptuously
assuming everything's
going to be OK in a moment.
Then I'm going to go ahead
and send a header, which
recall, we've discussed
briefly in the past,
whereby this header is going to
be content type and its value
is going to be text HTML,
which is a clue to browser
that it's receiving not a GIF,
or JPEG, or something else,
but an actual HTML page.
And then I'm going to go ahead
and say that's it for the headers.
I'm going to call function
called end headers.
And then lastly, I'm
going to use Python code
to dynamically generate my website.
Now, what does the website have to have?
Just hello world at the end of the
day, but there's a whole bunch of html
we need to do in order
to get to that point.

Arabic: 
تطبيق قائم على الويب يقول في الوقت الحالي
فقط مرحبًا بالعالم.
نحن نعلم كيفية القيام بذلك باستخدام HTML،
ولكن باستخدام HTML هذا مجرد ملف.
دعونا نكتب برنامجًا لا
يقوم بطباعة مرحبًا fالعالم فقط،
ولكن يقوم بإنشاء صفحة ويب
تحتوي على مرحبًا بالعالم.
إذن الطريقة التي قد أقوم بذلك بها هي هذه.
يمكنني أن أقول حرفيًا ذات، لأن ذات
تشير إلى خادم الويب في هذه الحالة.
ويمكنني أن أمضي قدمًا وأقوم
بإرسال تعليمة الاستجابة البرمجية من 200،
مجرد افتراض بشكل اجترائي
إلى حد ما أن كل شيء
سيكون على ما يرام بعد قليل.
بعد ذلك سأمضي قدمًا
وأقوم بإرسال رأس، كما
تذكرون، قد ناقشناها
بشكل موجز في الماضي،
حيث ستكون هذه الرأس
نوع المحتوى وستكون
قيمته هي نص HTML،
والذي يُعد دليل على أن المتصفح
لا يتلقى GIF، أو
أو JPEG، أو أي شيء آخر،
لكن صفحة HTML الفعلية.
ثم سأمضي قدمًا وأقول هذا
كل شيء بشأن الرؤوس.
سأقوم باستدعاء دالة
تسمى رؤوس النهاية.
ومن ثم في النهاية، سأستخدم
تعليمة Python البرمجية
لإنشاء موقع الويب الخاص بي بشكل ديناميكي.
الآن، ما الذي يجب أن يحتوي عليه موقع الويب؟
فقط مرحبًا بالعالم في نهاية
اليوم، ولكن هناك مجموعة كاملة من html
نحتاج إلى القيام بها من أجل
الوصول إلى تلك المرحلة.

Arabic: 
لذلك سأستخدم دالة
تُسمى wfile
لكتابة ما يلي.
دعوني أمضي قدمًا وأكتب doctype--
عذرًا، علامة تعجب doctype HTML.
ثم دعوني أمضي قدمًا وأفعل الأمر
نفسه، wfile.write، دعوني أمضي قدمًا
وأقوم بلصق ونسخ هذا وبعد ذلك،
هذا، بالطبع، يكون دائمًا
حدس سيئ.
ثم دعوني أمضي قدمًا وأقوم بإخراج
لغة HTML تساوي en للغة الإنجليزية.
ولاحظوا أنني أستخدم علامة اقتباس 
واحدة داخل علامتي الاقتباس
وبذلك لا يختلط الأمر على Python.
بعد ذلك دعوني أمضي قدمًا وأقوم
بإخراج علامة الرأس هنا.
ثم ما الذي يأتي بعد 
علامة الرأس عادة؟
نعم، عادة ما يأتي العنوان مؤخرًا.
إذن سيكون العنوان مثل
مرحبًا أيها العنوان، أغلق علامة العنوان.
والآن سنمضي قدمًا
وما الذي يأتي بعد العنوان؟
أغلق الرأس، كما أعتقد، إذا
كنت أفعل ذلك بشكل صحيح.
ومن ثم من المحتمل
أن لدينا بنية.
ثم يا إلهي، هذه أسوأ 
طريقة لإنشاء موقع الويب.

English: 
So I'm going to use a function
called wfile write in order
to write out the following.
Let me go ahead and write out doctype--
whoops, exclamation point doctype HTML.
Then let me go ahead and do the same
thing, wfile.write, let me go ahead
and copy paste this moving forward,
which, of course, is always
a bad instinct.
Then let me go ahead and output
HTML lang equals en for English.
And notice I'm using single
quotes inside my double quotes
so that Python doesn't get confused.
Then let me go ahead and
output head tag here.
Then what comes after
the head tag typically?
Yeah, so usually title lately.
So title will be like hello
title, close the title tag.
And now we're going to go ahead
and what comes after title?
Close head, I think, if
I'm doing this right.
And then after this we
probably have a body.
And then oh my God, this is the
worst way to build a website.

English: 
But let's go ahead and now say
something simple like hello world.
And now let's go in here
and say something like body.
And then finally, let's go ahead
and end the page and say slash HTML.
Done.
OK, and now I actually need to configure
the server to listen on a port.
So let me go ahead and define a TCP
port of 8080, which we've been using.
Let me go ahead and define
the server's address as being,
oh 0.0.0.0, which is what the IDE uses
by default, like a lot of servers.
And then let me create the
web server, HTTP server.
server_address HTTP server request
handler, httpd.serve_forever.
OK, that is how you make a
web-based application that
dynamically generates HTML.
In retrospect, I really regret typing
all of that out because the whole point
now is to throw this code away.
Like, this is why frameworks exist.

Arabic: 
ولكن دعونا نمضي قدمًا ونقول الآن
شيئًا بسيطًا مثل مرحبًا بالعالم.
والآن دعونا ننتقل إلى هنا
ونقول شيئًا مثل البنية.
ومن ثم في النهاية، دعونا نمضي قدمًا
وننهي الصفحة ونقول خط مائل HTML.
تم.
حسنًا، والآن أنا بالفعل أحتاج إلى تكوين
الخادم للاستماع على المنفذ.
لذلك دعوني أمضي قدمًا وأقوم بتحديد منفذ
TCP من 8080، الذي استخدمناه.
دعوني أمضي قدمًا وأقوم 
بتحديد عنوان الخادم على أنه،
أوه 0.0.0.0، وهو ما يستخدمه IDE
بشكل افتراضي، مثل العديد من الخوادم.
ومن ثم دعوني أقوم بإنشاء
خادم الويب، خادم HTTP.
معالج طلب خادم HTTP لعنوان الخادم،
httpd.serve_forever.
حسنًا، هذه هي كيفية إنشاء
تطبيق قائم على ويب
يقوم بإنشاء HTML بشكل ديناميكي.
بالنظر للماضي، أندم حقًا على كتابة
كل ذلك لأن المغزى كله
الآن هو التخلص من هذه التعليمة البرمجية.
مثل، هذا هو سبب وجود أُطُر العمل.

English: 
If my goal quite simply at hand is
to write Python code that dynamically
generates HTML, then calling
lots of functions like write,
which is essentially the equivalent of
print in this context, is just tedious.
I got bored writing it, I
accomplished so terribly
little at the end of the day.
And so frameworks exist
to make our lives easier.
But what's going on underneath
the hood is exactly this.
When we start using this
framework called Flask,
it's just going to make all
of this automated for us.
It's going to make it easier to
specify the IP address that you
want to run your web
server on, it's going
to make it easier to specify the
port number that you want your server
to be listening on, and
it's going to make it easier
to respond to get requests
because Flask will
take care of the implementation of some
function like this one called do get.
So all of this is there
underneath the hood,
but the flask framework gives
us essentially an abstraction
on top of that.
So what do I actually mean by that?
If we want to distill this now
into a simpler web application,
first let's go ahead and do this.

Arabic: 
إذا كان هدفي المطروح بكل بساطة هو
كتابة تعليمة برمجية في Python تقوم بإنشاء
hTML ديناميكيًا، ثم استدعاء
العديد من الدالات مثل write،
والتي في الأساس تعادل
print في هذا السياق، فهذا يكون مملاً.
وسأشعر بالملل من كتابتها، 
وسأنجز القليل للغاية
في نهاية المطاف.
ولذلك توجد أُطُر العمل
لجعل حياتنا أسهل.
ولكن ما يحدُث بشكل غير ظاهر
هو هذا بالضبط.
عندما نبدأ باستخدام إطار
العمل هذا المُسمى Flask،
فسيقوم بتشغيل كل
هذا آليًا من أجلنا.
سيسهل تحديد
عنوان IP الذي تريده
لتشغيل خادم الويب 
الخاص بك، سيسهل
تحديد رقم المنفذ
الذي تريد أن يتم الاستماع
للخادم الخاص بك
عليه، وسيسهل
من الاستجابة للحصول على الطلبات
لأن Flask سيتولى
تنفيذ بعض الدالات
مثل هذه التي تسمى do get.
إذن يوجد كل ذلك
بشكل غير ظاهر
ولكن إطار عمل flask يمنحنا
في الأساس تجريدًا
في أعلى ذلك.
إذن ما الذي أعنيه بذلك في الواقع؟
إذا أردنا استخلاص هذا الآن
في تطبيق ويب أبسط،
أولاً دعونا نمضي قدمًا ونفعل ذلك.

English: 
Let me go ahead and open up a terminal
window and let me go into my code
here and go ahead and
run Python of serve.py.
And you'll see nothing seems
to be happening just yet.
So I'm going to go to
cs50 IDE web server
to open up a tab containing the
web server that I'm now running.
And you'll see that's it.
That's the only thing I
accomplished right now.
It's not dynamic to be sure, but
there is code and Python code
there with which I could actually
do something dynamically.
But let's instead do this now
with Flask, this framework
that seems to make our lives easier.
I'm going to go ahead and make a
program called application.py, which
is just a convention.
I could call it anything I want.
And I'm going to go ahead
and say the following.
Let's first go ahead and import
this framework called Flask.
And specifically import
capitalized flask, which
is the name of the framework itself.
And then let me preemptively
import a couple of functions
called render template and then this
special global variable called request.
You would only know to do this
from reading the documentation.
But now let me go ahead
and say, hey Flask,

Arabic: 
دعوني أمضي قدمًا وأفتح نافذة
طرفية، وأنتقل إلى التعليمة البرمجية الخاصة بي
هنا وأمضي قدمًا
وأشغل Python لـ serve.py.
وسترون ألا شيء
يحدث بالفعل حتى الآن.
لذلك سأنتقل إلى
خادم ويب cs50 IDE
لفتح علامة تبويب تحتوي على
خادم الويب الذي أقوم بتشغيله الآن.
وسترون أن هذا هو كل شيء.
هذا هو الشيء الوحيد
الذي أنجزته الآن.
ليس ديناميكيًا بالتأكيد، ولكن
هناك تعليمة برمجية وتعليمة برمجية في Python
هناك والتي يمكنني بواسطتها
القيام بشيء ما بشكل ديناميكي بالفعل.
ولكن دعونا بدلاً من ذلك نفعل ذلك الآن
باستخدام Flask، إطار العمل هذا
الذي يبدو أنه يجعل حياتنا أسهل.
سأمضي قدمًا وأقوم بإعداد برنامج
يسمى application.py، والذي
يعد مجرد تقليد.
يمكنني أسميه أي شيء أريده.
سأمضي قدمًا 
وأقول ما يلي.
دعونا نمضي قدمًا أولاً ونقوم باستيراد
إطار العمل هذا المُسمى Flask.
وعلى وجه التحديد أقوم باستيراد
flask المكتوب بالأحرف الكبيرة،
وهو اسم إطار العمل نفسه.
ثم دعوني وبشكل استباقي
أقوم باستيراد دالتين
تسمى render template ثم هذا
المتغير الشامل الخاص المُسمى request.
ستعرفون فقط كيفية القيام بذلك
من خلال قراءة الوثائق.
ولكن الآن دعوني أمضي قدمًا
وأقول، مرحبًا Flask،

Arabic: 
هل يمكنك منحي 
تطبيق ويب؟
وهذا عبارة عن نسخ ولصق.
أنت في حاجة إليه
لأي تطبيق Flask،
وهذا يعني فقط تحويل هذا الملف--
application.py-- إلى تطبيق ويب.
ثم أخيرًا، سأمضي
قدمًا وأفعل ذلك.
سأخبر Flask أنني أريد
إنشاء تطبيق
لديه طريق يستمع إلى
الخط المائل داخل ذلك الظرف الافتراضي.
ووقتما ترى طلبًا لخط مائل
من بعض المستخدمين يا Flask،
امضِ قدمًا وقم باستدعاء تلك الدالة
التي سميتها بشكل اعتباطي index،
لكن يمكنني أن أسميها foo،
أو bar، أو أيًا كان.
وما أريدك أن تفعله
هو ذلك، return hello world.
وهذا كل شيء.
إذن كل تلك السطور الأخرى التي
كتبتها بضجر منذ لحظة
تم استخلاصها الآن إلى
7 سطور فقط، والتي لا يوضح أي شيء
منها تمامًا
كيف تعمل حتى الآن.
لكن إذا افترضتم أن هذا يعني
أعطني حق الوصول إلى المكتبة،
وحول الملف الخاص بي إلى تطبيق 
ويب، واستمع الآن
إلى طلبات get على الخط المائل،
هو أمر منطقي نوعًا ما
ويناسب النموذج العقلي الذي
قدمناه قبل بضعة أسابيع

English: 
could you please give
me a web application?
And this is copy paste.
You need this at the top
of any Flask application,
and it just means turn this file--
application.py-- into a web application.
Then lastly, I'm going
to go ahead and do this.
I'm going to tell Flask I
want to build an app that
has a route that's listening for
slash inside of that virtual envelope.
And whenever, Flask, you see a
request for slash from some user,
go ahead and call this function
which I arbitrarily called index,
but I could call it foo,
or bar, or whatever.
And what I want you to do
is this, return hello world.
And that's it.
So all of those other lines I
tediously wrote out a moment ago
are now distilled into just
7 lines, which none of which
are completely obvious
how they work just yet.
But if you assume that this means
give me access to the library,
turned my file into a web
application, and listen now
for get requests on slash,
it kind of makes sense
and fits into the mental model that
we introduced a couple of weeks

English: 
ago with HTML and CSS itself.
And to run this server, what I'm going
to do now in my hello directory, which
is where a online copy of this
is on the course's website,
I'm going to go ahead and
quite simply say Flask run.
So Flask is not only a framework
or code that you have access
to as free and open
source code, but it's also
a program you can run at the
command line that also figures out
how to turn the server on
and just run it forever.
You're going to see some diagnostic
output at first glance, most of which
you don't have to care about.
But there will be a few
URL that's spit out which
is based on your own user name.
Mine today is jharvard 3 just
for demonstration purposes.
And if you click on that
URL and then click Open,
you'll see now this version of the
same application doing just this.
Now, I'm kind of cheating, though.
Because if I open up Chrome and view
my page source, notice that of course
I'm cheating because all I've
done is print out hello world.
And if I view the
source of this page, I'm
literally only going to say
hello world and no actual HTML

Arabic: 
باستخدام HTML و CSS نفسها.
ولتشغيل هذا الخادم، ما سأقوم 
به الآن في دليل hello الخاص بي، حيث
توجد نسخة عبر الإنترنت من هذا 
على موقع الويب الخاص بالدورة،
سأمضي قدمًا 
وأقول بكل ببساطة تشغيل Flask.
إذن Flask ليس مجرد إطار عمل
أو تعليمة برمجية يمكنك الوصول إليها
مجانًا وتعليمة برمجية،
مفتوحة المصدر لكنها أيضًا
برنامج يمكنك تشغيله في 
سطر الأوامر الذي اكتشف أيضًا
كيفية تشغيل الخادم عليه
وتشغيله فقط إلى الأبد.
وسترون بعض المخرجات
التشخيصية للوهلة الأولى، والتي
يجب عليكم ألا تلقوا بالاً لمعظمها.
ولكن سيكون هناك بضعة
عناوين URL تظهر
تعتمد على اسم المستخدم الخاص بك.
والاسم الخاص بي اليوم هو jharvard 3
فقط لأغراض التوضيح.
وإذا نقرتم على عنوان
URL هذا ثم نقرتم فوق فتح،
سترون الآن أن هذا الإصدار من 
التطبيق نفسه يقوم بهذا فقط.
الآن، أنا أقوم بالغش نوعًا ما، رغم ذلك.
لأنه إذا فتحت Chrome وقمت بعرض
مصدر الصفحة الخاص بي، فلاحظوا أنني بالطبع
أقوم بالغش لأن كل ما قمت به
هو طباعة hello world.
وإذا قمت بعرض مصدر
هذه الصفحة، فسأقول
حرفيًا hello world
فقط وليس HTML الفعلي

Arabic: 
لأنني حرفيًا لم
أكتب أي HTML في ملفي.
ولكن تبين أن Flask
يجعل هذا الأمر سهلاً، أيضًا.
لذلك دعوني أمضي قدمًا وأقوم
بإيقاف الخادم هنا للحظة.
يُعد Control-c 
صديقك، يقوم
بإخراجك من أي برنامج مشغّل بالفعل.
ودعوني أمضي قدمًا وأفعل هذا.
ودعوني أمضي قدمًا ولا أقوم فقط بإرجاع
"hello world"
كقيمة ضمنية.
دعوني أمضي قدمًا وأقوم بإرجاع تقديم
القالب المسمى index.html.
إذن هذه ميزة من ميزات Flask، أيضًا.
إذا كنتم تريدون فصل المنطق الخاص بكم--
أدوات التحكم لديكم-- من HTML الخاص بكم--
العرض الخاص بكم-- فستقومون حرفيًا
بوضع الأول في application.pi،
وتقومون بوضع الآخر في
ملف HTML مثل هذا.
وتقومون بإخبار التعليمة البرمجية الخاصة بوحدة التحكم--
application.py-- اعرض
المستخدم، لتقديم
ملف index.html للمستخدم.
إذن أين أضع هذا؟
سيكون التقليد عبارة عن إنشاء
دليل يسمى القوالب.
ثم في هذا الدليل، قم بالمضي قدمًا
وضع ملفًا يُسمى index.html.
وإذا مضيت قدمًا وفتحت
الملف الذي قمت بإنشائه

English: 
because I literally didn't
type out any HTML in my file.
But it turns out that Flask
makes this easy, as well.
So let me go ahead and stop the
server here for just a moment.
Control-c is your
friend, it gets you out
of whatever program is actually running.
And let me go ahead and do this.
Let me go ahead and not just
return quote-unquote hello world
as a hardcoded value.
Let me go ahead and return the rendering
of a template called index.html.
And so this is a feature of Flask, too.
If you want to separate your logic--
your controller-- from your HTML--
your view-- you literally put
the former in application.pi,
and you put the latter in
an HTML file like this.
And you tell the controller code--
application.py-- show
the user, to render
for the user the index.html file.
So where do I put this?
The convention would be to make
a directory called templates.
And then in that directory, go ahead
and put a file called index.html.
And if I go ahead and open
up the file that I already

Arabic: 
مسبقًا بالفعل في المحاضرة هنا، دعوني
فقط أُظهر لكم كيف يبدو هذا.
وبعد ذلك سوف نلقي
نظرة عليه في المتصفح.
ها هو HTML الآن مع
ميزة رائعة للغاية
التي على وشك
أن نكشف فائدتها.
ما الشيء الجديد الذي يظهر
أمامكم في هذا الملف؟
الجمهور: قوسين متعرجين حول الاسم.
ديفيد مالان: نعم، قوسين متعرجين.
وبطريقة أو بأخرى
اعتاد ذلك على قول world،
ولكن في نسختي النهائية
من هذا أقوم في الواقع
بالتلميح إلى بعض
القدرات الأكثر قوة.
هذا يشبه العنصر النائب
نوعًا ما، إذا صح التعبير.
ربما اسم شخص حقيقي.
وهنا تدخل قوة
شيء مثل Flask حيز التشغيل.
إنه يسهل حقًا القيام 
بشيء كهذا.
إذن دعوني أمضي قُدمًا
وأقوم بتحويل ذلك بالفعل
إلى شيء أكثر
إثارة للاهتمام.
دعوني أنتقل إلى application.py.
وقبل أن أقوم بتقديم ملف HTML
هذا، دعوني أمضي قدمًا وأفعل ذلك.
دعوني أمضي قدمًا وأعلن
متغيرًا يُسمى name.
ودعوني أمضي قدمًا
وأتحقق من الطلب الوارد،
ما بداخل هذا الظرف الافتراضي.

English: 
created in advance of class here, let
me just show you what this looks like.
And then we'll take a
look at it in a browser.
Here is HTML now with
a pretty fancy feature
that we're about to
reveal the utility of.
What jumps out at you
is new in this file?
AUDIENCE: Two curly braces on the name.
DAVID MALAN: Yeah, two curly braces.
And somehow or other that
used to be saying world,
but in my final version
of this I actually
am hinting at some more
powerful capabilities.
This kind of looks like a
placeholder, if you will.
Maybe someone's actual name.
And here's where the power of
something like Flask comes into play.
It makes it really easy
to do something like this.
So let me go ahead
and actually turn this
into something a little
more interesting.
Let me go into application.py.
And before I actually render this HTML
file, let me go ahead and do this.
Let me go ahead and declare
a variable called name.
And let me go ahead and
check the incoming request,
the inside of that virtual envelope.

Arabic: 
دعوني أتحقق من وسيطاته أو أي من
معلمات HTTP التي تم تمريرها
وأحاول الحصول على شيء
يسمى name مثل هذا.
دعوني أمضي قدمًا وأقوم
بحفظ ذلك ثم لاحظوا ذلك.
يأخذ قالب التقديم
وسيطات متعددة.
ينبغي أن يكون المتغير الأول هو اسم
القالب الذي تريدون تقديمه.
ولكن إذا كنتم تريدون تمرير
البيانات بشكل ديناميكي،
يمكنكم استخدام المعلمات المسماة في Python.
تذكّروا من الأسبوع الماضي أنه يمكنكم
القيام بأشياء من هذا القبيل، x يساوي y،
وz يساوي w.
يمكنكم تمرير أسماء
الأشياء التي تريدون تمريرها
والقيم المقابلة لها.
لذلك إذا كنت أريد تمرير متغير name 
وتعيينه مساويًا لمتغير الاسم
الذي حددته للتو،
شاهدوا ما يمكننا القيام به هنا.
دعوني أعود إلى وحدة التحكم الخاصة بي.
دعوني أمضي قدمًا وأعيد تشغيل في دليل hello
الخاص بي، والذي يكون متوفرًا على الإنترنت،
تشغيل Flask.
والآن دعوني أنتقل إلى هذا حيث
قال hello world في السابق.
دعوني الآن، تمامًا مثل مثال
Google الخاص بنا منذ بضعة
أسابيع، أكتب not q يساوي القطط،
وهو ما فعلناه في المرة السابقة،

English: 
Let me check its arguments or any of
the HTTP parameters that were passed in
and try to get something
called name like this.
Let me go ahead and save
that and then notice this.
Render template takes
multiple arguments.
The first one should be the name
of the template you want to render.
But if you want to pass
in data dynamically,
you can use named parameters in Python.
Recall from last week that you can
do things like this, x equals y,
and z equals w.
You can pass in the names of
the things you want to pass in
and their corresponding values.
So if I want to pass in a name variable
and set it equal to the name variable
that I just defined,
watch what we can do here.
Let me go back to my console.
Let me go ahead and rerun in my hello
directory, which is available online,
Flask run.
And now let me go over to this where
it previously said hello world.
Let me now, just like with our
Google example a couple of weeks
ago, type in not q equals cats,
which is what we did last time,

English: 
but maybe name equals David
to simulate a get request.
And if I did everything right, when I
hit Enter I now see this dynamically.
And if I change this now from
David to, say, Veronica, of course,
this is going to
dynamically output this.
Can someone now try to break my code?
Propose an input that I should try
to see if I messed up somewhere.
AUDIENCE: No entry.
DAVID MALAN: OK, no input.
Or what's that?
say again?
Name equals name, I like that one, too.
So let's try that, name equals name.
So OK, I mean it's kind of maybe like
a grammatical bug or semantic bug,
but not really a code bug per se.
That's just user error.
But what if I just get rid of it?
OK, that just looks a little stupid.
So an aesthetic bug, but we should
probably start handling this.
What if I get rid of name altogether?
Interesting.
It seems that my final version actually
has some built in functionality.
So where is that coming from?
Well, what if I did this?
It turns out that I could
say something like this.
If not name, then go ahead
and set name equal to world

Arabic: 
ولكن ربما name يساوي ديفيد
لمحاكاة طلب get.
وإذا فعلت كل شيء بشكل صحيح، عندما أضغط
على Enter الآن أرى هذا بشكل ديناميكي.
وإذا قمت بتغيير هذا الآن من
ديفيد إلى، لنقل، فيرونيكا، بالطبع،
سيقوم هذا بإخراج ذلك
بشكل ديناميكي.
هل يمكن لشخص ما الآن تقسيم تعليمتي البرمجية؟
اقترحوا مُدخلاً ينبغي عليّ تجربته
لمعرفة ما إذا قمت بالعبث في مكان ما.
الجمهور: لا تدخل شيئًا.
ديفيد مالان: حسنًا، لا مُدخل.
أو ما هذا؟
كررها؟
Name يساوي Name، أحب ذلك، أيضًا.
إذن دعونا نجرب ذلك، Name يساوي Name.
حسنًا إذن، أعني أنه قد يكون مثلاً
خطأ نحوي أو خطأ دلالي نوعًا ما،
ولكن ليس خطأ تعليمة برمجية في حد ذاتها بالفعل.
إنه فقط خطأ من المستخدم.
ولكن ماذا لو تخلصت منه؟
حسنًا، هذا يبدو أمرًا غبيًا قليلاً.
إذن خطأ جمالي، ولكن ينبغي علينا
ربما البدء في معالجة ذلك.
ماذا لو تخلصت من name بالكامل؟
مثير للإعجاب.
يبدو أن الإصدار النهائي الخاص بي 
يحتوي على بعض الوظائف المضمنة.
إذن من أين يأتي ذلك؟
حسنًا، ماذا لو فعلت ذلك؟
تبين أنه يمكنني
قول شيء مثل هذا.
إذا لم يكن name، فامضِ قدمًا
وقم بتعين name مساويًا لـ world

English: 
would be one way of doing it.
Or I could actually
use the function here.
Turns out that this get function
can take a default value.
And so if you read the
documentation, you'll
see that the second
value you provide will be
used if the user hasn't provided one.
And so indeed, if I reload now
and see nothing, I get world.
And if I instead do name equals, say,
Brian, I get that dynamic output.
And so when I say web application,
this is just a hint of what I mean.
This is dynamically generated content.
It's not hardcoded, because it's
actually coming from the user.
So when Google implements its
slash search web application,
this is the kind of thing they're doing.
It's way more involved, of course.
They're searching a database, looking
for cats, and dogs, or whatever
it is you're searching for
and then generating HTML.
But notice with just
this simple approach
can we ourselves generate
any HTML we want dynamically.
Because all we have
to do in that template
called index.html is exactly this.
Hello, comma, and then
a placeholder where

Arabic: 
ستكون إحدى طرق فعل ذلك.
أو يمكنني استخدام
الدالة هنا بالفعل.
تبين أن دالة get هذه
يمكن أن تأخذ قيمة افتراضية.
وهكذا إذا قرأتم
الوثائق، فسترون
أن القيمة الثانية
التي تقدمونها سيتم
استخدامها إذا لم يقدم المستخدم واحدة.
وبالفعل، إذا قمت بإعادة التحميل
الآن ولم أر شيئًا، فأحصل على world.
وإذا فعلت بدلاً من ذلك name تساوي، لنقل،
بريان، فأحصل على هذا المُخرج الديناميكي.
ولذلك عندما أقول تطبيق ويب،
فهذا مجرد تلميح عما أعنيه.
هذا محتوى تم إنشاؤه ديناميكيًا.
ليس ترميزًا ضمنيًا، لأنه
قادم بالفعل من المستخدم.
لذلك عندما تقوم Google بتنفيذ
تطبيق بحث الخط المائل للويب الخاص بها،
فهذا ما يقومون به نوعًا ما.
إنها طريقة أكثر انخراطًا، بالطبع.
يقومون بالبحث في قاعدة بيانات،
عن القطط، والكلاب، أو أيًا كان
الذي تبحثون عنه
ثم إنشاء HTML.
لكن لاحظوا باستخدام هذا
النهج البسيط فقط
يمكننا أن نقوم بإنشاء 
أي HTML نريده بشكل ديناميكي.
لأن كل ما يتعين علينا
القيام به في هذا القالب
المُسمى index.html هو ذلك بالضبط.
Hello، فاصلة، ثم
عنصر نائب حيث

Arabic: 
name هو المتغير الذي تمرره.
ولكي نكون واضحين، فإنه
لا يلزم تسميته name.
يمكنني كتابة شيء مثل foo،
والذي سيكون سخيفًا قليلاً.
ولكن إذا فعلت ذلك، فأحتاج إلى تسمية 
المتغير الذي سأدخله foo هنا.
وإذن هناك توافق
واحد لواحد
بين الأشياء قبل
علامات يساوي ومكان
إدخالهم في الأسفل هنا.
أي أسئلة، حتى الآن، على هذا 
المثال البسيط، والذي يعد مع هذا كتلة بنائية؟
أجل؟
الجمهور: [INAUDIBLE]
تم إنشاؤه بشكل ديناميكي.
ديفيد مالان: بالتأكيد.
أعني من إنشائه ديناميكيًا أنني
لم أكتبه مسبقًا عن طريق كتابة
صفحة ويب يدويًا تقول
مرحبًا ديفيد، أو مرحبًا بريان،
أو مرحبًا فيرونيكا.
يتم إنشاء كل هذه الصفحات
بشكل ديناميكي بناءً على مُدخل المستخدم.
أنا كتبت معظم تلك الصفحات.
لقد قمت بكتابة كل شيء فيها
وبعد الفاصلة، ولكن بعد ذلك-- آسف،
حتى الفاصلة، ولكن تم
إضافة الأسماء ديناميكيًا.
سؤال جيد.
أي أسئلة أخرى؟
حسنًا.

English: 
name is the variable you're passing in.
And so to be clear, it doesn't
have to be called name.
I could do something like foo,
which would be a little nonsensical.
But if I do that, the variable I
plug in needs to be called foo here.
And so there's a one
to one correspondence
between the things before the
equal signs and where they get
plugged in down here.
Any questions, then, on this
simple example, but building block?
Yeah?
AUDIENCE: [INAUDIBLE]
dynamically generated.
DAVID MALAN: Sure.
By dynamically generated, I mean I have
not written in advance by typing it out
manually a web page that says
hello David, or hello Brian,
or hello Veronica.
Those pages are all generated
dynamically based on user input.
I wrote most of those pages.
I wrote everything up into and
after the comma, but then-- sorry,
up to the comma, but then the
names are dynamically added.
Good question.
Other questions?
All right.

English: 
So why don't we rewind
to 1997 or so and see
if we can't build a more dynamic
web application that actually allow
students to register
for something that's
a little more compelling than
just providing their name?
So let me go ahead and open up froshim0,
which is the first larger scale
application we have here today.
And notice that I have a few files.
So already things are going to
escalate quickly whereby we're
going to suddenly introduce
multiple templates,
but we'll do this in
order to solve a problem.
But first let me go ahead
and open up application,py,
which just like your main function
in C is kind of the entry point now
to a web-based application.
So notice that-- let's start like this.
Let me go ahead and delete that
and start from the beginning here.
Let's go ahead and do this.
In froshim0, we have this
default route of slash,
and notice that it's going
to render index.html.
So when you start to
read someone else's code,
you kind of follow these breadcrumbs.

Arabic: 
إذن لماذا لا نعود بذاكرتنا
إلى عام 1997 أو قرب ذلك ونرى
إذا لم يكن بإمكاننا إنشاء تطبيق 
ويب أكثر ديناميكية يتيح إلى الطلاب
قيامهم بالفعل 
بالتسجيل لشيء ما
أكثر إقناعًا من
مجرد تقديم أسمائهم؟
لذلك دعوني أمضي قدمًا وأفتح froshim0،
والذي يعد أول تطبيق نطاق أكبر
لدينا هنا اليوم.
ولاحظوا أن لديّ بعض الملفات.
إذن ستتصاعد الأمور 
بسرعة بالفعل حيث سنقوم
فجأة بتقديم
قوالب متعددة،
ولكننا سنقوم بذلك لكي
نحل مشكلة.
ولكن أولاً دعوني أمضي قدمًا
وأفتح تطبيق،py،
الذي يشبه تمامًا دالة main الخاصة بكم
في لغة C ويُعد نقطة الدخول نوعًا ما الآن
إلى تطبيق قائم على الويب.
إذن لاحظوا ذلك-- دعونا نبدأ هكذا.
دعوني أمضي قدمًا وأحذف ذلك
وأبدأ من البداية هنا.
دعونا نمضي قدمًا ونقوم بذلك.
في froshim0، لدينا هذا
الطريق الافتراضي للخط المائل،
ولاحظوا أنه سيقوم
بتقديم index.html.
لذلك عندما تبدأون في
قراءة تعليمة برمجية لشخص آخر،
فإنكم تتبعون هذه الآثار نوعًا ما.

English: 
So let me go ahead and open
the same folder, froshim0.
Let me go into--
let me go ahead, rather, let's
do this from scratch, actually.
Let's do this.
Index.html, and let me do
the familiar doctype HTML.
Then let me go ahead and do an HTML tag
here, it finishes my thought for me.
The head tag here, the title tag
here, froshim0 will be the title here.
Let me go ahead and create a body.
And now for this web
page, I want to go ahead
and have a few things via which the
user can actually register for froshim.
So let me go ahead and
have just some title text
here, like register for froshims
like I did back in the day.
Then let me go ahead
and start a form tag.
And then in here, what
information might a student
want to provide when registering
for something like a sports team?
AUDIENCE: Name.
DAVID MALAN: OK, the student's name.
So input type equals text.
The name of this input probably
shouldn't be something generic like q,
it should probably be more
descriptive like name.
So its a little weird
looking, but name equals name.
And we'll go ahead and do this.

Arabic: 
إذن دعوني أمضي قدمًا وأفتح
المجلد نفسه، froshim0.
دعوني أنتقل إلى--
دعوني أمضي قدمًا، وبدلاً من ذلك، دعونا نفعل ذلك
من سكراتش، في الواقع.
لنقم بذلك.
Index.html، ودعوني
أكتب doctype HTML المألوف.
ثم دعوني أمضي قدمًا وأكتب علامة HTML
هنا، فإنها تنهي الأفكار نيابة عني.
علامة الرأس هنا، علامة العنوان
هنا، سيكون froshim0 العنوان هنا.
دعوني أمضي قدمًا وأقوم بإنشاء بنية.
والآن لصفحة الويب
هذه، أريد المضي قدمًا
والتحلي ببعض الأشياء التي
يمكن للمستخدم التسجيل بواسطتها بالفعل لـ froshim.
إذن دعوني أمضي قدمًا ويكون
لديّ نص عنوان
هنا، مثل التسجيل في froshims
مثلما فعلت سابقًا.
ثم دعوني أمضي قدمًا
وأبدء علامة نموذج.
ثم هنا، ما هي المعلومات
التي قد يريد تقديمها
الطالب عند التسجيل
لشيء ما مثل فريق رياضي؟
الجمهور: الاسم.
ديفيد مالان: حسنًا، اسم الطالب.
إذن نوع المُدخل يساوي نصًا.
لا ينبغي على الأرجح أن يكون اسم
هذا المُدخل شيئًا عامًا مثل q،
ربما ينبغي أن يكون وصفيًا 
أكثر مثل name.
إذن يبدو غريبًا
قليلاً، أن name يساوي name.
وسنمضي قدمًا ونفعل ذلك.

English: 
And if we really want
to be fancy, we can
do like a placeholder text of name just
to in light gray text show the user
what we want.
And then back in the day,
minimally the students
registering for sports
had to provide their dorm,
so the building in which they lived.
So in HTML, we've got
a bunch of input types.
We've got text boxes, turns out there's
text areas which are even bigger,
check boxes, radio buttons, what's most
apt perhaps for choosing your dorm?
AUDIENCE: Dropdown list.
DAVID MALAN: Like a dropdown
list, otherwise called a menu.
But which tag?
AUDIENCE: Container?
DAVID MALAN: Not a container, a
little more precise than that.
With what tag can you
generate a dropdown list
if you've done this before in HTML?
AUDIENCE: Select.
DAVID MALAN: Select.
So it's not perfectly clearly named,
but it's, indeed, a select menu by name.
And so I can actually do this.
Select, and the name of this
field will be dorm, for instance.
And then inside of this I'm going
to go ahead and have a few options.
So one option might be
let's say Apley Court, which

Arabic: 
وإذا أردنا أن نكون 
خيالين حقًا، يمكننا
فعل ما يشبه نص العنصر النائب للاسم لكي
نظلل نصًا رمادي يظهر للمستخدم
ماذا نريد.
ثم في وقت سابق من اليوم،
تعين على الطلاب
المُسجلين للرياضات
أن يوفروا سكنهم على الأقل،
إذن المبنى الذي يعيشون فيه.
لذلك في HTML، لدينا
مجموعة من أنواع المُدخلات.
لدينا مربعات النصوص، تبين أن
لدينا مناطق للنصوص تكون أكبر حجمًا،
مربعات الاختيار، أزرار الراديو، ما هو الأكثر 
ملائمة ربما لاختيار السكن الخاص بكم؟
الجمهور: القائمة المنسدلة.
ديفيد مالان: مثل القائمة 
المنسدلة، أو التي تُسمى قائمة.
لكن أي علامة؟
الجمهور: وعاء؟
ديفيد مالان: ليس الوعاء، هي
أكثر دقة من ذلك قليلاً.
مع أي علامة يمكنكم
إنشاء قائمة منسدلة
إذا كنتم قد فعلتم ذلك من قبل في HTML؟
الجمهور: تحديد.
ديفيد مالان: تحديد.
إذن لم يتم تسميتها بشكل واضح تمامًا،
ولكنها في الواقع قائمة تحديد حسب الاسم.
إذن يمكنني القيام بذلك بالفعل.
تحديد، وسيكون اسم هذا 
الحقل هو سكن، على سبيل المثال.
ثم داخل هذا سأمضي قدمًا
ويكون لديّ بعض الخيارات.
إذن أحد الخيارات قد يكون
لنقُل Apley Court، وهي

Arabic: 
واحدة من المباني
التي يعيش فيها الطلاب الجدد.
قد يكون هناك مكان آخر
يُسمى Canoday،
ثم سيكون هناك 
مجموعات أخرى.
ثم لاحظوا، أيضًا، إذا لم تستخدموا
قائمة تحديد من قبل، والتي لم
تتح لكم الفرصة حقًا
حتى الآن لاستخدامها ما لم تكونوا قد فعلتم ذلك
من قبل، يجب أن تحتوي هذه الخيارات 
أيضًا على قيم، والتي ستكون
متشابهة بالضبط تماشيًا مع أغراضي.
ولكن بينما يرى
الأشخاص ما بين العلامات،
فإن ما بين هذه 
الاقتباسات كقيمة القيمة
هو ما يراه الكمبيوتر في الواقع.
إذن هذه هي الكلمات التي
تملأ القائمة المنسدلة،
هذه هي القيم التي بالفعل تصبح
محشوةً في الظرف الافتراضي
الذي يراه الطالب أو
الطالبة بنفسهم بالفعل.
إذن دعوني أمضي قدمًا وأحفظ ذلك.
دعوني أمضي قدمًا 
وأفتح وحدة التحكم الخاصة بي الآن.
سأقوم باستعارة تعليمة
برمجية صغيرة فقط حتى
يمكننا القيام بذلك من سكراتش هنا.
إذن دعوني أمضي قدمًا وأسحب من
froshim0 ملف application.py الخاص بي
وأنتقل إلى مساحة العمل الخاصة بي.
إذن دعوني أمضي قدمًا
الآن وأشغل Flask حيث

English: 
is one of the buildings
in which freshmen live.
There might be another
one called Canoday,
and then there's going
to be bunches of others.
And then notice, too, if you've never
used a select menu, which you wouldn't
have really had occasion to
yet unless you've done this
before, these options also have to
have values, which for my purposes
are going to be exactly the same.
But whereas what's between the
tags is what the human sees,
it's what's between these
quotes as the value of value
that the computer actually sees.
So these are the words that
populate the dropdown menu,
these are the values that actually
gets stuffed into the virtual envelope
that the student him or
herself actually see.
So let me go ahead and save this.
Let me go ahead and
now open up my console.
And I'm going to borrow
a little code just so
that we can do this from scratch here.
So let me go ahead and grab from
froshim0 my application.py file
and go into my workspace.
So let me go ahead now
and run Flask run wherein

Arabic: 
لديّ ملف application.py هذا.
سأشاهد عنوان URL
الذي تستقر فيه تعليمتى البرمجية الآن.
وإذا قمت بفتح هذا، سأرى 
خطأ داخليًا في الخادم.
إذن هذا مقصود عند مرحلة ما لأن
الخطأ الداخلي في الخادم، تذكّروا،
كان واحدًا من أكثر التعليمات البرمجية للحالة
غموضًا، 500، الذي ربما
لن تروه إلا إذا قمتم بزيارة
موقع ويب حيث يسير شيء ما
على نحو خاطئ بالفعل.
إذن كيف يمكنني معرفة
الخطأ الذي قد حدث الآن
حيث أقوم بكتابة التعليمات البرمجية بالفعل 
وليس مجرد كتابة HTML مرمّز ضمنيًا؟
حسنًا، سيتم العثور على
جميع الدلائل
هنا بداخل نافذة وحدة التحكم.
إذن عندما تشغلون Flask فإنكم
تقومون بتشغيل خادم ويب كامل.
أنت تستمعون عبر TCP/IP 
للطلبات الواردة من المستخدمين.
وبالتالي فإن ما ستشاهدونه في وحدة التحكم
ليس فقط مخرجًا تشخيصيًا
عندما تقومون بتشغيل Flask أولاً، لكنكم
سترون كافة رسائل الخطأ
التى قد تحدث بعد ذلك.
وهذا يبدو مشفرًا قليلاً.
بصراحة، للوهلة الأولى يبدو
هذا النص زاخمًا لرؤيته.
ولكن في حين أنه في Clang
و لغة C بشكل عام
يساعدك النظر في الأعلى،
أما رسائل الخطأ في بعض الأحيان

English: 
I have this application.py file.
I'm going to see the URL
at which my code now lives.
And if I open this up, I'm going
to see an internal server error.
So intended at some point because
internal server error, recall,
was one of the more arcane status
codes, 500, that you probably
have not seen unless you're visiting
a website where something has actually
going wrong.
So how do I begin to figure
out what has gone wrong now
that I'm actually writing code and
not just writing hard coded HTML?
Well, all of the clues
are going to be found
here inside of the console window.
So when you're running Flask you are
running a full fledged web server.
You are listening via TCP/IP for
incoming requests from users.
And so what you'll see in the console
is not just the diagnostic output
when you first start Flask, but you're
going to see all of the error messages
that might actually happen thereafter.
And this is a little cryptic looking.
Frankly, it's overwhelming to
see this text at first glance.
But whereas in Clang
and in C it generally
helps to look at the very top,
sometimes the error messages

Arabic: 
هنا في هذا السياق لـ Flask
تكون نحو الأسفل نوعًا ما.
وهنا لدينا قالب غير موجود.
قالب لأنه لم يمكنه
العثور على index.html.
وهذا فقط لأنني أخفقت.
إذن في الواقع دعوني أخرج من
Flask بكتابة control-c.
وإذا كتبتُ ls في الدليل الخاص بي،
لاحظوا أني لم أنفذ
ما أنصح به إلى حد ما.
من المحتمل أنه دقيق بعض الشيء،
ولكن لم أنظم نفسي
بالطريقة الصحيحة.
ما هو الخطأ الذي ارتكبتُه؟
نعم؟
الجمهور: لم تقم بإنشاء
دليل قوالب.
ديفيد مالان: نعم، إنه
خطأ سخيف إلى حد ما.
لم أقم بإنشاء دليل قوالب.
وبذلك يمكنكم القيام
بذلك بطرق أخرى مختلفة.
بواسطة رمز المجلد هنا،
يمكنكم إنشاء مجلد جديد
عن طريق النقر بزر الماوس الأيمن أو النقر فوق التحكم.
أو في Linux يمكنكم إعداد
dir لإنشاء دليل.
وحتى أتمكن من القيام بإنشاء
قوالب dir enter.
ومن ثم يمكنني نقل ملف 
index.html الخاص بي، والذي
كتبتُه منذ لحظة، في دليل القوالب الخاص
بي فقط باستخدام mv للتنقل.
والآن يمكنني المضي قدمًا وتشغيل
Flask، بتمرير أصابعي،
وأعود إلى علامة تبويب 
المتصفح وأنقر فوق إعادة التحميل،
و ها هو ذا، الآن أرى النموذج بالفعل.
إذن امتلك هذه الأنواع من البديهيات.

English: 
here in this context of Flask
are kind of toward the bottom.
And here we have template not found.
Template because it
can't find index.html.
And that's just because I screwed up.
So let me actually exit
Flask by typing control-c.
And if I type ls in my directory,
notice that I haven't quite
practiced what I've preached.
It's perhaps a little subtle,
but I haven't organized myself
in the right way.
What have I done wrong?
Yeah?
AUDIENCE: Didn't make
a templates directory.
DAVID MALAN: Yeah, it's
kind of a silly mistake.
I didn't make a templates directory.
So you can do this in
a few different ways.
By the folder icon up here,
you can create a new folder
by right clicking or control clicking.
Or in Linux you can do make
dir for make directory.
And so I can do make
dir templates enter.
And then I can move my
index.html file, which
I wrote a moment ago, into my templates
directory by just using mv for move.
And now I can go ahead and run
Flask run, cross my fingers,
go back to the browser
tab and click reload,
and voila, now I actually see the form.
So have these kinds of instincts.

English: 
I didn't actually intend that,
but I forgot to create the folder.
I got this server error.
You don't have to just
stare at the browser, which
is not going to have much information.
But if you look at the
console, the terminal window
that you have control over will you
see those clang-like error messages.
So here we have a basic HTML form.
It's not complete because
I didn't bother typing out
all of the dorm names, but I
do have an input of type text
as well as the Select menu.
And I'm also kind of missing
a key detail, it seems.
What should I probably add to this form?
AUDIENCE: Where you're selecting.
DAVID MALAN: Well, I'm selecting--
I could be selecting dorm, so I
could clean this up in a couple ways.
I also am missing a Submit button.
Now, it turns out you
could probably hit Enter
and it would actually be submitted
by default. But we can fix this.
So let me go into index.html.
Let me shrink this tab just a little
bit and let me fix both of these things.
So let me go ahead and open
up this latest version, which
is now in that templates directory.
Let me go ahead and at the bottom
here do an input type equals submit,
the value of which is going
to be a register, just to make
clear to the human what's going on.

Arabic: 
لم أكن أنوي ذلك في الحقيقة،
ولكنني نسيتُ إنشاء المجلد.
لقد حصلتُ على خطأ الخادم هذا.
لا يجب أن تحدقوا
في المتصفح فقط، ولن
يحتوي على معلومات كثيرة.
ولكن إذا نظرتُ في
وحدة التحكم، النافذة الطرفية
التي يمكنكم التحكم بها سترون
رسائل الخطأ هذه مثل تلك في clang.
إذن لدينا هنا نموذج HTML الأساسي.
ليس مكتملاً لأنني
لم أتحمّل عناء كتابة
جميع أسماء السكن، ولكن لديّ
مُدخل من نوع النص
بالإضافة إلى قائمة تحديد.
وينقصني التفصيل الرئيسي
أيضًا إلى حد ما، على ما يبدو.
ما الذي يجب إضافته على الأرجح إلى هذا الشكل؟
الجمهور: أين تقوم بالتحديد.
ديفيد مالان: حسنًا، أنا أقوم بتحديد--
يمكنني تحديد السكن، وبذلك
يمكنني محو هذا بعدة طرق.
لا أجد زر Submit أيضًا.
الآن، يتضح أنه يمكنكم
الضغط على Enter
وسيتم تقديمه بشكل افتراضي
بالفعل. لكن يمكننا إصلاح هذا.
إذن دعوني أنتقل إلى index.html.
دعوني أُقلص حجم علامة التبويب هذه فقط 
قليلاً ودعوني أُصلح هذين الأمرين.
لذا دعوني أمضي قدمًا وأفتح
هذا الإصدار الأخير، والذي
هو الآن في دليل القوالب هذا.
دعوني أمضي قدمًا وأقوم في الجزء السفلي
هنا بكتابة نوع المدخل يساوي تقديم،
قيمة ذلك ستصبح
التسجيل، فقط
لإيضاح ما حدث لشخص ما.

Arabic: 
دعوني أمضي قدمًا وأعود
إلى النموذج الخاص بي، وأنقر فوق إعادة التحميل.
ولم يحدث شيء حتى الآن فقط.
وذلك لأنه بشكل افتراضي عندما
تقومون بإجراء تغييرات على بعض ملفاتكم،
فلن يقوم Flask بملاحظتها.
وبالفعل سنصلح ذلك
في مجموعة المشاكل
القادمة من خلال إضافة المزيد من
التعليمات البرمجية والمزيد من
التعقيد لتشغيل هذا تلقائيًا من أجلكم.
ولكن في حالة الشّك،
control-c لإنهاء flask.
ثم امضوا قدمًا وقوموا بإعادة تشغيل
flask، والتي ستقوم بإعادة تحميل
HTML الخاصة بكم، جميع تعليمة Python البرمجية الخاصة بكم.
وإذا عدتُ الآن إلى هنا ونقرتُ فوق
إعادة التحميل، فسنرى زر تسجيل.
لذلك يجب ألا تكون هناك أي مفاجآت.
وإذا كانت موجودة، حاولوا فقط 
الوصول إلى التشخيص فيه.
هذا أيضًا غير واضح قليلاً،
أيضًا، إلى ما تكون عليه هذه القائمة.
لذلك يتضح أنه إذا قمتم بالفعل
بإنشاء خيار وهمي مثل هذا
الذي لا يحتوي على قيمة ويقول شيئًا
مثل السكن، فيمكنكم حفظ هذا.
دعونا نمضي قدمًا ونعيد تشغيل
Flask ونعيد تحميل الصفحة هنا.
سترون أنكم ترون السكن الآن.
لسوء الحظ، هذا غباء
إلى حد ما لأن السكن الآن
هو المكان الذي من الواضح أنه
حرفيًا يمكنكم العيش فيه،
وهو لا يبدو جيدًا إلى حد ما.

English: 
Let me go ahead and go back
to my form, click reload.
And nothing's happened just yet.
And that's because by default when you
make changes to some of your files,
Flask is not going to notice.
And we'll fix this actually
in the coming problem
set by adding more
code and a little more
complexity to automate this for you.
But when in doubt, just
control-c to quit flask.
Then go ahead and rerun
flask, that will reload all
of your HTML, all of your Python code.
And if I now go back here and click
reload, we'll see the Register button.
So there should never be any surprises.
And if there are, just try to
get to the diagnosis thereof.
This is also a little unclear,
too, to what this menu is.
So it turns out that if you actually
create a bogus option like this
that has no value and say something
like dorm, you can save this.
Let's go ahead and restart
Flask and reload the page here.
You'll see that now you see dorm.
Unfortunately, this is kind
of stupid because now dorm
is where you can
literally live apparently,
which doesn't quite feel right.

Arabic: 
لذلك هناك إصلاحات HTML لهذا أيضًا.
يمكنني الانتقال إلى هنا بالفعل
وأقول مُعطل من الناحية الفنية،
لذلك لا يمكنكم تحديد ذلك في الواقع.
الآن إذا قمتُ بإعادة تشغيل Flask وإعادة تحميله،
ما يزال يظهر هناك الآن.
ولكن لأنني قمتُ بتحديد Apley Court 
بالفعل، يمكنكم رؤيته باللون الرمادي.
ويمكننا في الواقع
أن نكون محدّدين بشكل أكبر،
إذا لم تريدوا تعطيله فقط، ولكن
تحديده بشكل افتراضي ومن ثم امضوا قدمًا
وأعيدوا تحميل الصفحة هنا،
آمل أنكم سترون الآن
ما هو مألوف على معظم مواقع الويب.
إنه يقول سكن، لكنه معطل.
وعلى الرغم من وجود علامة اختيار
سخيفة هناك،
فأنتم مجبرون على اختيار سكن فعلي.
إذن هذه جماليات ثانوية،
لكن الأشياء التي
تتحكمون بها الآن.
إذن ما الذي سيحدث؟
في الواقع لم أقم بتحديد
أين يجب أن ينتقل هذا الشكل
عندما أقوم بالتسجيل بالفعل لأنني
أفتقد بعض التفاصيل الرئيسية على علامة
الشكل.
ونحن لم نفعل ذلك
خلال أسبوعين.
ولكن عندما أعدنا تنفيذ 
Google بشكل هزلي،
ما الذي أضفناه إلى علامة الشكل أيضًا؟
أي سمات؟
هل يتذكر أي شخص منكم؟
نعم.

English: 
So there's HTML fixes for this too.
I can actually go in here
and technically say disabled,
so you can't actually select that.
Now if I rerun Flask and reload,
now it still shows it there.
But because I already selected
Apley Court, you can see it in gray.
And we can actually be
a little more specific,
if you want to not only disable it, but
select it by default and then go ahead
and reload the page here,
now you'll see hopefully
what's familiar on most websites.
It says dorm, but it's disabled.
And even though the
silly checkmark is there,
you're forced to choose an actual dorm.
So these are minor aesthetics,
but the kind of things
you now have control over.
So what's going to happen?
I haven't actually specified
where this form should
go when I actually register because I'm
missing some key details on the form
tag.
And we haven't done this
in a couple of weeks.
But when we were playfully
reimplementing Google,
what else did we add to the form tag?
What attributes?
Anyone remember?
Yeah.

English: 
Oh, say again?
Action, which means what?
AUDIENCE: What to do.
DAVID MALAN: What to do.
All right, so the
action we want to take,
even though this is not
necessarily perfectly well named,
is where do you want
to submit the form to?
And I could actually submit
this in a few different ways.
I'm going to go ahead
and say, you know what,
submit it to a reasonably
named route slash register.
Google, for instance, might
have code that instead says
to submit their form to slash search.
But we're not searching for
something, we're registering.
So the name of the route
is entirely up to us.
And via what method should
we submit this information?
What are our two options?
AUDIENCE: Get or post.
DAVID MALAN: Get or post.
Get tends to be the default
if you don't mention in links.
Why might you want to use post instead?
AUDIENCE: You want it to go to a
database in order to do something.
DAVID MALAN: Yeah, you want it to
go to a database and do something.
And the right verb to use
there is to post information
as opposed to getting information.
And even more specifically when it
comes to privacy, when you use post,
the information doesn't
end up in the user's URL,
and therefore doesn't end
up in his or her history,

Arabic: 
أوه، كررها مجددًا؟
إجراء، والتي تعني ماذا؟
الجمهور: ما العمل.
ديفيد مالان: ما العمل.
حسنًا، إذن الإجراء
الذي نريد أن نتخذه،
حتى على الرغم من أنه لم تتم
تسميته بشكل مثالي بالضرورة،
هو حيث تريد
تقديم الشكل؟
ويمكنني بالفعل تقديم
ذلك بطرق مختلفة.
سأمضي قدمًا
وأقول، أتعلمون ماذا،
قوموا بتقديمها إلى ما تم تسميته
بشكل منطقي طريق خط مائل تسجيل.
قد يحتوي Google، على سبيل المثال، على
تعليمة برمجية تقول بدلاً من ذلك
لتقديم الشكل إلى خط مائل بحث.
لكننا لن نبحث عن
شيء، نحن نقوم بالتسجيل.
إذن اسم الطريق
متروك لنا تمامًا.
وعبر أي وسيلة يجب
أن نقدم هذه المعلومات؟
ما هما الخياران الموجودان لدينا؟
الجمهور: Get أو post.
ديفيد مالان: Get أو post.
يميل Get إلى أن يكون الافتراضي
إذا لم تذكروا ذلك في الارتباطات.
لماذا قد ترغبون في استخدام post بدلاً من ذلك؟
الجمهور: تريد أن تنتقل إلى 
قاعدة البيانات من أجل القيام بشيء ما.
ديفيد مالان: نعم، تريد أن تنتقل إلى 
قاعدة البيانات من أجل القيام بشيء ما.
والفعل الصحيح للاستخدام
هناك هو نشر المعلومات
بدلاً من الحصول على المعلومات.
وبصورة محدّدة أكثر عندما
يتعلق الأمر بالخصوصية، عندما تستخدم نشر،
لا تنتهي المعلومات في
عنوان URL الخاص بالمستخدم،
وبالتالي لا تنتهي
في محفوظاته أو محفوظاتها،

English: 
and therefore doesn't end up in a place
that siblings, or roommates, or anyone
else can actually see
just by poking around.
So we'll, indeed, go ahead, because
this is my name, and dorm, and maybe
my phone number, and email,
and credit card number,
and the like on some other website.
I'm going to use post for that instead.
So the catch here is
that this week, we now
have the ability to
implement slash register.
Two weeks ago we could just send
people to Google's slash search,
but now we have the ability
to make our own routes.
But how many routes have we
defined thus far in application.py?
Just the one.
And again, some new syntax with
the funky at sign and the route
keyword here.
But let me actually
just intuitively guess
that if I go ahead and say
app.route slash register,
I bet I could implement a second
route and tell the web server
to listen in two places, on slash
as well as on slash register.
But if I wanted to listen specifically
on post, it actually has to be this.
Methods equals quote-unquote post.

Arabic: 
وبالتالي لا تنتهي في مكان
يمكن للأقارب، أو رفقاء السكن، أو أي شخص
آخر رؤيته في الواقع
فقط بالتدقيق فيها.
إذن، سنمضي قدمًا، بالفعل، لأن
هذا هو اسمي، وسكني، وربما
رقم هاتفي، وبريدي الإلكتروني،
ورقم بطاقة الائتمان الخاص بي،
وما شابه ذلك على موقع ويب آخر.
سأستخدم نشر لذلك بدلاً من ذلك.
إذن المغزى هنا هو
أننا هذا الأسبوع، نمتلك الآن
القدرة على
تنفيذ خط مائل تسجيل.
منذ أسبوعين، كان بإمكاننا فقط إرسال
الأشخاص إلى خط مائل بحث من Google،
ولكن الآن لدينا القدرة
على إنشاء الطرق الخاصة بنا.
ولكن كم عدد الطرق التي قمنا
بتحدديها حتى الآن في application.py؟
فقط طريق واحد.
ومجددًا، بعض الصيغ الجديدة باستخدام
علامة في غير التقليدية وكلمة
الطريق الرئيسية هنا.
ولكن دعوني في الواقع
أخمّن بشكل بديهيي
إذا مضيتُ قدمًا وقلتُ
app.route خط مائل تسجيل،
أراهن أنه يمكنني تنفيذ طريق
ثاني وإخبار خادم الويب
أن يستمع في مكانين، على خط مائل
بالإضافة إلى خط مائل تسجيل.
لكن إذا أردتُ الاستماع على وجه التحديد
على نشر، فيجب أن يكون هذا بالفعل.
الطرق تساوي علامة اقتباس وعلامة إنهاء الاقتباس نشر.

English: 
Because by default just for
convenience, it assumes only gets.
So I need to add that.
You'd only know that
from the documentation.
Now I'm going to go ahead
and define a function.
This is slightly an
annoying feature of Flask.
You have to give the function a
name even though you'll probably
never reference it anywhere.
So I'm going to go ahead and just
reasonably call this register.
And now I have a to do.
What am I going to want to do when
the user clicks that Submit button?
AUDIENCE: Store it.
DAVID MALAN: I want
to store it somewhere.
So I probably want to store it.
But what might I want to do first
before he or she is actually
allowed to register, even though
they've clicked that submit form?
Maybe confirm their information, right?
Because if a lazy user comes in, or if
a user accidentally clicks the button
or hits enter, they might actually
submit nothing-- no name, no dorm.
That's not useful information.
It could just be perceived as spam.
So we probably want to ask
some kind of logical question
like if they didn't give us a name
or they didn't give us a dorm,
yell at the user in some way.
So I'm going to go ahead and do that.
So let me actually
express this in Python,
kind of like we did last week
with some error checking.

Arabic: 
لأنه بشكل افتراضي فقط لتيسير الأمور،
إنه يفترض get فقط.
إذن أنا أحتاج إلى إضافة ذلك.
وستعرفون ذلك فقط
من الوثائق.
الآن سأمضي قدمًا
وأقوم بتحديد دالة.
هذه ميزة مزعجة 
قليلاً من Flask.
يجب أن تعطوا الدالة اسمًا
حتى ولو كنتم على الارجح
لم تشيروا إليها من قبل في أي مكان.
إذن سأمضي قدمًا وأطلق على
هذا تسجيل.
والآن لديّ ما يجب القيام به.
ما الذي أريد فعله عندما
ينقر المستخدم فوق زر Submit هذا؟
الجمهور: تخزينه.
ديفيد مالان: أريد
تخزينه في مكان ما.
إذن ربما أريد تخزينه.
ولكن ما الذي أريد فعله أولاً
قبل السماح له أو لها بالفعل
بالتسجيل، على الرغم من أنه
قام بالنقر فوق شكل التقديم هذا؟
ربما تؤكد معلوماته، أليس كذلك؟
لأنه إذا قام مستخدم كسول، أو إذا قام
مستخدم بالنقر فوق الزر عن طريق الخطأ
أو ضغط على enter، فقد لا يقوم بالفعل 
بتقديم أي شيء-- لا يوجد اسم، لا يوجد سكن.
هذه ليست معلومات مفيدة.
يمكن النظر إليها على أنها غير مرغوب فيها.
لذلك من المحتمل أننا نريد أن نسأل
سؤالاً منطقيًا إلى حد ما
على سبيل المثال إذا لم يعطينا اسمًا
أو لم يعطينا سكنًا،
اصرخوا في وجه المستخدم بطريقة ما.
إذن سأمضي قدمًا وأفعل ذلك.
إذن دعوني في الواقع
أعبر عن ذلك في Python،
كما فعلنا في الأسبوع الماضي
باستخدام بعض عمليات التحقّق من الخطأ.

English: 
So recall that the user's name can
be gotten from an HTTP parameter.
From the request.args get, and
then ask for the name parameter.
Their dorm, meanwhile, can come
from request.args get dorm.
And again, this
request.args is something
we gave ourselves access to up
here when we said, hey Flask,
please give me access to the user's
request, that virtual envelope.
Request.arg refers to all of
the HTTP parameters in the URL.
And get is just a function or a
method built into that special Flask
feature that allows us to get
a specific parameter like name,
or dorm, or anything else.
And recall that in Python, what's kind
of nice is that you can say pretty
English-like, if not name or not--
not dorm, let's go ahead
and reprimand the user.
For instance, we could say failure
because he or she did not actually
cooperate as we intended.
Otherwise if they did
cooperate, I'm going
to go ahead and render template success.

Arabic: 
إذن تذكرون أن اسم المستخدم يمكن
الحصول عليه من معلمة HTTP.
من request.args get، ومن ثم
طلب معلمة الاسم.
يمكن أن يأتي سكنه، في نفس الوقت،
من request.args أعطني السكن.
ومجددًا، هذا
request.args هو شيء
منحنا لأنفسنا حق الوصول إلى
هنا عندما قلنا، مرحبًا Flask،
من فضلك أعطني حق الوصول إلى طلب
المستخدم، هذا الظرف الافتراضي.
يشير Request.arg إلى جميع
معلمات HTTP في عنوان URL.
وget هي مجرد دالة أو طريقة
متضمّنَة في ميزة Flask
الخاصة تلك التي تتيح لنا الحصول
على معلمة محدّدة مثل الاسم،
أو السكن، أو أي شيء آخر.
وتذكرون أنه في Python، من الجيد
أنه يمكنكم قول لغة تشبه اللغة الإنجليزية
إلى حد كبير، إذا لم يوجد اسم أو--
لم يوجد سكن، دعونا نمضي قدمًا
ونقوم بتوبيخ المستخدم.
على سبيل المثال، يمكن أن نقول failure
لأنه لم يتعاون أو لأنها لم تتعاون في الواقع
كما ذكرنا.
وبطريقة أخرى، إذا
تعاون، سأمضي
قدمًا وأقدم قالب success.

Arabic: 
وسنوضح ذلك
في غضون لحظات.
لذلك حصلتُ على سيناريوهين تمت معالجتهما.
إذا لم يتعاون أو إذا 
تعاون، علامة اقتباس وعلامة إنهاء الاقتباس failure
أو قالب HTML كامل.
إذن الآن قمتُ بتنفيذ 
خط مائل تسجيل وأنا أستمع للطريق
من خلال النشر، دعونا نمضي قدمًا
ونعيد تحميل الصفحة لتدبر الأمور بشكل جيد.
اكتب اسمي.
لن أخبركم عن سكني، ولكن
ستلاحظون الكثير.
حسنًا، لذا لاحظ الخادم الآن أنني
لم أتعاون بالفعل وأقدم
كل من اسم وسكن.
ولذلك يعيد من أجلي
علامة اقتباس وعلامة إنهاء الاقتباس failure فقط.
إذن هذا جيد لأنني الآن أعلم، حسنًا،
أنه من الواضح أنني ارتكبتُ شيئًا خاطئًا.
دعوني أعود دعوني أمضي قدمًا
وقد أستخدم Canaday هنا.
والآن دعوني أمضي قدمًا وأقوم بالتسجيل.
ولكن، ولكن، ولكن، هذا، أعلم
مسبقًا أنه سيكون خاطئًا.
لماذا؟
ليس لديّ success.html.
حسنًا، دعونا نعالج ذلك بشكل استباقي.
دعوني أنتقل هنا بالفعل
إلى دليل القوالب الخاص بي.
سأمضي قدمًا وأقوم بإنشاء ملف
جديد يُسمى success.html.
دعوني أنتقل إلى القوالب
لحفظها هناك.
وأتعلمون ماذا، يمكن أن
يكون success صفحة بسيطة للغاية.

English: 
And we'll flesh this
out in just a moment.
So I've got two scenarios handled.
If they didn't cooperate or if they
did, render quote-unquote failure
or a full fledged HTML template.
So now that I've implemented slash
register and I'm listening for a route
by a post, let's go ahead and
reload the page for good measure.
Type in my name.
Not going to tell you my dorm, but
you're going to notice as much.
OK, so now the server has noticed that
I didn't actually cooperate and provide
both a name and a dorm.
And so it's returning to me
just quote-unquote failure.
So that's good because now I know, all
right, I did something wrong clearly.
Let me go back let me go ahead
and maybe do Canaday here.
And now let me go ahead and register.
But, but, but, but, this I know
in advance is going to err.
Why?
I don't have a success.html.
OK, so let's preemptively address this.
Let me actually go in here
to my templates directory.
I'm going to go ahead and create
a new file called success.html.
Let me go into the
templates to save it there.
And you know what, success
can be a pretty simple page.

English: 
And let me open my index page, let
me copy that, let me go into success,
let me paste this.
Let me get rid of all of that body
and just say success, for instance.
So let me now go ahead
and go restart Flask,
because I've made a new template.
Let me go ahead and reload the
form just for good measure.
Let me go ahead and give you my name
this time, and OK, I live in Canaday,
and register.
And what did I do wrong this time?
So it turns out you can't
do it this way, obviously.
[LAUGHTER] So when you're
actually submitting information to
via a form via get,
Flask very cleverly puts
that information in a different place.
Because by definition, as I
claim very correctly earlier,
in request.args are all
of the key value pairs
that are in the URL that are
coming in from the user's request.
But when you submit via post, for
reasons I wish were now otherwise
you actually have to access those
values via a different variable.
So instead of using request.args, you
have to use request.form both here

Arabic: 
دعوني أفتح صفحة الفهرس الخاصة بي، دعوني
أنسخ ذلك، دعوني أنتقل إلى success،
دعوني أُلصق هذا.
دعوني أتخلص من كل تلك البنية
وأقول فقط success، على سبيل المثال.
إذن دعوني أمضي قدمًا
وأعيد تشغيل Flask،
لأنني أعددتُ قالبًا جديدًا.
دعوني أمضي قدمًا وأعيد تحميل
الشكل فقط لتدبر الأمر جيدًا.
دعوني أمضي قدمًا وأعطيكم اسمي
هذه المرة، حسنًا، أعيش في Canaday،
وأقوم بالتسجيل.
وما هو الخطأ الذي ارتكبته هذه المرة؟
إذن يتضح أنه لا يمكنكم
فعل ذلك بهذه الطريقة، بالتأكيد.
[LAUGHTER] لذلك بالفعل عندما 
تقومون بتقديم المعلومات إلى
عبر شكل عبر get،
فإن Flask بذكاء شديد يضع
هذه المعلومات في مكان مختلف.
لأنه حسب التعريف، كما زعمتُ
بشكل صحيح جدًا في وقت سابق،
في request.args كل
أزواج القيم الرئيسية
الموجودة في عنوان URL والتي
تأتي من طلب المستخدم.
ولكن عندما تقومون بالتقديم عبر نشر،
لأسباب كنت أتمنى وجودها الآن وإلا
يجب أن تصلوا بالفعل إلى تلك
القيم عبر متغير مختلف.
إذن بدلاً من استخدام request.args، يجب
أن تستخدموا request.form هنا

Arabic: 
وهنا للتوضيح-- وتمت تسمية هذا
بشكل فظيع بالضبط للأسباب
التي أعتقد أنني أتعثر بها هنا--
لأنها في الواقع تأتي عبر
شكل، أو عبر get أو نشر.
لكن يضع Flask الوسيطات في args
ويضع وسيطات نشر في شكل.
مما يؤدي بشكل واضح
إلى حدوث التباس محتمل.
لكن إذا مضيتُ قدمًا الآن
وقمتُ بتحميل هذا الإصدار من الموقع وآمل أنني،
سأمضي قُدمًا الآن وأقوم بتشغيل Flask،
وأعيد تحميل تلك الصفحة، وأكتب ديفيد،
وأعطيكم سكني، وأسجل 
وأقوم بالتسجيل بنجاح في Frosh Ims.
أترون مدى سهولة برمجة الويب؟
لذا آمل الآن أنه يمكننا على الأقل
التركيز على بنية ما قمتُ به
ونبدأ في تطويرها الآن.
لأنه لاحظوا أنني لم أقم بممارسة ما 
أشرتُ إليه منذ قليل.
ما هي القاعدة التي خرقتُها
عندما عرضتُ success.html؟
كيف وصلتُ لتلك النقطة؟
أجل؟
الجمهور: النسخ واللصق.
ديفيد ج. مالان: أجل، قمتُ بالنسخ واللصق.

English: 
and here to make clear-- and this is
horribly named for exactly the reasons
that I think I'm tripping over here--
because they actually are both coming
in via a form, via a get or post.
But Flask puts get arguments in args
and puts post arguments in form.
Thereby leading clearly
to potential confusion.
But if I go ahead now and load this
version of the site and I keep hoping,
I'm going to go ahead now run Flask,
restart this page, type in David,
give you my dorm, and register and
successfully register for froshim.
See how easy web programming is?
So hopefully now we can at least focus
on the structure of what I've done
and now begin to improve it.
Because notice that I kind of did not
practice what I preached a moment ago.
What habit did I violate when
I whipped up success.html?
How did I get to that point?
Yeah?
AUDIENCE: Copy and paste.
DAVID MALAN: Yeah, I copied and paste.

English: 
Which again, usually in programming
not the right thing to do.
Might get the job done super fast,
but it's probably the wrong instinct,
because it's going to get
harder and harder to maintain.
Now, why is that?
You've played HTML a
couple of weeks ago.
And recall from that problem set
when you had to make a home page,
you probably found yourselves
copying and pasting across your two,
or three, or four pages because you
wanted them to kind of look the same.
And therefore it made sense for
them to have some commonalities.
But in HTML alone, there was no way to
say use the same layout for my whole
site-- use the same color scheme,
the same fonts, the same CSS--
but just change the body of the
page for each individual page.
And so some of you very rightly
on discourse and beyond like
posted questions asking,
could you do this?
And you can't really in HTML alone.
But now that we have access to
Python, an actual programming language
they can do things logically,
now you can actually
start to factor those things out, too.
And notice in this file, success.html,
as well as in index.html,

Arabic: 
وهذا مجددًا، عادة ليس الشيء الصحيح
للقيام به في البرمجة.
قد يقوم بالوظيفة بسرعة فائقة،
لكن من المحتمل أنه الحدس الخاطئ،
لأن الاحتفاظ به سيصبح
أصعب وأصعب.
الآن، لمَ ذلك؟
لقد قمنا بتشغيل HTML 
منذ أسبوعين.
وتتذكرون من مجموعة المشاكل تلك
عندما كان يجب أن تقوموا بإنشاء صفحة رئيسية،
من المحتمل أنكم قد وجدتم أنفسكم 
تقومون بالنسخ واللصق في صفحتين،
أو ثلاث صفحات، أو أربع صفحات لأنكم أردتم أن تجعلوها
تبدو هي نفسها.
وبالتالي فمن المنطقي
وجود بعض قواسم مشتركة بينها.
لكن في HTML فقط، لم تكن هناك طريقة لقول
استخدم نفس التخطيط للموقع بأكمله--
استخدم نفس مخطط اللون--
نفس الخطوط، CSS نفسها--
لكن غيّر فقط بنية الصفحة
لكل صفحة على حدة.
ولذا قد يقوم بعض منكم بذلك
في هذا الشأن بالتحديد وما ورائه
على سبيل المثال الأسئلة المنشورة التي تسأل،
هل يمكنكم فعل هذا؟
ولكنكم لا يمكنكم فعل ذلك حقًا في HTML فقط.
لكن الآن يمكننا الوصول إلى Python،
لغة برمجة فعلية
يمكنهم القيام بأشياء بطريقة منطقية،
الآن بالفعل يمكنكم
البدء أيضًا في طرح تلك الأشياء.
ولاحظوا في هذا الملف، success.html،
أيضًا في index.html،

Arabic: 
ما هي بعض القواسم المشتركة،
الكافية لقول؟
الشكل في واحد منهم فقط،
لكن ما الأمر
المتكرر أيضًا بصورة واضحة في كل مكان؟
العنوان، رأس الصفحة بصورة عامة أكثر،
doctype في الأعلى،
علامة البنية فقط.
ويمكنكم تخيل أنه يمكن أن توجد تفاصيل أكثر 
مثل الموجودة في صفحاتكم الرئيسية
التي أردتم أن تكون هي نفسها
عبر عدة صفحات.
إذن دعونا نلقي نظرة بالفعل 
على إعادة تحليل هذه التعليمة البرمجية،
التي كتبتُها مسبقًا
في froshim0،
وسترون لمَ يبدو
بالفعل
الحصول ليس فقط على ملفات متعددة،
يمثل كل منها
طريقًا واحدًا من طرقكم
أو وجهات نظركم،
ولكن أيضًا الحصول على هذا الملف 
المُسمى layout.html أمرًا منطقيًا.
في Flask، عند إنشاء
تطبيق ويب كما تعلمون
أنه سيتبع نمطًا بنائيًا معينًا،
قواسم مشتركة
عبر جميع صفحاتكم، 
يمكنكم بالفعل القيام بذلك.
لذا في هذا الملف هنا، layout.html هو مجموعة
كاملة من لغة HTML التي تم ترميزها بشكل ثابت.
وهو أمر بسيط للغاية.
لقد حصل على علامة HTML، وعلامة الرأس،
وعلامة العنوان، وعلامة البنية، وبضعة أشياء أخرى،
لكن هذه هي البنية
العامة للصفحة.

English: 
what are some of the
commonalities, suffice it to say?
The form is only in
one of them, but what
else is obviously redundant everywhere?
The title, the head of the page more
generally, the doctype at the very top,
the body tag alone.
And you could imagine there'd be even
more details like from your own home
pages that you wanted to be
the same across multiple pages.
So let's actually take a look at
a refactorization of this code,
the one I did write in
advance in froshim0,
and you'll see why it
actually makes sense
to have not only multiple
files, each of which
represents one of your
routes or your views,
but also to have this
file called layout.html.
In Flask, when building a
web application that you know
is going to follow a certain
structural pattern, commonalities
across all of your pages,
you can actually do this.
So in this file here, layout.html
is a whole bunch of hardcoded HTML.
And it's pretty simple.
It's got my HTML tag, head tag, title
tag, body tag, and a few other things,
but that's the general
structure of the page.

Arabic: 
ولاحظوا أنها تحتوي على تلك الصيغة الغريبة
في المنتصف.
يوجد في الجزء الأبيض هنا 
ما يُطلق عليه الكتلة.
الآن هذا هو Flask المحدّد.
تمامًا مثلما يدعم Flask تلك الأقواس المتعرجة
على اليسار واليمين
التي تقوم ضَع قيمة
هنا،
كما يدعم flask ذلك التدوين الآخر،
قوس متعرج ونسبة مئوية ونسبة مئوية قوس متعرج
حيث بالفعل يتيح لكم وضع عناصر نائبة 
لأجزاء فعلية من HTML.
ليس فقط متغيرات، 
لكن الأجزاء الفعلية من HTML.
ولذا يمكنكم التفكير في هذا التخطيط
كنموذج أو قالب
حرفيًا حيث ستقومون بإنشاء
جميع صفحاتكم الأخرى بناء عليه،
لكنها ستختلف فى هذا السطر
وهذا السطر فقط.
وسنضع HTML بقدر ما نريد 
بين علامات البنية،
علامة الفتح وعلامة الإغلاق.
هذا يشير فقط إلى Flask 
هذه هي الأشياء التي يجب تغييرها.
لذا إذا نظرتُ الآن في index.html الخاص بي،
وكما تذكرون أنه في وقت سابق
كان يحتوى على الشكل الخاص بي index.html.
لاحظوا أن هذا هو الشكل،
ولقد أنهيتُه في وقت سابق.
عندما مضيتُ قدمًا وكتبتُ
جميع عناوين سكن الطلاب الجدد،
ليس فقط عنوانين منها.

English: 
And notice it has this
funky syntax in the middle.
In white here is what's
called the block.
This is now Flask specific.
Just like Flask supports those
two curly braces on the left
and the right that says
put a value here, flask
also supports this other notation,
curly brace percent and percent curly
brace that actually allows you to put
placeholders for actual chunks of HTML.
Not just variables, but
actual chunks of HTML.
And so this layout you can
think of as a mold or a template
literally that all of your other pages
are going to be structured based on,
but they are going to vary in
this line and only this line.
And we're going to put as much HTML
between the body tags as we want,
the open and the close tag.
This just indicates to Flask this is
the stuff that should be changing.
So if I now look at my
index.html, which recall earlier
contained my form index.html.
Notice that here's the form,
and I finished it earlier.
I went ahead and typed out
all of the freshman dorms,
not just the two of them.

Arabic: 
وسترون أن الملف يبدأ
تقريبًا هو نفسه
ومن ثم يستمر بأشياء أخرى.
لكن لاحظوا ما هو الشيء المفقود من
index.html هذه المرة.
لا يوجد doctype.
لا توجد علامة HTML.
لا توجد علامة رأس، أو علامة عنوان، أو علامة بنية.
تم استبعاد كل تلك
الأشياء المشتركة.
لكن توجد تلك الصيغة الجديدة الغريبة،
مجددًا، هي Flask المُحدّد.
هذا السطر الأول هو الرابط
بين هذا الملف والتخطيط.
هذا السطر الأول يقول،
مرحبًا Flask، هذا ملف index.html
يوّسع نطاق تعريف layout.html.
لذا إنه يقول التقط هذا القالب
وأدخلني هناك.
ما الذي تريد إدخاله؟
الصيغة نفسها هنا.
عندما تضع أشياء بالفعل
بين علامة الكتلة
وعلامة نهاية الكتلة، الموجودة أدناه،
عندما تقولون لـ Flask،
امضي قدمًا وخذ هذه الأشياء
وأدخلها في العنصر النائب في التخطيط.
إذن في الوقت نفسه، يمكن أن تكون
أيضًا صفحة success متطورة أكثر قليلاً الآن.
إذا انتقلتُ إلى success،
إنها ليست معقدة للغاية.
وبصراحة، إنها لا تبدو 
مثل HTML بعد الآن
لأننا نستخدم
هذه الميزات الأكثر ديناميكية.

English: 
And you'll see that the
file starts almost the same
and then continues with more stuff.
But notice what's missing
from index.html this time.
No doctype.
No HTML tag.
No head tag, no title tag, no body tag.
All of the common stuff
has been factored out.
But there's some funky new syntax
that, again, is Flask specific.
This first line is the link
between this file and the layout.
That first line says, hey
Flask, this index.html file
extends the definition of layout.html.
So it says grab that template
and plug myself in there.
What do you want to plug in?
The same syntax here.
When you actually put
stuff between the block tag
and the end block tag, which is down
below, that's when you say to Flask,
go ahead and take this stuff and plug
it into the placeholder in the layout.
So meanwhile, the success page also
now can be a little more sophisticated.
If I go into success,
it's not very complicated.
And honestly, it doesn't
even look like HTML
anymore because we're using
these more dynamic features.

English: 
But this just says, hey
Flask, use the same layout
so the page is structured
exactly the same.
But for the body, go ahead and
plug in this value instead.
So indeed, when you go ahead
and load this success message,
you see this message
here-- not just success,
I expounded here and
said you are registered.
Well, not really, that's
because there's no database yet.
But that's going to generate
a full fledged HTML page.
And what about failure?
Before I was just cheating and
just saying return failure,
quote-unquote, no HTML at all.
The failure page is going
to be almost the same,
but now I can actually
provide some descriptive text.
This body just says you must
provide your name and dorm,
thereby admonishing the user for
not having cooperated properly.
So now your home pages, if you
kind of extrapolate from this,
could have the exact same
layout, aesthetics and menu bars,
and all of that fanciness, but only
the content would have to change.
And you can get out of the business
of just copying and pasting.
So there, too, to your question
earlier about dynamism,
the dynamism doesn't have
to just come from the user.
It can also come from the
construction dynamically of a website
based on multiple pages.

Arabic: 
لكنها فقط تقول، مرحبًا Flask،
استخدم التخطيط نفسه
لذا تم إنشاء الصفحة
بالضبط نفسها.
لكن بالنسبة للبنية،
امضي قدمًا وأدخل هذه القيمة بدلاً من ذلك.
لذا بالطبع، عندما تمضون قدمًا
وتقومون بتحميل رسالة success هذه،
سترون هذه الرسالة
هنا-- ليس فقط success،
أنا أوضحت ذلك هنا
وقلتُ أنكم مسجلون.
حسنًا، ليس بالفعل،
ذلك بسبب عدم وجود قاعدة بيانات حتى الآن.
لكن هذا سيقوم بإنشاء
صفحة HTML كاملة.
وماذا عن failure؟
قبل ذلك كنت فقط أخادع
وأقول فقط أعِد failure،
علامة اقتباس وعلامة إنهاء الاقتباس،
ليست HTML على الإطلاق.
ستكون صفحة failure
هي نفسها تقريبًا،
لكن الآن يمكنني بالفعل 
أن أقدّم بعض النصوص الوصفية.
تقول تلك البنية فقط يجب
أن تقدم اسمك وسكنك،
حيث يتم تحذير المستخدم 
من عدم التعاون بشكل صحيح.
لذا الآن صفحاتكم الرئيسية،
إذا استنتجتم من ذلك،
أنه قد يحتوي على نفس التخطيط،
والجماليات، وشرائط القائمة،
وكل تلك الأمور الرائعة،
لكن يجب أن يتغير المحتوى فقط.
ويمكنكم الانتهاء من ذلك
فقط بالنسخ واللصق.
لذا هناك، أيضًا، بالنسبة إلى سؤالك
في وقت سابق عن الديناميكية،
لا يجب أن تأتي الديناميكية
فقط من المستخدم.
يمكن أن تأتي أيضًا من البنية
بشكل ديناميكي من موقع ويب
قائم على عدة صفحات.

English: 
So at the end of the
day, the browser has
no idea that Python exists,
has no familiarity with Flask.
All the browser still
sees is an HTML page.
But what Flask and in
turn Python are doing
for us is constructing that
page dynamically, following
the rules from two weeks
to go in HTML and CSS,
and following last week's
rules on how Python works.
Questions?
AUDIENCE: So even though [INAUDIBLE]
DAVID MALAN: It's not.
Good question.
This new syntax, the double curly
braces that we saw earlier and now
the curly brace percent signs, this
is actually yet another language
called jinja--
J-I-N-J-A-- which is
a templating language.
And there's dozens of these things
in the world, people just come up
with their own syntax.
And the reason for the funky
syntax is that the author of jinja
presumably could think
of no other language that

Arabic: 
إذن في نهاية اليوم،
لن يكون لدى المتصفح أدنى فكرة عن
وجود Python،
ولن يكون معتادًا على استخدام Flask.
ما تزال جميع المتصفحات
ترى أنها صفحة HTML.
لكن ما يقوم به Flask وPython بدورها
من أجلنا
هو إنشاء تلك الصفحة بشكل ديناميكي،
حيث تتبع القواعد
منذ أسبوعين
حيث بدأنا مناقشة HTML وCSS،
وتتبع قواعد الأسبوع الماضي
بشأن كيفية عمل Python.
أي أسئلة؟
الجمهور: إذن حتى لو [INAUDIBLE]
ديفيد ج. مالان: إنها ليست كذلك.
سؤال جيد.
تلك الصيغة الجديدة، الأقواس المتعرجة المزدوجة
التي رأيناها قبل ذلك والآن
القوس المتعرج علامات النسبة المئوية،
هذه بالفعل لغة جديدة حتى الآن
يُطلق عليها jinja--
J-I-N-J-A-- وهي
لغة نموذجية.
وتوجد العشرات من تلك الأشياء 
في العالم، وقدّم الأشخاص
الصيغة الخاصة بهم.
والسبب وراء الصيغة الغريبة
هو أن مخترع jinja
قد فكّر بشكل افتراضي في
أنه لا توجد لغة أخرى

Arabic: 
تستخدم قوس متعرج
وعلامة النسبة المئوية
وعلامة النسبة المئوية وقوس متعرج.
وبالتالي قرر،
أنتم تعرفون ذلك،
أنا سأستخدم تلك الصيغة
لأنها ستبدو مختلفة عن HTML،
وCSS، وPython 
لذا إطار العمل ذلك مثل Flask
لا يخلط بينها وبين شيء آخر.
الجمهور: إذن هل يجب أن تقوم بتحميل ذلك في
[INAUDIBLE]، أم يحدث ذلك بشكل تلقائي؟
ديفيد مالان: يتم دعمه
بشكل تلقائي.
إذن Flask بشكل افتراضي يدعم jinja.
قد تظهر مع الصيغة
النموذجية الخاصة بها.
لكن أيًا كان الشخص الذي اخترع Flask
فقد قرر أنا لا أحتاج إلى إعادة ابتكار تلك العجلة،
قام شخص آخر بالفعل بإنشاء
لغة نموذجية
وهي تعطيني هذه الدالة.
لذا سأقوم
بدمج عملنا معًا في عمل واحد.
ولم أطلق عليه 
لغة منذ قليل،
لأنه بصراحة ،HTML، CSS
--Python، JavaScript
أعني، لدينا بالفعل
لغات كثيرة هنا.
لكن jinja، في الواقع،
لغة أخرى حتى الآن.
إنها ليست مجرد لغة برمجة
في حد ذاتها،
على الرغم من أنها ستحتوي على
بعض ميزات التحكم في التدفق
التي سنراها في غضون لحظات.
إنها فقط محدودة أكثر من Python.
أي أسئلة أخرى؟
الجمهور: هل من الممكن الجمع بين ملفي
success وFailure. HTML
في ملف واحد فقط ليكون التصميم أفضل؟
ديفيد مالان: سؤال جيد.

English: 
uses like a curly brace
and a percent sign
and a percent sign and a curly brace.
And so therefore they
decided, you know what,
I'm going to use this syntax because
it will look distinct from HTML,
and CSS, and Python So
that frameworks like Flask
don't confuse it with something else.
AUDIENCE: So do you have to upload that
into [INAUDIBLE],, or is it automatic?
DAVID MALAN: It's
automatically supported.
So Flask by default supports jinja.
It could have come up with
its own templating syntax.
But whoever invented Flask decided
I don't need to reinvent this wheel,
someone else already made
a templating language
that gives me this functionality.
So I'm going to combine
our works into one.
And I didn't call it a
language a moment ago,
because frankly, HTML,
CSS, Python, JavaScript--
I mean, we're already
running out of fingers here.
But jinja is, indeed,
yet another language.
It's just not a programming
language per se,
though it will have some
control flow features
that we'll see in a little bit.
It's just much more limited than Python.
Other questions?
AUDIENCE: Is it possible to combine
the success and failure HTML
files into one just for better design?
DAVID MALAN: Good question.

Arabic: 
هل يمكن أن تجمع بين صفحتي success
وfailure في صفحة واحدة؟
إجابة مختصرة، أجل.
ودعوني لا أعرض ذلك الآن، لأن الأمر
سيكون أكثر تعقيدًا.
لكن أجل، قد أتخيل تمرير متغيرات فيها
ذلك أمر منطقي--
صحيح أم خاطئ--
فقط في أحد هذه القوالب.
وربما أطلق على القالب الجديد
result.html.
بالفعل يمكنني بعد ذلك أن أحصل على شرط
إذا في القالب الخاص بي الذي
يقول إذا كانت النتيجة صحيحة، قل هذا.
وأيضًا إذا كانت النتيجة
خاطئة، قل ذلك الشيء الآخر.
لذا يمكنكم فعل هذا، أجل.
بشكل عام، على الرغم من ذلك، من المحتمل
أنه من الجيد الحفاظ على الرسائل منفصلة
إذا كانت تقوم بشيء آخر من الناحية الوظيفية.
في النهاية، هذه الملفات
صغيرة جدًا على كل حال.
أجل؟
الجمهور: فقط كسؤال،
ماذا يرى المستخدم
إذا كانت ستفتح وحدة التحكم
في تصحيح الأخطاء على Chrome
ونظر فيها، ما الذي يراه
حيث HTML هي التي تظهر؟
ديفيد مالان: سؤال جيد حقًا.
ما الذي يراه المستخدم؟
يمكننا الإجابة على ذلك حرفيًا بمجرد
فتح Chrome وفتح
عرض مصدر الصفحة أو مركز التحكم.
هذا ما يراه المتصفح.
لذا عندما قلتُ في وقت سابق أن المتصفح
ليس لديه أي فكرة عن أن Python أو Flask

English: 
Could you combine the success
and the failure pages into one?
Short answer, yes.
And let me not show it yet, because
it'll get a little more complicated.
But yes, I could imagine passing
a variable in that's a Boolean--
true or false--
into just one of these templates.
And maybe I call the new
template result.html.
I can actually then have an if
condition in my template that
says if the result is true, say this.
Else if the result is
false, say this other thing.
So you could do that, yes.
Generally, though, it's probably
cleaner to keep messaging separate
if they functionally do something else.
After all, these files
are pretty small anyway.
Yeah?
AUDIENCE: Just for
question, what does the user
see if they were to open up
the debugging console on Chrome
and look at at it, what do they
see as the HTML that shows up?
DAVID MALAN: Really good question.
What does the user see?
We can answer this by just
literally opening Chrome and opening
View Page Source or the Inspector.
This is what the browser sees.
So when I claimed earlier that the
browser has no idea of Python or Flask

Arabic: 
متضمنتان،
هذا، بالفعل، أمر صحيح.
لأن ما يستقبله المتصفّح
في نهاية الأمر
هو فقط هذه،
HTML التي تم إنشاؤها بشكل ديناميكي.
سؤال جيد.
أجل؟
الجمهور: [INAUDIBLE] هل يمكنك أيضًا
وضع تعليمة Python البرمجية هناك،
أم HTML فقط؟
سؤال جيد.
سنرى أشياء أكثر عن ذلك
في غضون لحظات.
السؤال هو، هل يمكنك بين
القوس المتعرج وعلامات النسبة المئوية
وضع تعليمة Python البرمجية بالفعل؟
يمكنك وضع أشياء تبدو مثل
تعليمة Python البرمجية، ولكن ليس كل Python.
ولذا أكثر من ذلك بعض الشيء.
الجمهور: هل توجد دالة
تقوم بالاستدعاء أو شيء من هذا القبيل؟
ديفيد مالان: فقط دالات معينة.
اللغات النموذجية، قصة قصيرة
مطولة، هي أدوات تحديد الوصول لذا
هي ليست معبرة تمامًا مثل
لغات برمجة حقيقية.
وإلا كنتم معرضين لاختراقات
محتملة.
تريدون أن تكون دالتها
محدودة للغاية لأنها
فقط عن عرض البيانات، وليست عن التفكير
أو القيام بشكل عام بما هو منطقي.
المزيد حول ذلك في غضون لحظات.
حسنًا، كان ذلك كثيرًا في مرة واحدة.
دعونا نأخذ استراحة لمدة خمس دقائق،
هنا، قم بتشغيل بعض الموسيقى، وسنعود،
وسنجعل هذا يعمل بشكل أفضل.
حسنًا، لقد عدنا.
إذن لنلخص ما توصلنا إليه في
froshim0، نحن الآن
لدينا هذه البنية والتي
هي تقليدية إلى حد كبير.

English: 
are even involved,
that is, indeed, true.
Because what browser's
receiving at the end of the day
is just this, the
dynamically constructed HTML.
Good question.
Yeah?
AUDIENCE: [INAUDIBLE] can you
also put Python code in there,
or is it just HTML?
Good question.
We'll see more of this
in just a little bit.
The question is, can you between
the curly brace and percent signs
put actual Python code?
You can put stuff that looks like
Python code, but not all of Python.
And so more of that in a bit.
AUDIENCE: Is there a function
call or something like that?
DAVID MALAN: Only certain functions.
Templating languages, long
story short, are sandbox so
that they are not as expressive
as a real programming language.
Otherwise you are vulnerable
to potential hacks.
You want their functionality to
be very limited because they're
only about displaying data, not about
thinking or doing logic generally.
More on that in a bit.
All right, that was a lot all at once.
Let's take a five minute break
here, turn on some music, come back,
and we'll make this act better.
All right, we are back.
So to recap where
froshim0 left off, we now
have this structure which
is pretty much conventional.

Arabic: 
أي تطبيق ويب
نقوم بإنشائه هنا
سيتبع هذا النمط من امتلاك نقطة دخول
application.py حيث
تبدأ كل الأشياء الممتعة،
ملف layout.html
في دليل القوالب الخاص بكم
الذي يحدّد
الموقع بالكامل وأي قواسم مشتركة،
ومن ثم صفحة واحدة أو بضع صفحات أخرى
بالفعل تمثل وجهة نظركم الفردية
التي تتوافق مع طريق واحد أو أكثر
من طرقكم الفعلية.
لذا نحن الآن عند نقطة
خط الأساس الثابت،
لكن هل تعمقنا في هذا بالطريقة الصحيحة،
قد لا يكون الأمر منطقيًا
لماذا قمنا
بتلك التحليلات المختلفة.
لذا دعونا الآن نقوم بتحسين ذلك.
لأنه بالطبع، إذا
نظرتم في success.html،
فإنه يزعم فقط أنكم مسجلون.
حسنًا، ليس تمامًا.
لأن في application.py، هل فعلنا
أي شيء باستخدام معلومات المستخدم؟
لا.
لقد تحقّقنا فقط، هل
أعطانا معلومات؟
وإذا كان الأمر كذلك، فإننا نزعم success.
وأيضًا إذا نسي اسمه و/أو
مسكنه، فنزعم failure.
إذن ما هي بنية البيانات
في Python
حيث يمكننا تخزين المسجلين؟
ليست لدينا قواعد بيانات
حتى الآن، ليست لدينا SQL بعد.
هذا في الأسبوع المقبل.
الجمهور: مصفوفة.
ديفيد ج. مالان: أجل، يمكننا
استخدام مصفوفة، أو ما هو معروف

English: 
Any web application
we make here on out is
going to follow this pattern of having
an application.py entry point where
all the interesting stuff
starts, a layout.html file
in your templates
directory that lays out
the whole site and any commonalities,
and then one or more other pages that
actually represent your individual
views that correspond to one or more
of your actual routes.
So now we're at the point
of a stable baseline,
but had we dived in right to this, it
would perhaps not make as much sense
as to why we did this
various factorization.
So let's now improve this.
Because of course, if
you look at success.html,
it just claims you are registered.
Well, not really.
Because in application.py, did we do
anything with the user's information?
No.
We just checked, did
they give us information?
And if so, we claim success.
Else if they missed their name and/or
their dorm, we just claimed failure.
So what might a data
structure be in Python
where we could store registrants?
We don't have databases
yet, we don't have SQL yet.
That's a week ahead.
AUDIENCE: Array.
DAVID MALAN: Yeah, we could
use an array, otherwise known

English: 
as a list in Python.
So let me propose how we might do this.
Let me actually open up froshims1 for
our second iteration of this program.
And in application.py, notice this.
At the very top of the
file, not only am I
creating my application using
the same line as before,
and I've commented things this time
in advance using the hash symbol,
notice that I claim that
on line 6 and 7 here, here
is an empty list for all of the
students who have registered.
This way we can keep
the information around.
And we only did this briefly
last time, but does anyone
remember how you add
something to a list in Python?
By what function?
Append.
So if you have .append at
the end of a list's name,
you can add something to it.
So where is that going to go?
Well, here is my route for slash,
implies, again, get by default.
That's the default route
that a human might get,
and they are going to see
index.html, which contains that form.
If I scroll down now, you'll see that I
have a register route just like before.
But I'm doing one additional step.

Arabic: 
بالقائمة في Python.
لذا دعوني أقترح كيف يمكننا القيام بذلك.
دعوني بالفعل أفتح froshims1 
للمرة الثانية في هذا البرنامج.
وفي application.py، لاحظوا ذلك.
في الجزء العلوي من الملف،
لا أقوم فقط
بإنشاء تطبيقي باستخدام
السطر نفسه كما كان من قبل،
ولقد أشرتُ إلى أشياء هذه المرة
مسبقًا باستخدام رمز علامة التجزئة،
لاحظوا أنني زعمتُ أن
في السطر 6 والسطر 7 هنا، هنا
قائمة فارغة لجميع
الطلاب الذين سجلوا.
بهذه الطريقة يمكننا الاحتفاظ
بالمعلومات.
وقمنا بهذا فقط بشكل موجز
آخر مرة، لكن هل يتذكر أي شخص
كيف نضيف
شيئًا إلى قائمة في Python؟
باستخدام أي دالة؟
Append.
إذن إذا كانت لديكم دالة append.
في نهاية اسم قائمة،
يمكنكم إضافة شيء إليها.
إذن إلى أين سيؤدي ذلك؟
حسنًا، هذا طريقي الخاص بخط مائل،
يشير، مجددًا، إلى الحصول بشكل افتراضي.
هذا هو الطريق الافتراضي
الذي قد يحصل عليه شخص،
وسيرى index.html، الذي
يحتوي على هذا الشكل.
إذا قمتُ بالتمرير الآن، سترون أن
لديّ طريق تسجيل كما كان لدي مسبقًا.
لكنني أقوم بخطوة واحدة إضافية.

English: 
Which is the new line here, to be clear?
Yeah, 26.
So I could implement this
in any number of ways.
But the key detail is that I
reference the list name-- students,
but I could have called it anything.
.append, as someone proposed, is how you
add something to the end of the list.
And then I can add anything I want.
To keep it simple, I'm
just going to add a string.
And I'm going to keep
it super simple and just
say the string is so-and-so
from such and such a dorm.
So David from Matthews Hall,
or Brian from wherever.
And so here we have placeholders
using f strings in Python.
So this has nothing
to do with Flask, this
has nothing to do with jinja or
anything we just talked about.
This has to do everything with
last week's syntax in Python alone.
So this appends to that list
this name from this dorm.
So let's go ahead now
and try this version out.
If I go into my source sub and directory
for today's code into froshims1
and run flask run, we'll see
a URL that I can now visit.
Let me go ahead and
open that for froshims1.
Notice that I have that
complete dropdown now.

Arabic: 
ما هو السطر الجديد هنا، لأكون واضحًا؟
نعم، 26.
إذن يمكنني تنفيذ هذا
بطرق متعددة.
لكن التفصيل الرئيسي هو أنني
أُشير إلى اسم القائمة-- students،
لكن يمكنني تسميتها بأي شيء.
.append، كما اقترح شخص ما، وهي كيف تضيفون
شيئًا إلى نهاية القائمة.
ومن ثم يمكنني إضافة أي شيء أريده.
لأبقي الأمر بسيطًا،
سأقوم فقط بإضافة سلسلة.
وسأبقيها
بسيطة للغاية وأقول
فقط السلسلة ذاك وذاك
من كذا وكذا هي سكن.
إذن دايفيد من ماثيوز هول،
أو براين من أي مكان.
وهكذا لدينا هنا عناصر نائبة
عبر استخدام سلاسل f في Python.
إذن فإن هذا ليس له
علاقة بـ Flask، هذا
ليس له علاقة بـ jinja أو
أي شيء تحدثنا عنه للتو.
هذا متعلق بشكل كامل بصيغة
الأسبوع الماضي في Python فقط.
إذن هذا يُلحق بتلك القائمة
هذا الاسم من هذا السكن.
إذن دعونا نمضي قدمًا الآن
ونُجرّب هذا الإصدار.
إذا انتقلتُ إلى المصدر الفرعي ودليل
تعليمة اليوم البرمجية في froshims1
وقمتُ بتشغيل flask، سنرى
عنوان URL الذي يمكنني زيارته الآن.
دعوني أمضي قدمًا
وأفتح ذلك من froshims1.
لاحظوا أن لديّ قائمة
منسدلة كاملة الآن.

Arabic: 
دعوني أمضي قدمًا وأقول ديفيد، ولكن
لن أخبركم بالسكن الخاص بي
حتى الآن وأحاول التسجيل.
الآن أرى رسالة ودودة أكثر،
وليست رسالة failure فقط.
وهذا بسبب القالب
الجديد المُحسّن.
حسنًا، سأمضي قدمًا وأكون ديفيد،
وسأكون من ماثيوز هنا.
دعوني أمضي قدمًا وأُقوم بالتسجيل وها هو ذا.
الآن نرى أن ديفيد من
ماثيوز تم تسجيله.
ويبدو أنه بشكل مفاجئ أصبح
في شكل قائمة نقطية جديدة.
ولكن في الواقع من أين جاء ذلك؟
حسنًا، لا أعلم.
دعوني أحاول ذلك مجددًا.
دعوني أعود لأكتب خط مائل، وهو
الطريق الذي يعطيني الشكل.
دعوني أمضي قدمًا وأكتب ليس
ديفيد هذه المرة، ولكن لنقل، براين.
براين، أي سكن تعيش فيه؟
الجمهور: بيني بايكر.
ديفيد مالان: بيني بايكر.
إذن دعوني أختار هذا من القائمة
بدلاً من ذلك وأنقر فوق تسجيل.
والآن نرى براين من بيني بايكر.
إذن بطريقة ما يقوم التطبيق
بتغيير الحالة،
ولاحظوا أن عنوان URL الذي نحن فيه
يُسمى خط مائل المُسجلون.
إذن يبدو أن ذلك طريق ثالث هذه المرة
وهو على ما يبدو غير تفاعلي
في حد ذاته، إنه يُظهر فقط
قائمة الطلاب المُسجلِين.
إذن دعونا فقط نضع
قبعة التصميم المشهورة.
إذا قمنا بتنفيذ
طريق خط مائل المُسجلون

English: 
Let me go ahead and say David, but
I'm not going to tell you my dorm
yet and try to register.
Now I see a more friendly
message, not just failure.
And that's because of my
new and improved template.
OK, I'll go ahead and be David,
and I'll be from Matthews here.
Let me go ahead and register and voila.
Now we see David from
Matthews has registered.
And it seems to be all of a sudden
in the form of a new bulleted list.
But where did that actually come from?
Well, I don't know.
Let me try this again.
Let me go back to slash, which is
the route that gives me the form.
Let me go ahead and type in not
David this time, but say, Brian.
And Brian, which dorm are you in?
AUDIENCE: Pennypacker.
DAVID MALAN: Pennypacker.
So let me choose this from the
menu instead and click Register.
And now we see Brian from Pennypacker.
So somehow the application
is changing state,
and notice the URL that we're
at is called slash registrants.
So that seems to be a third route this
time that apparently is not interactive
per se, it just spits out the
list of registered students.
So let's just put the
proverbial engineering hat on.
If we go about implementing
this slash registrants route,

Arabic: 
بشكل منطقي ما الذي يجب أن تفعله هذه التعليمة البرمجية
في تعليمة برمجية زائفة لفظية، إذا صح التعبير؟
الجمهور: تكرار حلقي من النوع for؟
دايفيد مالان: مثل تكرار حلقي من 
النوع for، يكرّر ماذا؟
الجمهور: في القائمة التي
تحفظ جميع المُسجلين.
ديفيد مالان: أجل.
يكرر قائمة الطلاب
التي
تحتوي على جميع هؤلاء المُسجلين.
ويحتوي القالب، في الوقت نفسه، على الأرجح
على علامة LI لعنصر قائمة
وعلامة UL لقائمة غير مرتبة،
وهذا يعطيني قائمة نقطية.
إذن، دعونا نلقي نظرة على ذلك.
إذن، كيف نتبع هذه الآثار؟
حسنًا، إذا قمتُ بالتمرير إلى أعلى في
application.py، سنرى
طريق يُسمي خط مائل المُسجلون.
وسترون أن
كل ما يفعله على ما يبدو
هو أنه يقوم بإرجاع قالب
يُسمي registered.html،
حيث يُعد registered.html على الأرجح
قالب يقوم بإنشاء تلك القائمة.
ولكن هناك شيء
مختلف هذه المرة.
أقوم بتمرير وسيطة.
ولقد رأينا ذلك في وقت سابق.
عندما أردتُ تمرير اسم
يساوي ديفيد أو اسم يساوي براين،
فقط سحبتُ ذلك من متغير.
هذه المرة لن أقوم بكتابة request.args،
ولن أقوم بكتابة request.form.
لأن ما هو students؟

English: 
logically what must that code be doing
in verbal pseudocode, if you will?
AUDIENCE: A for loop?
DAVID MALAN: Like a for
loop, iterating over what?
AUDIENCE: In the list that
saves all the registrants.
DAVID MALAN: Yeah.
Iterating over the
list of students which
contains all of those registrants.
And the template, meanwhile, probably
has like an LI tag for list item
and a UL tag for unordered list,
which gives me the bulleted list.
So let's take a look at that.
So how do we follow these breadcrumbs?
Well, if I scroll up in
application.py, we'll
see a route called slash registrants.
And you'll see that
all it does apparently
is it returns a template
called registered.html,
where registered.html is probably a
template that is generating that list.
But there's something
different this time.
I'm passing in an argument.
And we saw this earlier.
When I wanted to pass in name
equals David or name equals Brian,
I just grabbed that from a variable.
This time I'm not doing request.args,
I'm not doing request.form.
Because what is students?

Arabic: 
من أين أتى هذا؟
من هذه القائمة في الأعلى.
تذكرون أن لدينا هذا المتغير الشامل
في أعلى البرنامج، students،
الذي تتم تهيئته إلى قائمة فارغة.
لكن تذكرون أننا نستمر في إلحاقه
في طريق التسجيل الخاص بي.
إذن يمكنني أن أمضي قدمًا
وأقول، أتعلمون ماذا؟
امضي قدمًا وقُم بالتمرير في قالب register.html--
أو بدلاً من ذلك، قائمة--
تُسمى students وقيمتها
هي ذلك بالضبط.
ومجددًا، هذا الأمر يبدو غبيًا حيث يكون
لديكم الكلمة نفسها على يسار
ويمين اسم المتغير.
يمكنكم القيام بذلك بشكل مختلف.
مجددًا، يمكنكم أن تقولوا foo، يمكنكم أن تقولوا
x أو y أو أي شيء.
لكن بصراحة، يبدو منطقيًا أكثر،
فقط عندما تقومون
بتمرير اسم المتغير نفسه الذي
تهتمون لأمره بحيث يمكن أن يرى القالب
ذلك بالضبط.
إذن ما هي الآثار التالية؟
إذا أردتُ أن أفهم
بالضبط ما يحدث،
أي ملف من المحتمل أنه يجب أن أفتحه بعد ذلك؟
ربما register.html.
إذن دعونا ننتقل إلى هناك.
إنها في دليل القوالب
حسب التعريف،
وسترون، في الواقع، رسالة failure
التي تتيح لي فحص الأخطاء.
الفهرس، الذي يحتوي على الشكل؛ التخطيط،
الذي يحتوي على البنية العامة؛
وأخيرًا، registered.html.

English: 
Where did this come from?
That's the list from higher up.
Recall that we have this global variable
at the top of the program, students,
which is initialized to an empty list.
But recall that we keep appending
to it in my register route.
So I can go ahead and
say, you know what?
Go ahead and pass into register.html
a template-- or rather, a list--
called students whose
value is exactly that.
And again, it's stupid looking that
you have the same word on the left
and the right of the variable name.
You could do this differently.
Again, you could say foo, you
could say x, or y, or anything.
But frankly, it tends to
make most sense, just pass
in the same name as the variable that
you care about so that the template can
see exactly that.
So what's the next breadcrumb?
If I want to understand
exactly what is happening,
what file should I open up next perhaps?
Probably register.html.
So let's go in there.
It's in my templates
directory by definition,
and you'll see, indeed, a failure
message which allows me to error check.
Index, which contains the form; layout,
which contains the overall structure;
and finally, registered.html.

Arabic: 
والآن يمكننا الإجابة على السؤال الذي
ألقيته في وقت سابق عن تعليمة Python البرمجية
في القالب.
إذن هذا يبدو متطور أكثر
من قبل،
لكن لاحظوا أنه يتبع نمطًا.
يوسّع Register.html ذلك التخطيط نفسه.
إذن يستعير من النموذج نفسه، لذلك يبدو نفسه.
إن بنية هذه الصفحة، على الرغم من ذلك،
هي هذا المقتطف من HTML فقط.
أعطني قائمة غير مرتبة،
مفتوحة ومغلقة، وهذا
ما يمكنكم القيام به الآن باستخدام jinja.
مجددًا، إنها تقريبًا
مُطابقة للغة Python، إذن
لا داعي للقلق بشأن التفكير
في تعلم لغة أخرى بعد.
إنها مجرد مجموعة فرعية من
Python بشكل أساسي.
إذن إذا أردتُ الإخراج في
قائمة جميع الطلاب،
أستخدم صيغة jinja هنا، صيغة القالب 
بقوس متعرج نسبة مئوية.
وأقول for student في students.
تمامًا مثل Python، والذي ينتج عنه
تكرار تلك القائمة.
ومن ثم ما الذي أُريد إخراجه؟
حسنًا، يمكننا أن نستعير الأقواس
المتعرجة من مثال الاسم
ونقوم فقط بفتح عنصر قائمة، ونُدخل
اسم الطالب، ونغلق عنصر القائمة.
ومن ثم endfor.
إذن هذا هو الشيء
الوحيد الغبي باستخدام القوالب.
بينما في Python الصحيحة،
تذكرون أنه يمكنكم فقط

English: 
And now we can answer the question that
you asked earlier about Python code
in the template.
So this one looks more
advanced than before,
but notice it follows a pattern.
Register.html extends that same layout.
So it borrows from that same
mold, so it looks the same.
The body of this page, though,
is just this snippet of HTML.
Give me an unordered list,
open and closed, and this
is what you can do now with jinja.
Again, it's almost
identical to Python, so you
don't have to worry about thinking
about learning yet another language.
It's just a subset of
Python essentially.
So if I want to output in the
list of all of the students,
I use my jinja syntax here, my template
syntax with curly brace percent.
And I say for student and students.
Just like in Python, that induces
an iteration over that list.
And then what do I want to output?
Well, we can borrow our curly
braces from our name example
and just do list item, plug in the
name of the student, close list item.
And then endfor.
So this is the one stupid
thing with the templates.
Whereas in Python proper,
recall that you can just

English: 
say for student in
students, you have a colon
and then indentation handles everything.
The problem with that
in the world of HTML
is that browsers recall
ignore all whitespace,
like whitespace has no special
significance, but in Python it does.
So the way people solve
this is you literally,
if a little weirdly, say endfor--
one word, no space.
And that's it.
And indentation helps you
read something like this.
So what is the HTML I'm getting back?
I can actually look at this.
Let me go ahead and view
page source in Chrome,
and you'll see it's not quite
as pretty as might be ideal
because there's a lot of whitespace
which comes from those templates
from my having pretty
printed those, as well.
But this is syntactically correct,
and I'm dynamically putting
this part inside of this layout.
Any questions, then, on this?
AUDIENCE: So if we restart
the server, whatever's stored
in the list, that goes away, right?
DAVID MALAN: Good question.
Let's kill Flask with control-c.
Let's rerun the server.
And let me go back to my
registrants route and reload.

Arabic: 
أن تقولوا for student في
students، لديكم نقطتين
ومن ثم تعالج المسافة البادئة كل شيء.
هذه المشكلة
في عالم HTML
هي أن المتصفحات تتذكر
تجاهُل جميع المسافات،
على سبيل المثال المسافة ليس لها أهمية
خاصة، ولكن لها أهمية خاصة في Python.
إذن، الطريقة التي يحل بها الأشخاص
هذا هي حرفيًا،
وإن كانت غريبة قليلاً، قول endfor--
كلمة واحدة، بدون مسافة.
وهذا كل شيء.
وتساعدكم المسافات البادئة على
قراءة شيء كهذا.
إذن ما هي HTML التي أقوم باسترجاعها؟
يمكنني بالفعل النظر في هذا.
دعوني أمضي قدمًا وأعرض
مصدر الصفحة في Chrome،
وسترون أنها ليست جميلة تمامًا
بقدر ما قد تكون مثالية
لأن هناك الكثير من المسافات
والتي تأتي من تلك القوالب
عندما قمتُ بطباعة
هذه، أيضًا.
ولكن هذا صحيح من الناحية البنائية،
وسأقوم بإخراج
هذا الجزء داخل هذا التخطيط بشكل ديناميكي.
أي أسئلة، بعد ذلك، حول هذا؟
الجمهور: إذن إذا أعدنا تشغيل
الخادم، أيًا كان ما تم تخزينه
في القائمة، ويختفى، أليس كذلك؟
ديفيد مالان: سؤال جيد.
دعونا نوقف تشغيل Flask باستخدام control-c.
دعونا نُعيد تشغيل الخادم.
ودعوني أعود إلى طريق
المسجلين الخاص بي وأعيد التحميل.

Arabic: 
وللأسف، نعم، هذه ليست أفضل
طريقة لتسجيل الطلاب في رياضة.
لأنه إذا أصبح الخادم غير متصل،
أو فقد الطاقة، أو قمتم بالضغط على control-c،
بالتأكيد ستفقدون الجميع بالفعل.
ولاحظوا، أيضًا، على
الرغم من أننا بشكل عام
رفضنا استخدام المتغيرات الشاملة،
وهو الأمر نفسه بالنسبة لقائمة الطلاب هذه،
لمَ قمتُ بتعريفها
هنا بالأعلى في السطر 7 وليس،
على سبيل المثال، في طريق التسجيل الخاص بي هنا؟
لأن في الواقع، أقوم
بالإلحاق إلى القائمة هنا.
لكنني لم أعلن عن القائمة
بشكل متعمد هناك.
أجل؟
الجمهور: تستخدمها
في أجزاء أخرى.
ديفيد مالان: أستخدمها في مكان آخر في
الطرق الأخرى، طريق المُسجلين.
وأيضًا فيما يتعلق بأكثر من هذه النقطة،
إذا أعلنتُ عن قائمة هنا،
تصبح حسب التعريف
متغيرًا محليًا.
وهو ما يعني أنه بمجرد
أن توجد هذه الدالة،
الآن سأستغني عن هؤلاء
الطلاب الذين يُسجلون بشكل فوري
وليس حتى بعد الضغط على control-c.
إذن كان هذا أفضل نهج
للقيام بذلك، لكنه ليس
ما قمتُ به فيما قبل.
لقد قمتُ في الواقع بشيء
أفضل قليلاً.
إذن في ذلك الوقت، لم
أعلم حقًا-- على الأقل في،
أي عام، 1997-- أي شيء عن قواعد البيانات.

English: 
And sadly, yes, this is not the best
way to register students for a sport.
Because if the server ever goes
offline, loses power, you hit control-c,
you obviously, indeed, lose everyone.
And notice, too, even
though we've generally
frowned upon using global variables,
which this students list indeed
is, why did I define it
up here in line 7 and not,
for instance, in my register route here?
Because indeed, I'm
appending to the list here.
But I very deliberately did
not declare the list there.
Yeah?
AUDIENCE: You're using
it in other parts.
DAVID MALAN: I'm using it elsewhere in
my other routes, the registrants route.
And also even more to the point,
if I declared a list here,
it becomes by definition
a local variable.
Which means as soon as
this function exits,
now I've just thrown away those
students who register immediately not
even after a control-c.
So this was a better approach
to do it, but it's not
what I did way back in my day.
I actually did something
that was a little fancier.
So at the time, I didn't
really know-- at least in,
what, 1997-- anything about databases.

English: 
I don't think I even knew about
CSV files just yet, or at least
how to create them dynamically.
So I instead took this approach.
Let me go into froshims2, and it has
noticed the same templates as before.
And indeed, I pretty much copied
and pasted for this second example.
But in application.py,
notice this fanciness.
So here I have almost the same
thing up top in terms of Flask,
but I'm also using this OS
library, more on that in a bit.
But what about line 2?
It's subtle, but I rattled this acronym
off I think just once weeks ago, SMTP.
Does anyone know what that stands for?
AUDIENCE: Simple mail transfer protocol?
DAVID MALAN: Yeah, simple mail
transfer protocol-- email, that is.
So Python comes with
built in functionality
via which you can send emails,
and this is exactly what I
did when I first made this website.
Didn't know anything about
databases, I didn't know anything
about saving things to files
just yet, I was still learning.
But I didn't realize, hm,
I could use programming
to send an email to the proctor or
the RA who was overseeing the sports
program so that they could
just save it in a folder

Arabic: 
لا أعتقد أنني كنتُ أعلم حتى بشأن
ملفات CSV حتى الآن، أو على الأقل
كيفية إنشائها بشكل ديناميكي.
إذن بدلاً من ذلك اتخذتُ هذا النهج.
دعوني أنتقل إلى froshims2، وقد
لاحظ نفس القوالب كما كانت من قبل.
وبالفعل، قمتُ بالنسخ واللصق
بشكل كبير لهذا المثال الثاني.
ولكن في application.py،
لاحظوا هذا الأمر الرائع.
إذن هنا لديّ تقريبًا الشيء نفسه
بالأعلى من حيث Flask،
ولكنني أستخدم أيضًا مكتبة نظام التشغيل
هذه، المزيد حول ذلك بعد قليل.
ولكن ماذا عن السطر 2؟
إنه دقيق، ولكنني تحدثتُ بشأن هذا الاختصار
أعتقد مرة واحدة فقط منذ أسابيع، SMTP.
هل يعرف أحدكم ما الذي يشير إليه ذلك؟
الجمهور: بروتوكول إرسال البريد البسيط؟
ديفيد مالان: نعم، بروتوكول إرسال
البريد البسيط-- البريد الإلكتروني، وهو كذلك.
إذن تأتي Python مع
دالة مُدمجة
والتي يمكنكم عبرها إرسال رسائل البريد الإلكتروني،
وهذا هو بالضبط ما
فعلتُه عندما قمتُ بإنشاء هذا الموقع أول مرة.
لم أعرف أي شيء عن قواعد
البيانات، ولم أعرف أي شيء
عن حفظ أشياء في ملفات
بعد، ما زلتُ أتعلم.
ولكنني لم أدرك، امم،
أنه يمكنني استخدام البرمجة
لإرسال رسالة بريد إلكتروني إلى المراقب أو
RA الذي كان يُشرف على برنامج
الرياضة حتى يتمكّن فقط
من حفظه في مجلد

English: 
and know who had registered.
It's not super user
friendly, but it at least
got the job done because they were
then able to track everything.
So in this program, notice that
I have my route for my form.
And I have this register route
but a few new lines of code.
And you would only know how to do
this by reading the documentation.
But in this case here, notice what
I'm doing in my register route.
I'm first getting the user's name and
their email this time and their dorm.
Then I'm error checking.
If they didn't give me a name,
or their email, or the dorm,
render failure.html to
apprise them as much.
Then go ahead and do
these lines of code.
And this is more of a mouthful,
and you would only, again,
know this from the documentation.
But it turns out if you
read the documentation
for this SMTP lib or library, you can
use lines of code like this as follows.
You can tell the library what
server to use for sending email.
And it turns out if you
read Gmail's documentation,
you can use smtp.gmail.com to
automatically send e-mails not using
the web UI, but using code.

Arabic: 
ومعرفة مَن قام بالتسجيل.
وهو ليس سهل الاستخدام 
بشكل كبير، ولكن على الأقل
يُنهي المهمة ليكون
قادرًا بعد ذلك على تتبع كل شيء.
إذن في هذا البرنامج، لاحظوا أن
لديّ طريق للشكل الخاص بي.
ولديّ طريق التسجيل هذا
ولكن بضعة سطور جديدة من التعليمة البرمجية.
وستعرفون فقط كيفية القيام بذلك
من خلال قراءة الوثائق.
ولكن في هذه الحالة هنا، لاحظوا ما
أفعله في طريق التسجيل لديّ.
سأحصل أولاً على اسم المستخدم 
وبريده الإلكتروني هذه المرة وسكنه.
ثم أقوم بالتحقّق من الخطأ.
إذا لم يعطيني اسمًا
أو بريدًا إلكترونيًا أو سكنًا،
سأقوم بتقديم failure.html
لإطلاعه على هذا القدر.
ثم أمضي قدمًا وأكتب هذه
السطور من التعليمة البرمجية.
وهذا صعب للغاية،
وستقومون فقط، مجددًا،
بمعرفة هذا من الوثائق.
ولكن يتضح أنه إذا
قرأتم الوثائق
الخاصة بمكتبة أو SMTP lib، يمكنكم
استخدام سطور التعليمة البرمجية كهذه على النحو التالي.
يمكنكم إخبار المكتبة عن الخادم
المراد استخدامه لإرسال رسالة بريد إلكتروني.
ويتضح أنه إذا قرأتم
وثائق Gmail،
فيمكنكم استخدام smtp.gmail.com لإرسال
رسائل بريد إلكتروني تلقائيًا ليس باستخدام
واجهة مستخدم الويب، ولكن باستخدام التعليمة البرمجية.

Arabic: 
587 هو منفذ TCP الذي يستخدمونه.
إذن ليس 80، ليس 443،
إنه 587 حسب التقليد.
Starttls، إذا قرأتم الوثائق،
تقول شغِّل التشفير.
لذا يتم تشفير رسالة البريد الإلكتروني
بينك وبين Gmail.
ثم امضي قدمًا وقم بتسجيل الدخول
باستخدام اسم مستخدم وكلمة مرور.
لقد قمتُ بإنشاء حساب مسبقًا
يُسمى harvard@cs50.net، وكلمة المرور
الخاصة بي في بيئة IDE.
لقد قمتُ بتخزينه في مكان آخر
بحيث لا يكون مرئيًا على الشاشة،
وإلا يمكن أن يرسل الأشخاص
رسائل بريد إلكتروني باسم جون.
ثم أمضي قدمًا وأطلب حرفيًا
دالة تُسمى إرسال بريد.
وإذا قرأتم الوثائق،
فستأخذ
هذه كوسيطة شخص تريد
إرسال رسالة بريد إلكتروني إليه،
ومحتويات رسالة البريد الإلكتروني
التي تريد إرسالها،
والرسالة التي
تريد إرسالها بالفعل هنا.
أو بالأحرى، هذا العنوان
من المُرسِل، والعنوان من المُستلِم،
والرسالة الفعلية
التي تريد إرسالها.
بعد ذلك، يجب أن تمضوا قدمًا
وتقدموا قالب ولنفترض أنه success.
يمكنني إضافة تحقق آخر
من الخطأ، على سبيل المثال من المحتمل أنه يجب
أن أتحقّق مما إذا كان هنا أي
شيء خاطئ، ولكنني أبقي الأمر بسيطًا.
لكن هذه السطور الجديدة التي يتم
تظليلها ترسل رسالة بريد إلكتروني بالفعل.
إذن دعونا نجرب هذا.

English: 
587 is the TCP port that they use.
So it's not 80, it's not
443, it's 587 by convention.
Starttls, if you read the
documentation, says turn on encryption.
So the email is encrypted
between you and Gmail.
Then go ahead and log in with a
certain username and password.
I created an account in advance called
jharvard@cs50.net, and my password
is in my IDE's environment.
I stored it elsewhere so that
it's not visible on screen,
otherwise people could
send emails as John.
Then I go ahead and call literally
a function called send mail.
And if you read the
documentation, this one
takes as argument who you
want to send email to,
the contents of the email
that you want to send,
and the message that you
actually want to send here.
Or rather, this is the from
address, the to address,
and the actual message
that you want to send.
After that, you just go ahead and
render template and assume success.
I could add more error
checking, like I should probably
check if anything went wrong
here, but I'm keeping it simple.
But these new lines that are
highlighted actually send an email.
So let's try this.

Arabic: 
دعوني أنتقل إلى froshims2 ودعوني
أمضي قدمًا وأقوم بتشغيل Flask.
دعوني أمضي قدمًا وأفتح
هذه الصفحة هنا، خط مائل.
ولاحظ أن لدي بالفعل
حقل ثاني للنص الآن.
إذن هذا سيكون ديفيد،
وهذا سيكون--
دعونا نرى، ماذا عن المضي قدمًا،
والتسجيل ليس نفسي،
لأنه ليس حساب بريدي الإلكتروني،
ولكن جون هارفارد الذي نزعم أن
بريده الإلكتروني هو cs50.net، jharvard هنا.
ويعيش في لنقل، ويلد.
دعونا نمضي قدمًا وننقر فوق تسجيل.
حسنًا، إن الأمر يستغرق وقتًا
أطول قليلاً هذه المرة،
ولكنه يقوم بعمل إضافي
لإرسال رسالة بريد إلكتروني.
والآن دعونا ننتقل إلى
gmail.com، ونفتح هذا.
أوه.
في بريدي الوارد، أنت مُسجل.
إذا قمتُ بفتح ذلك،
لاحظوا أن jharvard@cs50.net
أرسل إلي رسالة بريد إلكتروني عن طريق بذور BC،
على الأقل أحتفظ بجزء من المعلومات
الخاصة.
ويقول فقط في بنية
الرسالة إذا قمتُ بتحريك المؤشر،
أنت مُسجل.
لذا لقد عدتُ
إلى عام 1997 بشكل أكبر، لكنني
أدرجتُ اسم المستخدم، وعنوان
بريده الإلكتروني، وسكنه،

English: 
Let me go into froshims2 and let
me go ahead and do Flask run.
Let me go ahead and open
up the page here, slash.
And notice I do, indeed, have
a second field for text now.
So this will be David,
and this will be--
let's see, how about let's go
ahead and just register not myself,
since it's not my email account,
but John Harvard who we claim's
email is cs50.net, jharvard thereat.
And he lives in say, Weld.
Let's go ahead and click Register.
All right, it's taking a
little longer this time,
but it was doing a little
more work sending an email.
So now let's try to go to
gmail.com, open this up.
Ooh.
In my inbox, you are registered.
If I open this up,
notice jharvard@cs50.net
has sent me an email by a BC seed,
at least keep part of the information
private.
And it just says in the body of
the message if I move the cursor,
you are registered.
So I did a little more
back in 1997, but I
included like the user's name, and
their email address, and their dorm,

Arabic: 
وربما رقم هاتفه أو أي شيء،
والرياضة التي يهتم بها.
لكن الفكرة هي ذلك بالضبط.
يمكنكم إرسال أي معلومات تريدونها
فقط باستخدام التعليمة البرمجية الآن.
لا يمكنكم القيام بذلك باستخدام
HTML أو CSS فقط.
أي أسئلة، بعد ذلك، حول هذا؟
أجل؟
الجمهور: في الأسبوع الماضي عندما كتبنا
التعليمة البرمجية في Python، كان يجب أن نقول
على سبيل المثال إذا كان الاسم يساوي الدالة
التي نرغب في تنفيذها.
كيف لا نفعل ذلك في هذا؟
ديفيد مالان: كان ذلك كله في JavaScript.
لذا يشير هذا إلى إذا كان الاسم
يساوي، ومن ثم قمتُ بتعيينه إلى دالة،
أنا أعتقد أنك تشير إلى أمثلة
JavaScript لدينا، أليس كذلك؟
حسنًا.
لذا سنرجع إلى ذلك
بعد قليل
حيث نعيد تقديم بعض الأمور
من JavaScript،
وهي تعطينا بالفعل بعض
الدالات الأخرى التي تذكرنا
بتلك الأمثلة.
أي أسئلة أخرى؟
الجمهور: ما هو عنوان البريد الإلكتروني الذي
أرسلتُ منه هذا البريد الإكتروني،
ولا تحتاج إلى إدخال
كلمة مرور للتأكد من
عدم إرسال أي شخص فقط رسالة بريد إلكتروني بشكل عشوائي؟
ديفيد مالان: نعم، إنه
سؤال جيد حقًا.
لذلك عبر أي عنوان بريد إلكتروني
قمتُ بإرسال ذلك، ولمَن أرسلتُ ذلك؟

English: 
and maybe their phone number or whatnot,
and the sports they were interested in.
But the idea is exactly that.
You can send any information
you want just by now using code.
You could not do that with
HTML or with CSS alone.
Any questions, then, on this?
Yeah?
AUDIENCE: Last week when we wrote
code in Python we had to like
say if name equals the
function to like execute that.
How come in this we're not doing that?
DAVID MALAN: That was all in JavaScript.
So that allusion to if name equals,
and then you assign it to a function,
I think you're referring to
our JavaScript examples, no?
OK.
So we'll actually come back
to that in a little bit
where we reintroduce
a bit of JavaScript,
which actually gives us some
more functionality reminiscent
of those examples.
Other question?
AUDIENCE: What email address
did you send that email from,
and don't you need to enter
like a password to make sure
that no one just randomly sends email?
DAVID MALAN: Yeah, it's
a really good question.
So via what email address did I
send that, and to whom was it sent?

Arabic: 
مجددًا، هذا هو العنوان
من المُرسِل، وهذا هو العنوان من المُستلِم،
وهذه هي الرسالة الآن.
ولأنه ليس لدي حساب بريد إلكتروني
واحد فقط، فقد أرسل جون بنفسه
رسالة بريد إلكتروني في هذه الحالة.
من الناحية النظرية إذا كنتُ أقوم بتشغيل
برنامج رياضة داخلية للطلاب الجدد،
يمكنني محاولة القيام بذلك
وتغيير هذا من العنوان لنفسي.
يتمثل المغزى في أن Gmail لديه
بالفعل حماية في مكانه بحيث إذا قمتم
بتسجيل الدخول كـ jharvard
باستخدام كلمة مروره، ثم
البريد الإلكتروني، بغض النظر
عما تحدده كعنوان من المُرسِل،
سيتم تجاوزه بالفعل
ليكون من جون هارفرد.
ومع ذلك، يشير هذا إلى
احتمال عدم أمان البريد الإلكتروني.
إذا كنتَ لا تستخدم Gmail
ولكنك تستخدم خدمة من جهة خارجية
ليست صارمة للغاية
للتحقق من الخطأ،
من السهل بشكل لا يصدق تزييف
رسائل البريد الإلكتروني من شخص إلى آخر.
أعني، البحث في مجلد
الرسائل غير المرغوب فيها في بعض الأحيان.
معظم هؤلاء الأشخاص الذين يرسلون
إليك تلك الرسائل غير موجودين.
على سبيل المثال، عناوين البريد الإلكتروني
و/أو الأسماء وهمية.
ومع ذلك، قد يبدو أنها في
الواقع من أحد أقاربك، أو أحد أفراد العائلة،
أو صديق، على الرغم من أن هؤلاء
الأشخاص لم يرسلوا رسائل بريد إلكتروني.
وهذا لأن بعض مرسلي الرسائل
غير المرغوب فيها قد كتبوا تعليمة برمجية
على سبيل المثال هذه في
Python أو في أي لغة أخرى،

English: 
So again, this is the from
address, this is the to address,
and this is now the message.
And just because I only have one email
account open, I had John send himself
an email in this case.
Theoretically if I were running the
freshmen intramural sports program,
I could try to do this and change
this from address to be myself.
The catch is that Gmail actually has
protections in place so that if you've
logged in as jharvard
with his password, then
the email, no matter what you
specify as the from address,
is actually going to be overridden
to be from John Harvard.
However, this does speak to the
potential insecurity of email.
If you don't use Gmail
but you use a third party
service that is not so rigorous
with its error checking,
it is incredibly easy to fake
emails from one person to another.
I mean, look through your
spam folder sometime.
Most of those people who send
you those spams don't exist.
Like, the email addresses
and/or the names are fake.
And yet they might appear to actually
be from a sibling of yours, a family
member, or a friend, even though
those humans did not send e-mails.
And that's because some
spammer has written code
like this in Python or
some other language,

Arabic: 
لكنه يتجاوز هذه الحقول،
ولكنه استخدم خادمًا ليس Gmail
لا يفرض هذه السياسات.
أي أسئلة أخرى؟
حقيقة ممتعة، أيضًا في عام 1995،
تعلمتُ كيفية الإرسال--
أو كيفية تغيير العنوان من المُرسِل
في البريد الإلكتروني.
ويتضح في هارفارد أنه يوجد
كيان يُسمى لوحة الإعلانات
وهو لا يرغب في القيام بذلك.
لذا لا تفعل ذلك.
في بعض الأحيان، توجد دفاعات بشرية
لهذا الغرض، وليست مجرد تقنية.
لحسن الحظ، صديقي الذي زورت
رسالة بريد إلكتروني منه لا يقوم--
لقد نجح الأمر، حسنًا.
حسنًا.
لديكم الآن قوة كبيرة،
لا تستخدموها من أجل الشر.
حسناً، دعونا نمضي قدمًا
ونقوم بمثال آخر، لكن هذا يأخذ
خطوة أخرى، مضيفًا، في
النهاية، بعض المعلومات الثابتة.
دعونا نمضي قدمًا في
froshims3 الآن ونفتح application.py.
لذا تذكرون أنه يمكننا استخدام ملفات
CSV-- ملفات قيم مفصولة بفاصلة--
لإنشاء وهم
جداول البيانات،
ولكننا الآن
سنقوم بإنشائها بأنفسنا.

English: 
but has overridden these fields,
but used a server that's not Gmail
that doesn't enforce these policies.
Other questions?
Fun fact, also in 1995,
I learned how to send--
or how to change the
from address on an email.
And turns out at Harvard there's
this entity called the ad
board who doesn't like doing this.
So don't do that.
Sometimes there's human defenses in
place for this, not just technological.
Thankfully, my friend whom I
faked an email from did not--
it worked out OK.
All right.
You have now great power,
don't use it for evil.
All right, so let's go ahead now and
do another example, but that takes this
a further step, adding, finally
some persistence of information.
Let's go ahead into froshims3
now and open up application.py.
So recall that we can use CSV
files-- comma separated value files--
to create the illusion
of like spreadsheets,
but now we're actually going
to create them ourselves.

Arabic: 
التعليمة البرمجية لهذا
متضمنة بشكل كبير قليلاً،
والشيء الوحيد الذي قمتُ
بتغييره الآن هو حقًا طريقة التسجيل.
لذا في الإصدار الأول من هذه التعليمة البرمجية،
قمتُ بحفظه في قائمة شاملة في الذاكرة فقط.
لم يكن ذلك جيدًا لأنه
يتم التخلص منه بسهولة.
الإصدار الثاني من هذا
أرسلنا للتو رسالة بريد إلكتروني
إلى المراقب الذي يشغّل البرنامج.
كان هذا أفضل قليلاً، لأنه على
الأقل يمكنه حفظ البريد الإلكتروني بعد ذلك.
الإصدار الثالث، سنستخدم قاعدة
بيانات خفيفة الوزن جدًا تُسمى
ملف CSV الذي يحفظه على محرك
الأقراص الصلب الخاص بي بشكل دائم.
لذا حتى عندما يتوقف الخادم،
تظل البيانات موجودة.
إذن في Python، كيف يعمل هذا؟
حسنًا، لاحظوا أنني قمتُ بتحسين طريق التسجيل
الخاص بي في هذه المرة على النحو التالي.
إذا لم يعطيني المستخدم
اسمه أو سكنه،
بعد ذلك سأمضي قدمًا وأقدم failure.
هذا إلى حد كبير نفس
المنطق كما كان من قبل،
لكنني لم أحمّل نفسي عناء
إعلان المتغيرات هذه المرة،
فقط لقد طلبتُ الدالات مباشرة.
ها هو سطر جديد من التعليمة البرمجية
قد يذكرنا ببعض تعليمة الإدخال/الإخراج البرمجية
للملف السابق.
في السطر 16 هنا، أنا أخبر Python أن تمضي
قدمًا وتفتح ملف يُسمى
record.csv علامة اقتباس وعلامة إنهاء الاقتباس a.
لذا رأينا R، لقد رأينا
W للقراءة والكتابة.
أي شخص يتذكر ما هو a، أو لا؟

English: 
The code for this is a
little more involved,
and the only thing I've changed
now really is the register method.
So in version one of this code, I saved
it in a global list just in memory.
That was not good because it
gets thrown away too easily.
Version two of this
we just sent an email
to the proctor who runs the program.
That was a little better, because at
least they can then save the email.
Version three, we're going to use
a very lightweight database called
the CSV file that saves it
to my hard drive permanently.
So even when the server stops,
the data is still there.
So in Python, how does this work?
Well, notice that I've improved my
register route this time as follows.
If the user did not give
me their name or dorm,
then I go ahead and render a failure.
That's pretty much the
same logic as before,
but I didn't bother declaring
the variables this time,
I just called the functions directly.
Here's a new line of code that might be
reminiscent of some of your past file
I/O code.
In line 16 here, I'm telling Python
to go ahead and open a file called
registered.csv quote-unquote a.
So we've seen R, we've
seen W for read and write.
Anyone recall what a is, or no?

Arabic: 
الجمهور: Append.
ديفيد مالان: يصادف أن هذا يعني
إلحاق، مما يعني فقط إضافة
صف إلى الملف، وهو أمر رائع.
لأنه إذا كان هناك طلاب مُسجَلون
بالفعل، عندما يتم تسجيل طالب واحد جديد،
فإننا نريد فقط إلحاق
الجزء السفلي من الملف.
يتم دعم علامة اقتباس وعلامة إنهاء الاقتباس a
بواسطة Python باستخدام هذه الدالة المفتوحة.
هذا يعطيني مرجعًا أو
ما يشبه مؤشر إلى ملف،
حتى على الرغم من أن
Python ليس لديها مؤشرات.
ثم هذه هي الميزة الجديدة.
وهنا أيضًا، لا يمكنك معرفة ذلك
فقط إلا من خلال رؤية مثال
أو عبر قراءة الوثائق.
يمكنكم استخدام مكتبة CSV، التي
سنراها كمستوردة أعلاه.
ويمكنكم أن تطلبوا كاتبًا،
تعليمة برمجية تقوم بالكتابة-- إنها،
تقوم بإنشاء--
ملفات CSV.
وتحديدًا، تريدون
الكتابة في هذا الملف.
تأتي تلك المكتبة-- مكتبة
CSV-- مع دالة
تُسمى كتابة صف، وهي
تقوم بما تقوله.
إذا قمتم بتمريره في قائمة
من الحقول مفصولة بفاصلة
والتي تريدونها لتمثيل
العمود الأول، والثاني،
والثالث لديكم،
فإنها ستعالج الكتابة من أجلكم
لذا لن تضطروا إلى الدخول
في تعقيدات ملف الإدخال/الإخراج
كما فعلتم في العديد من مجموعات المشاكل السابقة.
لاحظوا الدقة.
تحتاجون إلى الحصول على
الزوج الثاني من الأقواس،

English: 
AUDIENCE: Append.
DAVID MALAN: It happens to
mean append, which means just
add a row to the file, which is nice.
Because if there's already students
registered, when a new one registers
we just want to append to
the bottom of the file.
Quote-unquote a is supported by
Python with this open function.
That gives me back a reference
or like a pointer to file,
even though Python
does not have pointers.
Then this is the new feature.
And here, too, you'd only know
this from having seen an example
or you reading the documentation.
You can use the CSV library, which
we'll see as imported up above.
And you can ask for a writer, a piece
of code that writes out-- that is,
creates--
CSV files.
And specifically, you want
to write to this file.
That library-- the CSV
library-- comes with a function
called write row, which
does what it says.
If you pass it in a comma
separated list of fields
that you want to represent your
first column, your second column,
and your third column, it will
handle the writing for you
so you don't have to get
into the weeds of file I/O
like you did several problem sets ago.
Notice the subtlety.
You do need to have these
second pair of parentheses,

English: 
because technically what
you're giving it is a tuple.
We talked very briefly
about that last week,
which is just like an x comma y
pair, or latitude comma longitude.
Same idea here.
First column, second column, and
so forth is a so-called tuple.
Then I close the file,
then I render the template.
So what does this actually do for me?
Well, let me go into my
folder froshims3 here.
And notice register.csv
at the moment is empty.
This is a CSV file.
Nothing's going on inside of that.
There's no one registered yet.
But let me go ahead, then, and
go into froshims3, run Flask run.
Let me go ahead and load this up.
And you'll see the same kind
of form, but also a new link.
Notice that no one's registered
yet if I click on that link.
But if I go into here and register
David from Matthews and click Register,
now it claims I am registered really.
Let me click this link and notice
that it's very small on the screen,
but slash registered is
where this is going to lead
me, which is just where I was before.
You see that now David
from Matthews registered.

Arabic: 
لأن من الناحية الفنية ما
تعطونه هو صف.
تحدثنا بشكل موجز للغاية
عن ذلك في الأسبوع الماضي،
وهو ما يشبه تمامًا زوج من x فاصلة
y، أو خط الطول فاصلة خط العرض.
الفكرة نفسها هنا.
العمود الأول، والعمود الثاني،
وهكذا هو ما يُسمى صف.
ثم أُغلق الملف،
وبعد ذلك أُقدم القالب.
إذن ما الذي يفعله هذا في الواقع من أجلي؟
حسنًا، دعوني أنتقل إلى
المجلد froshims3 هنا.
ولاحظوا أن register.csv
في هذه اللحظة يُعد فارغًا.
هذا هو ملف CSV.
لا يحدث شيء داخل ذلك.
لا يوجد أحد مُسجَّل بعد.
ولكن دعوني أمضي قدمًا، ثم،
أنتقل إلى froshims3، وأُشغل Flask.
دعوني أمضي قدمًا وأقوم بتحميل هذا.
وسترون الشكل نفسه 
إلى حد ما، ولكن أيضًا رابطًا جديدًا.
لاحظوا أنه لا يوجد أي شخص مُسجَّل
حتى الآن إذا قمتُ بالنقر فوق هذا الرابط.
ولكن إذا انتقلتُ هنا وسجلتُ
ديفيد من ماثيوز ونقرتُ فوق تسجيل،
الآن يزعم أنني مُسجَّل بالفعل.
دعوني أضغط على هذا الرابط ولاحظوا
أنه صغير جدًا على الشاشة،
لكن خط مائل مُسجَّل هو
حيث سيقودني هذا،
وهو حيث كنتُ من قبل.
ترون ذلك الآن ديفيد
من ماثيوز مُسجَّل.

Arabic: 
دعوني أعود إلى الشكل نفسه.
دعونا نُسجل، مثلاً،
براين من بيني بايكر.
أنقر فوق تسجيل.
من الواضح أنه أيضًا مُسجَّل.
دعونا ننقر فوق هذا الرابط.
براين من بيني بايكر.
حسنًا، إذن إلى أين تنتقل هذه البيانات؟
دعوني أعود إلى IDE،
أغلق ملف CSV المُسجَّل الخاص بي،
لأنه على الأرجح
تغيّر وأقوم بفتحه.
وها هو ذا، في الواقع، إنه
يطلب مني بإعادة تحميله.
ها هو الملف.
ولاحظوا ديفيد فاصلة ماثيوز، وبراين
فاصلة بيني بايكر، تمت ترجمة جميع تلك الصفوف
من أجلي.
إذن الآن لديّ قاعدة بيانات بالفعل.
وعلى الرغم من أنها قاعدة بيانات بسيطة
إلى حد ما، أتعرفون ما الذي يمكنني القيام به؟
دعوني أمضي قدمًا وأنقر بزر الماوس الأيمن
أو زر التحكم فوق IDE،
وأقوم بتحميلها في مجلد التنزيلات.
ومن ثم إذا قمتُ بالفعل
بفتح هذا الشيء، إذا كان
لديّ Excel مُثبّت
أو Apple Numbers، وهذه
هي المرة الأولى التي أستخدمه فيها على الإطلاق،
دعوني أمضي قدمًا وأفتح ذلك الملف.
فتح register.csv.
وها هو ذا، ها هو الآن ملف.
ويقوم Numbers بتنسيقه
بطريقة غريبة إلى حد ما،
لكنه يعرض الصفوف والأعمدة.
مَن منكم على دراية أكبر
باستخدام Excel يمكننا القيام بذلك، أيضًا.

English: 
Let me go back to the form itself.
Let's register, say,
Brian from Pennypacker.
Click Register.
He, too, is apparently registered.
Let's click that link.
Brian from Pennypacker.
All right, so where is this data going?
Let me go back to the IDE,
close my registered CSV file,
because it's probably
changed and open it up.
And voila, indeed, it's
prompting me to reload it.
There is the file.
And notice David comma Matthews, Brian
comma Pennypacker, all of those rows
were written out for me.
So now I actually have a database.
And even though it's kind of a simple
database, you know what I can do?
Let me go ahead and right click
or control click on it in the IDE,
download it into my Downloads folder.
And then if I actually
open this thing, if I
have Excel installed
or Apple Numbers, which
is the first time I've ever used it,
let me go ahead and open that file.
Opening register.csv.
And voila, here now is a file.
And Numbers is formatting
it in kind of a funky way,
but it is showing rows and columns.
Those of you who are more familiar
with Excel we can do that, too.

Arabic: 
دعوني أنتقل إلى الأسفل هنا.
دعوني أنتقل إلى مجلد التنزيلات.
سأنقر بزر التحكم أو بزر الماوس الأيمن هنا،
وهذه المرة أفتحه باستخدام Microsoft Excel.
وإذا رأيتم Excel مسبقًا،
سنرى على الأرجح واجهة مستخدم مُتشابهة جدًا.
لأنه في أي وقت Excel أو Numbers--
حسنًا، هذه هي المرة الأولى التي أستخدم فيها Excel.
إذن سيفتح ذلك، أيضًا،
بعض الصفوف والأعمدة، كذلك.
إذن ملفات CSV هي مجرد
جداول بيانات خفيفة جدًا.
ولكن الشيء الرائع بشأنها هو أنه
يمكنكم إنشاؤها بسهولة.
فقط يجب أن تضعوا الفواصل هناك.
الآن، كملاحظة جانبية، هل يمكنكم
استنباط مدخل مستخدم
الذي يمكنه على الأرجح تقسيم ملف CSV؟
ما الذي يمكن أن يكتبه شخص يمكنه
على الأرجح تقسيم ملفات CSV الخاصة بكم؟
فاصلة، أليس كذلك؟
إذا كان الأمر هكذا ديفيد مايلاند فاصلة
طالب في السنة الثالثة الجامعية، أو شيء من هذا القبيل.
أو أي شيء باستخدام علامات ترقيم غريبة.
هذا هو سبب استخدامكم المكتبات.
مكتبة CSV تلك في
هذه التعليمة البرمجية، التي
نقوم باستيرادها في الجزء العلوي من
الإصدار 3 هذا من التعليمة البرمجية،
الذي يعالج في الواقع
كل ذلك التعقيد من أجلنا.
عندما تُصادف المكتبة ديفيد
مايلاند فاصلة طالب في السنة الثالثة الجامعية إذا كان ذلك

English: 
Let me go down here.
Let me go into my Downloads folder.
Control click or right click here, and
this time open it with Microsoft Excel.
And if you've seen Excel before,
we'll probably see a very similar UI.
Because anytime Excel or Numbers--
OK, first time I've used Excel.
So that, too, will open up
some rows and columns, as well.
So CSV files are just very
lightweight spreadsheets.
But what's cool about them is that
you can create them so easily.
You just have to put commas in there.
Now, as an aside, can you
contrive a user's input
that could potentially break a CSV file?
What could a human type in that could
potentially break your own CSV files?
A comma, right?
If it's like David Mayland comma
junior, or something like that.
Or anything with weird punctuation.
This is why you use libraries.
That CSV library in
this code, which we're
importing at the very top of
this version 3 of the code,
is actually handling all
of that complexity for us.
When the library encounters David
Mayland comma junior if that's

English: 
the user's input, it
will then additionally
put quotes around my whole
name, thereby making sure
that my comma is inside
quotes and not, therefore,
confused with the special comma that
demarcates the start of other columns.
So again, that's why you
don't reinvent the wheel,
because corner cases like that arise.
Well, what about slash registered,
which is this list that's
generating an unordered list?
Let's see how that works.
If I scroll down to this
code, notice that it's not
just a simple matter of
grabbing a global variable,
because there is no
global variable anymore.
Now I have to read it
from that CSV file.
So here's three new lines of
code that work as follows.
I'm going to go ahead and open this
file, register.csv, in Read mode
this time, not append.
I'm going to go ahead now and say
hey Python, use the CSV reader--
which is the opposite of writer--
on that file.
And then, hey Python, go ahead and
turn that whole reader into a list.
So you'd only know this from
reading the documentation.
It turns out this is the recommendation.
If you want to take a reader and
just read the whole thing into memory

Arabic: 
هو مدخل المستخدم، ستقوم
بالإضافة إلى ذلك
بوضع علامات اقتباس حول
اسمي بأكمله، وبالتالي تتأكد
أن الفاصلة داخل
علامات الاقتباس، وبالتالي، لن يختلط عليها الأمر
مع الفاصلة الخاصة التي تُحدد
بداية الأعمدة الأخرى.
إذن مجددًا، لهذا السبب
لا تعيدون اختراع العجلة،
بسبب ظهور الحالات الحرجة مثل تلك.
حسنًا، ماذا عن خط مائل مُسجل،
وهو هذه القائمة التي
تقوم بإنشاء قائمة غير مرتبة؟
دعونا نرى كيف يعمل ذلك.
إذا قمتُ بالتمرير إلى هذه
التعليمة البرمجية، لاحظوا أنها ليست
مسألة بسيطة لسحب
متغير شامل فقط،
لأنه لا يوجد
متغير شامل بعد الآن.
الآن يجب أن أقرأه
من ملف CSV ذلك.
إذن ها هي ثلاثة سطور جديدة من
التعليمة البرمجية التي تعمل على النحو التالي.
سأمضي قدمًا وأفتح هذا
الملف، register.csv، في وضع القراءة
هذه المرة، وليس في وضع إلحاق.
سأمضي قدمًا وأقول
مرحبًا Python، استخدم قارئ CSV--
وهو مقابل الكاتب--
على هذا الملف.
ثم، مرحبًا Python، امضي قدمًا
وقم بتحويل ذلك القارئ بأكمله إلى قائمة.
إذن ستعرفون هذا فقط من
قراءة الوثائق.
يتضح أن هذا هو ما أوصي به.
إذا أردتم أخذ قارئ
وقراءة هذا الشيء بأكمله في الذاكرة فقط

Arabic: 
مرة واحدة وتحويله إلى قائمة 
Python، تقومون فقط بتمريره
إلى دالة القائمة هذه.
هذا يعطيني قائمة سأقوم
باستدعاء students،
وبعد ذلك يمكنني القيام
بالتعليمة البرمجية نفسها كما فعلتُ من قبل.
ولتدبر الأمر جيدًا، ربما يجب
أن أقوم بما
فعلته آخر مرة، وهو file.close
لإغلاق الملف، أيضًا، فقط
للتأكد من إغلاقه في المرة
التالية التي يتم فتحه فيها.
ولكن يمكنني بالفعل تبسيط هذا،
وسترون المزيد من هذه الأمثلة
عبر الإنترنت.
إن عدم القيام بذلك في الواقع
أمر تقليدي أكثر في Python،
ولكن بدلاً من ذلك، قوموا بتغيير
تعليمتكم البرمجية على النحو التالي.
حتى لا تتحملون عناء إغلاقه بشكل صريح،
بدلاً من استخدام كلمة رئيسية تُسمى with
بدلاً من ذلك، ضَعوا اسم المتغير مرة أخرى هناك
ثم ضَعوا مسافة بادئة لكل شيء أدناه.
لا يهم أي منهما تقوم به
بالنسبة إلى أهدافنا.
الأول كان صحيحًا.
والثاني صحيح.
هذا هو أمر تقليدي أكثر،
فقط إذا كان ذلك لأنه يعالج إغلاق
الملف من أجلك.
لذا إذا رأيتم هذا عبر الإنترنت،
فهذا كل ما يحدث هناك.
ولكن الأمر يشبه في C القيام بكتابة fopen وfclose،
أو في هذه الحالة يكون الفتح والإغلاق
كما كان لدي منذ لحظة.
أية أسئلة أخرى؟
الجمهور: كيف تعالج
التكرارات؟
ديفيد مالان: كيف
سأقوم بالتكرار؟

English: 
at once and convert it to a Python
list, you literally just pass it
to this list function.
That gives me a list I'm
going to call students,
and then I can do my
same code as before.
For good measure, I
should probably do what
I did last time, which is file.close
to close the file, as well, just
to make sure it's closed
the next time it's opened.
But I can actually simplify this,
and you'll see more of these examples
online.
It's actually more conventional
in Python not to do this,
but instead to change
your code as follows.
To not bother closing it explicitly,
to instead use a keyword called with
to instead put the variable name back
there and indent everything underneath.
Doesn't matter for our
purposes which one you do.
The first one was correct.
The second one is correct.
This is just more conventional,
if only because it handles
the closing of the file for you.
So if you see this online, that's
all that's happening there.
But it's just like in C doing fopen and
fclose, or in this case open and close
like I had a moment ago.
Any questions, then?
AUDIENCE: How would
you handle duplicates?
DAVID MALAN: How would I duplicates?

Arabic: 
سؤال جيد.
إذن لم أعالج التكرارات هنا
على الإطلاق، وديفيد من ماثيوز
يمكن أن يتم تسجيله مرارًا وتكرارًا.
ولكن ما الذي يمكنني فعله بشكل منطقي؟
حسنًا، من المحتمل أنه ينتمي
هنا في طريق التسجيل الخاص بي.
من المحتمل أنني أريد أن أتحقّق من
الخطأ بشكل أكبر من هذين السطرين فقط.
لأنه على الأرجح ما أريد
القيام به لمعرفة ما إذا كان ديفيد من ماثيوز
مُسجل بالفعل هو
فتح ملف CSV،
قم بتكرار سطوره للبحث عن
ديفيد وماثيوز على السطر نفسه
ومن ثم أعرض failure
للمستخدم إذا حاول أو حاولت
التسجيل للمرة الثانية.
لم أجعل الأمر سهلاً باستخدام
هذه التعليمة البرمجية، وبصراحة
سيكون ذلك أسهل بكثير
في الأسبوع القادم باستخدام SQL.
SQL، هذه اللغة الأخرى
لقواعد البيانات، ستجعل
الأمر سهلاً للبحث عن البيانات
التي تم حفظها بالفعل.
لا تجعل ملفات CSV هذا أمرًا سهلاً.
هذا قابل للتنفيذ، لكن يجب أن
تكتبوا المزيد من سطور التعليمة البرمجية.
إذن المزيد حول ذلك قريبًا.
أي أسئلة أخرى؟
حسنًا، دعونا ننتقل
إلى مثال واحد أخير،

English: 
good question.
So haven't handled duplicates here
at all, and David from Matthews
could register again and again.
But logically what might I do?
Well, it probably belongs
here in my register route.
I probably want to do more error
checking than just these two lines.
Because what I probably want to
do to see if David from Matthews
is already registered
is open the CSV file,
iterate over its lines looking for
David and for Matthews on the same line
and then show a failure to
the user if he or she is
trying to register for a second time.
I've not made it easy with
this code, and frankly that's
going to be so much
easier next week with SQL.
SQL, this other language
for databases, will
make it easy to search data
that has already been saved.
CSV files do not make this easy.
It's doable, but you have
to write more lines of code.
So more on that to come.
Other questions?
All right, so let's skip
ahead to one final example,

Arabic: 
froshim6، حيث سنقوم بشيء
أكبر قليلاً من أجلنا هنا.
لذا إذا انتقلتُ إلى
froshim6، لاحظوا أنه إذا
قمتُ بتشغيل Flask، والعودة إلى موقع الويب
هنا، وإعادة تحميل الشاشة،
ومضيتُ قدمًا وأعطيتكم اسمي، لكن
لا، لا أريد أن أعطيكم سكني،
لدينا هذه الميزة.
إنها قبيحة مجددًا، ولكن أين 
رأينا هذا النوع من الدالة
عندما لا يتعاون المستخدم؟
أو كيف قمتُ بتنفيذ هذا، على ما يبدو؟
الجمهور: JavaScript؟
ديفيد مالان: نعم، JavaScript.
إذن يتضح أنه باستخدام Python،
يمكنكم بالتأكيد
التحقّق من صلاحية مدخل المستخدم على
الخادم فقط من خلال التحقّق مما يوجد
في request.args أو request.form 
ومن ثم تصيحون وفقًا لنجاح
المستخدم أو فشله.
ولكن يمكنكم أيضًا استخدام JavaScript-- 
وبصراحة، لقد فعلنا هذا منذ أسبوعين،
لذا يبدو أننا فقط نقوم بحل
المشاكل نفسها مرة أخرى.
إذن كيف تفكرون في هذا؟
هل يجب أن أتحقق من اسم المستخدم
وسكنه في JavaScript؟
هل يجب أن أتحقق من 
اسم المستخدم وسكنه على الخادم؟
أعني، الرسائل مختلطة الآن.

English: 
froshim6, which we'll do something
a little more for us here.
So if I go ahead into
froshim6, notice that if I
do Flask run, and go back to the
website here, and reload the screen,
and I go ahead and give you my name, but
no, I'm not going to give you my dorm,
we have this feature.
It's ugly again, but where did
we see this kind of functionality
when the user does not cooperate?
Or how did I implement this, apparently?
AUDIENCE: JavaScript?
DAVID MALAN: Yeah, JavaScript.
So it turns out that with
Python, you can obviously
validate the user's input on the
server by just checking what's
in request.args or request.form and
then yell at the user success or failure
accordingly.
But you can also use JavaScript-- and
honestly, we did this two weeks ago,
so we just seem to be solving
the same problems again.
So how do you think about this?
Should I be checking for the
user's name and dorm in JavaScript?
Should I be checking for the
user's name and dorm on the server?
I mean, mixed messages now.

Arabic: 
الجمهور: أيًّا كان الأسرع.
ديفيد مالان: أيًّا كان الأسرع.
هذا مُعطى جيد جدًا
للاستخدام، الأسرع.
ويمكننا أن نجعله أجمل
عن طريق استخدام Bootstrap أو مكتبة ما
لتعطيكم مربع ملون، أو
نص خطأ باللون الأحمر أو شيء من هذا القبيل.
إذن ما هي أسرع لغة على الأرجح،
Python أو JavaScript؟
الجمهور: JavaScript.
ديفيد مالان: JavaScript.
لماذا، هل تُعد JavaScript
فقط أفضل، وأسرع لغة؟
الجمهور: أنت لا تقوم
بإنشائه [INAUDIBLE]
ديفيد مالان: كرري ذلك؟
الجمهور: أنت لا تقوم
بإنشائه على خادم جديد،
إذن كل شيء يحدث على نفس--
ديفيد مالان: هذا هو السبب، نعم.
ليس علينا الدخول في المناقشة العقائدية
بشأن أي لغة
هي الأفضل أو الأسرع، ولكن حيث يتم
تشغيلهما هو أمر هام بالتأكيد.
يتم تشغيل JavaScript، تذكرون،
حسب التعريف، في المتصفح.
يتم إرسالها كتعليمة JavaScript
البرمجية إلى المتصفح
الذي ينفذ بعد ذلك جانب العميل.
تقوم Python اليوم حسب التعريف
بكل شيء من جانب الخادم.
وبالفعل، لا يعرف
المتصفح حتى أن
Python مُتضمّنة، لأن كل ما تحصل عليه
هو تعليمة HTML البرمجية التي تنتج عن ذلك.
إذن حسنًا، تبدو
هذه وسيطة لعدم
القيام بكل العمل الجديد الذي قمنا به اليوم
في إذا لم يوجد اسم، إذا لم يوجد سكن،
وكل ذلك،
واستخدام JavaScript فقط.

English: 
AUDIENCE: Whatever's fastest.
DAVID MALAN: Whatever fastest.
That's a pretty good heuristic
to use, what's fastest.
And we can make it prettier by
using Bootstrap or some library
to give you like a colorful box, or
red error text or something like that.
So which probably is faster,
Python or JavaScript?
AUDIENCE: JavaScript.
DAVID MALAN: JavaScript.
Why, is JavaScript just a
better, faster language?
AUDIENCE: You're not
creating it [INAUDIBLE]
DAVID MALAN: Say again?
AUDIENCE: You're not
creating it on a new server,
so it's all happening on the same--
DAVID MALAN: That's why, yeah.
We don't have to get into the
religious debate of which language
is better or faster, but where they're
running is certainly important.
JavaScript is running, recall,
by definition, in the browser.
It is sent as JavaScript
code to the browser
which then executes it client side.
Python by definition today is
doing everything server side.
And indeed, the browser
doesn't even know
Python is involved, because all it
gets is the HTML code that results.
So OK, that seems to
be an argument for not
doing all of the new work we did
today with if not name, if not dorm,
and all of that, and
just use JavaScript.

Arabic: 
لكن المشكلة هي إذا أصبحتم
سيئين قليلاً او أذكياء قليلاً
وقمتم بتنفيذ التحقّق من الخطأ
من جانب العميل فقط.
لأنه كما تقولون، إنها أسرع،
وبصراحة عندما أجعلها أجمل،
ستكون فقط أكثر
تفاعلية وأكثر سلاسة.
المشكلة هي أنه لا يمكنكم
ولا يجب أن تثقوا في المستخدمين.
لنفترض أنني مستخدم ضار
وأريد فقط
أن أضخ بعض البيانات الوهمية في موقع الويب
الخاص بكم، أو أريد أن أرسل لكم بريدًا غير مرغوب فيه،
أو أوجِد 1000 مشتركًا من الطلاب الجدد
غير موجودين في الواقع، أو أقوم فقط
بإنشاء مشاكل لكم بشكل عام.
حسنًا، قد تعتقدون،
حسنًا، لا بأس، أن لديّ
بعض الدفاعات في
المكان الصحيح، وتعليمة JavaScript البرمجية،
وسيحصل هذا الخصم على
ملاحظات سريعة وجميلة جدًا
والتي لم تقدموها في
هذه الحقول المختلفة.
ولكن بصراحة، لا يمكنكم الوثوق
في أي شيء أبدًا يقدمه الشخص.
إذا فتحتُ أدوات المُطوِّر
في Chrome، وانتقلتُ
إلى هذا بالأسفل هنا إلى القائمة نقطة 
نقطة نقطة، وانتقلتُ إلى الإعدادات،
ثم انتقلتُ إلى هنا بالأسفل، هناك.
هذا كل ما يلزم
لتعطيل جميع عملكم الجاد.
يمكنه أو يمكنها فقط
فتح متصفحه/متصفحها--
Chrome أو شيء آخر--
إيقاف تشغيل JavaScript.

English: 
But the problem is that if you get
a little sloppy or a little clever
and only implement your
error checking client side.
Because as you say, it's faster,
and frankly once I make it prettier,
it's just going to be more
interactive and more seamless.
The problem is you can't
and should not trust users.
Suppose that I'm a
malicious user and I just
want to inject some bogus data into
your website, or I want to spam you,
or subscribe 1,000 freshmen who
don't actually exist, or just
generally create problems for you.
Well, you might think,
well, that's OK, I
have some defenses in
place, and JavaScript code,
and this adversary is going to get
very quick feedback, very pretty
feedback that they've not
provided these various fields.
But honestly, you can't trust
anything ever coming from the human.
If I open up Chrome's
developer tools, and I
go to this down here to the dot
dot dot menu, and I go to Settings,
and I go down here, there.
That's all it takes to
disable all of your hard work.
He or she can just
open up their browser--
Chrome or something else--
turn off JavaScript.

Arabic: 
إذن الآن عندما أقوم في الواقع
بتقديم هذا الشكل، لن يكون
هناك تحقّق عند التقديم،
أو معالجة عند النقر.
سيتم تعطيل كل ذلك.
إذن إذا مضيتُ قدمًا ونقرتُ فوق
Register، ما يزال على الأقل،
في هذا الإصدار من froshims،
لديّ تحقّق من جانب الخادم، أيضًا.
إذن قد يكون هذا الأمر مُحبِطًا قليلاً،
ولكن هذا هو الواقع إلى حد ما.
هذا الأمر جيد تمامًا لاستخدام تعليمة
JavaScript البرمجية
وتعليمة جانب العميل البرمجية لإعطاء المستخدم
تجربة أفضل-- المعروفة أيضًا.
بـ UX، تجربة المستخدم.
ولكن لا يمكنكم اختصار 
الأمور وعدم تنفيذ
جانب الخادم المنطقي نفسه 
إلى حد ما لأنكم
تحتاجون إلى التصدي لهذا.
وإلا، ستُصبح البيانات الوهمية في 
النهاية في قاعدة بياناتكم،
ستسير الأمور على نحو خاطئ.
لا تثقوا أبدًا، أبدًا، في المستخدم.
أي أسئلة؟
الجمهور: هل يمكنك فعل الشيء نفسه عبر CSS؟
دايفيد مالان: هل يمكنك
فعل الشيء نفسه باستخدام CSS؟
الجمهور: نعم، هل يمكنك [INAUDIBLE]
INAUDIBLE] JavaScript]؟؟
دايفيد مالان: ليس باستخدام CSS فقط.
يمكنك استخدام CSS لجعل
رسائل الخطأ أجمل بكثير، نعم،
ولكن ليس الأمر منطقيًا بما يكفي باستخدام CSS فقط.
وفي الواقع، فقط لإعطائكم الآن
معنى الخاص بكيفية جعل الأشياء أجمل
حيث استمر بالإشارة إلى مهارات تصميم 
أفضل من تلك التي أقوم بعرضها هنا.

English: 
So now when I actually
submit this form, there's
going to be no on-submit
checking, no on-click handling.
All of that is disabled.
So if I go ahead and
click Register, I at least
still, in this version of froshims,
have server side checking, as well.
So this might be a little frustrating,
but it's kind of the reality.
It is perfectly fine
to use JavaScript code
and use client side code to give the
user a better experience-- a.k.a.
UX, user experience.
But you can't cut
corners and not implement
the same kind of logic
server side because you
need to defend against this.
Otherwise bogus data is going
to end up in your database,
things are going to go wrong.
Never, ever, ever trust the user.
Any questions?
AUDIENCE: Can you do the same via CSS?
DAVID MALAN: Can you
do the same with CSS?
AUDIENCE: Yes, can you [INAUDIBLE]
JavaScript [INAUDIBLE]??
DAVID MALAN: Not with CSS alone.
You can use CSS to make the
error messages far prettier, yes,
but not logically enough with CSS alone.
And in fact, just to give you a sense
now how you can make things prettier
since I keep alluding to better design
skills than the ones I'm showing here.

English: 
If we go to Bootstrap, this very
popular, free, and open source
library for CSS, it actually has
some interactive features, as well.
And if I go under components in
the documentation and I scroll down
and I go to forms,
you'll see, one, notice
that these forms are already
way prettier than the ones
I've been making, right?
It's like black text, and
gray text, and small text.
It just looks nicer and cleaner.
But it's relatively easy to do this.
And indeed, for the next
problems that you'll
be welcome to copy and paste some
of this sample code and HTML,
use Bootstrap CSS just to
make your forms prettier.
But what it can really do if I
go to the sub menu over here,
notice that there's this
validation section in Bootstrap.
And other libraries have this, too.
And you'll want to read
the actual documentation.
But if I just scroll down for a while,
here's a sample form in Bootstrap.
It already looks a little prettier than
anything I've made in just raw HTML.
But notice if I don't cooperate, you
can do really cool validation of forms
with green and red text if
the user does or doesn't
cooperate by using a mix of CSS,
but with some JavaScript code.
And so what Bootstrap does
for you is it actually

Arabic: 
إذا انتقلنا إلى Bootstrap، هذه المكتبة
مفتوحة المصدر، والمجانية، والشائعة
جدًا من CSS، تحتوي في الواقع على بعض 
الميزات التفاعلية، أيضًا.
وإذا انتقلتُ أسفل المكونات في
الوثائق وقمتُ بالتمرير
وانتقلتُ إلى الأشكال،
سترون، شكل واحد، لاحظوا
أن هذه الأشكال هي بالفعل
أجمل بكثير من تلك التي
قمتُ بإنشائها، أليس كذلك؟
إنها مثل نص أسود،
ونص رمادي، ونص صغير.
يبدو الأمر فقط أجمل وأفضل.
لكن من السهل القيام بذلك بشكل نسبي.
وبالفعل، بالنسبة للمشاكل
التالية حيث سيكون
مسموح لكم أن تقوموا بنسخ ولصق
تعليمة النموذج البرمجية هذه وHTML،
واستخدام Bootstrap CSS فقط
لجعل أشكالكم تبدو أجمل.
ولكن ما يمكنها القيام به حقًا إذا
انتقلتُ إلى القائمة الفرعية هنا،
لاحظوا أنه يوجد قسم
التحقّق هذا في Bootstrap.
وتحتوي المكتبات الأخرى على هذا، أيضًا.
وسترغبون في قراءة
الوثائق الفعلية.
ولكن إذا قمتُ بالتمرير للأسفل لبعض الوقت،
ها هو نموذج شكل في Bootstrap.
يبدو بالفعل أجمل قليلاً من
أي شيء قمتُ بإنشائه في HTML البسيط فقط.
ولكن لاحظوا إذا لم أتعاون، يمكنكم إجراء
تحقّق رائع من الأشكال حقًا
باستخدام نص أخضر وأحمر إذا
تعاون المستخدم
أو لم يتعاون باستخدام مزيج من CSS،
ولكن مع بعض تعليمة JavaScript البرمجية.
إذن ما يفعله Bootstrap
لكم في الواقع هو

English: 
automates some of the process
of that JavaScript code
that we saw two weeks
ago and just used now.
But it doesn't just pop
up a message for the user,
it actually gives them
more immediate feedback.
And almost any popular web site
you visit these days gives you
this more immediate proximal input.
Generally you don't see some
simple error message popping up,
even though that's easier to do.
Any questions?
All right, so where did
that logic come from?
So let me go into, for
instance, my template
file now for the form in froshim6--
again, the last of these examples--
and you'll notice that I did this.
If I scroll through this
file, you'll see the same HTML
as we've been using for some time.
But notice at the bottom of the
page that I draw some inspiration
from two weeks back when we looked
at HTML, and CSS, and JavaScript.
So just as a quick refresher,
notice how this is working.
This line of code says
in JavaScript check
the document using the query selector,
which lets you select anything

Arabic: 
تشغيل معالجة تعليمة
JavaScript البرمجية تلك تلقائيًا
التي رأيناها منذ أسبوعين
واستخدمناها الآن للتو.
ولكن فقط لا تنبثق
رسالة منها للمستخدم،
في الواقع تعطيه
ملاحظات فورية أكثر.
وتقريبًا أي موقع ويب شائع
تزورونه هذه الأيام يمنحكم
هذا المدخل الأقرب والفوري أكثر.
بشكل عام لا ترون
رسالة خطأ بسيطة منبثقة،
حتى على الرغم من أن هذا الأمر أسهل للقيام به.
أي أسئلة؟
حسنًا، إذن من أين
أتى ذلك المنطق؟
إذن دعوني أنتقل، على
سبيل المثال، إلى ملفي
النموذجي الآن للشكل في froshim6--
مجددًا، آخر هذه الأمثلة--
وستلاحظون أنني فعلتُ هذا.
إذا قمتُ بالتمرير خلال هذا الملف،
فسترون HTML نفسها
كما كنا نستخدمها لبعض الوقت.
ولكن لاحظوا في أسفل الصفحة
أنني استحضرتُ بعض الإلهام
منذ أسبوعين عندما نظرنا في
HTML، وCSS، وJavaScript.
إذن فقط لأنشط ذاكرتكم سريعًا،
لاحظوا كيف يعمل هذا.
يقول هذا السطر من التعليمة البرمجية
في JavaScript تحقّق من
المستند باستخدام مُحدِد الاستعلام،
الذي يتيح لكم تحديد أي شيء

Arabic: 
في صفحة الويب حيث يبحث عن شكل.
وعندما يتم تقديم هذا الشكل، استدعوا
الدالة المجهولة التالية.
إذا عثر مُحدِد استعلام المستند
على مدخل ليس له قيمة--
وأقول ليس بسبب
علامة التعجب هنا--
التي تخبر المستخدم بهذا، 
يجب عليك تقديم اسمك
وقم بإرجاع خاطئ.
وأيضًا إذا لم يقدم المستخدم قيمة
لقائمة التحديد-- المعروفة أيضًا بالسكن--
امضي قدمًا وقُم بتنبيهه أنه
يجب أن يقدم السكن،
وإلا قُم بإرجاع صحيح.
وفقط لأكون واضحًا 
ولنتذكر منذ أسبوعين،
ما الذي أقوم بإرجاعه خاطئ؟
ما الذي يفعله هذا التأثير بشكل منطقي؟
نعم، كرّر ذلك مجددًا؟
ما كان ذلك؟
سمعتُ همسًا هنا.
لا؟
نعم، هذا يمنع 
تقديم الشكل.
السلوك الافتراضي لشكل ما
هو أنه يريد أن يتم تقديمه.
هذا هو سبب وجوده.
ولكن إذا قمتم بإرجاع
خاطئ في JavaScript، فإنها
ستقلل تدوير ذلك وتمنع 
هذا السلوك الافتراضي،
وبالتالي إيقاف المستخدم من
تقديم الشكل على الإطلاق.

English: 
in the web page looking for a form.
When that form is submitted, call
the following anonymous function.
If the document query selector finds
an input that does not have a value--
and I say not because of
the exclamation point here--
then yell at the user with
this, you must provide your name
and return false.
Else if the user did not provide a value
for the select menu-- a.k.a. the dorm--
go ahead and alert them that
they must provide the dorm,
otherwise return true.
And just to be clear and to
recall from two weeks ago,
what am I returning false?
What does that effect have logically?
Yeah, say again?
What was that?
I heard a whisper here.
No?
Yeah, it prevents
submission of the form.
The default behavior of a form
is it wants to be submitted.
That's why they exist.
But if you return
false in JavaScript, it
will short circuit that and
prevent that default behavior,
thereby stopping the user from
submitting the form at all.

Arabic: 
إذن دعونا نرجع خطوة للخلف الآن، هناك
أشياء كثيرة تحدث في هذا الملف الآن
فقط.
في هذا المثال السادس 
والنهائي، لاحظوا أن
لدينا application.py، وهو 
نقطة دخول، ما يُسمى بوحدة التحكم
في تطبيق الويب هذا.
ويحتوي على طريق يبدو 
ببساطة شديدة هكذا بالنسبة إلى خط مائل.
عندما يحصل المستخدم على خط مائل، 
يتم إرجاع هذا القالب ببساطة.
ما الذي يوجد في قالب index.html هذا؟
حسنًا، إنه يحتوي على ملف HTML جزئي.
إنه يحتوي على HTML هذه.
ولكنه لا يحتوي على doctype،
وعلامة HTML، وعلامة رأس، وعلامة البنية،
وعلامة العنوان، وكل ذلك.
يحتوي فقط على الأشياء التي يجب
أن تكون داخل علامة البنية.
لأن هذا الملف
يستخدم القليل من jinja،
التي تُعد اللغة النموذجية
التي يستخدمها Flask.
يمكنكم فقط التفكير فيه
كـ Flask، هذا أمر جيد.
إنه يستخدم بعض من HTML هنا، ولكنه أيضًا 
يستخدم في أسفل الملف JavaScript.
إذن كما فعلنا من قبل عندما
نظرنا في مصدر الصفحة،

English: 
So let's take one step back now, there's
now so much going on in this one file
alone.
In this sixth and final
example, notice that we
have application.py, which is the
entry point, the so-called controller
of this web application.
It has a route which very simply
for slash looks like this.
When the user gets slash, this
template is simply returned.
What is in that index.html template?
Well, it contains a partial HTML file.
It contains this HTML.
But it does not contain the doctype,
the HTML tag, head tag, the body tag,
the title tag, and all of that.
It only contains the stuff that
should go inside of the body tag.
Because this file is
using a bit of jinja,
which is the templating
language that Flask uses.
You can just think of it
as Flask, that's fine.
It uses some HTML here, but it also in
the bottom of the file uses JavaScript.
And so just as before when we've
looked at the source of the page, what

English: 
I'm going to see in the browser
on this forms page is no jinja,
no Python, nothing related to Flask.
Just a fully formed HTML
page that also now contains
some of that client side code.
And so I have this mixture now
of several different language,
but each of which solves
a very distinct problem.
Yeah?
AUDIENCE: So I think it was a
week ago or two weeks ago when
we were working on
JavaScript and CSS, you
were saying that it's preferable
to split languages, not
mix them in the same document.
Right now we are mixing
multiple languages.
DAVID MALAN: Really good observation.
So a couple of weeks ago I really
preached the separation of concerns,
and therefore separation of files.
And that's why we
introduced a .css file,
we also briefly showed
examples of a .js file.
The short answer is as your
applications get more complex,
life starts to get messy.
And the team and I were
actually talking about this
earlier as to how to present
some of these examples,
because what you are seeing in my
design decision here is a tension.

Arabic: 
الشيء الذي سأراه في المتصفح
في صفحة الأشكال هذه ليس jinja،
وليس Python، ولا شيء متعلق بـ Flask.
فقط صفحة HTML تم تشكيلها
بشكل كامل وتحتوي الآن أيضًا
على بعض تعليمة جانب العميل البرمجية هذه.
إذن لديّ هذا المزيج الآن
من عدة لغات مختلفة،
لكن كل منها يحل
مشكلة مميزة للغاية.
أجل؟
الجمهور: إذن أعتقد أنه
منذ أسبوع أو أسبوعين عندما
كنا نعمل على
JavaScript وCSS، كنتَ
تقول أنه من المُفضل
تقسيم اللغات، وليس
مزجها في المستند نفسه.
الآن نقوم بمزج
لغات متعددة.
ديفيد مالان: ملاحظة جيدة حقًا.
إذن منذ أسبوعين نصحتكم
بالفعل بفصل المخاوف،
وبالتالي فصل الملفات.
ولهذا السبب قدمنا
ملف .css،
كما عرضنا بشكل موجز أمثلة
من ملف .js.
الإجابة المختصرة هي أنه بينما
تصبح تطبيقاتك أكثر تعقيدًا،
ستصبح الحياة فوضوية.
وكنتُ أتحدث إلى الفريق
في الواقع بشأن هذا
في وقت سابق حول كيفية تقديم
بعض هذه الأمثلة،
لأن ما ترونه في قرار تصميمي
هنا يُشكل صعوبة.

English: 
So that tension here is as follows.
It is not necessarily the best practice
to just have your logical JavaScript
code comingled with your HTML.
It makes it harder to
collaborate with someone else.
If one of you is really good at design
and wants to work on the HTML and CSS,
the other person really wants to do
the JavaScript code, kind of hard
to do that when they're
both in the same file.
So we could factor this out.
I could change this line, just
to be super clear, to be this.
Instead of putting my actual code in the
file, I could do something like this.
The source of this shall be
form.js, and that is just it.
And then I have a separate file maybe
my colleague works in as follows.
But at some point the thoughts
that go through my head
are, it's only like 10
lines of code and I just
have to create a second file
now, and that second file
is going to be maybe in a
different folder as my template.
And you know, it feels like this
is just overengineering a solution
to the problem.
However, once it's 20 lines, 100
lines, now OK, now it's feeling messy.
Somewhere there's this inflection point.

Arabic: 
إذن هذه الصعوبة هنا هي على النحو التالي.
إنها ليست أفضل ممارسة بالضرورة
لتكون لديكم فقط تعليمة JavaScript
البرمجية المنطقية والمختلطة باستخدام HTML لديكم.
هذا يجعل التعاون
مع شخص آخر صعبًا أكثر.
إذا كان أحدكم جيدًا جدًا في التصميم
ويريد العمل في HTML وCSS،
ويريد الشخص الآخر حقًا أن يقوم بإنشاء
تعليمة JavaScript البرمجية، القيام بذلك
صعب إلى حد ما أثناء وجود
كلتاهما في الملف نفسه.
إذن يمكننا استبعاد هذا.
يمكنني تغيير هذا السطر، فقط
ليكون واضحًا جدًا، ليصبح هكذا.
بدلاً من وضع تعليمتي البرمجية الفعلية
في الملف، يمكنني القيام بشيء كهذا.
سيكون مصدر هذا 
form.js، وهذا كل شيء.
ومن ثم لديّ ملف منفصل ربما
يعمل فيه زميلي كما يلي.
ولكن في مرحلة ما الأفكار
التي تدور في رأسي
هي، إنها فقط مثل 10
سطور من التعليمة البرمجية ويجب
أن أقوم بإنشاء ملف ثاني
الآن، وهذا الملف الثاني
ربما سيكون في مجلد
مختلف مثل القالب الخاص بي.
وكما تعلمون، يبدو أن هذا
فقط يعمل على هندسة حل بشكل فائق
للمشكلة.
ومع ذلك، بمجرد وجود 20 سطرًا، 100 
سطر، حسنًا، الآن يبدو الأمر فوضويًا.
في مكان ما يوجد نقطة الانعطاف هذه.

English: 
And this is where reasonable people will
disagree, and I might argue one way,
you might argue the other way.
And honestly, both of
us are probably right.
And so this just speaks to the
web's development over time.
And there's fancier frameworks
now. and if we tie things earlier
into the question about CS50 beyond,
an opportunity after this class that
looks more closely at
web programming, there
are even fancier frameworks nowadays
than Flask and than Bootstrap
that if tried to solve this problem.
React is one of the most popular
ones developed by Facebook,
now open source and
used by so many people
around the world that
actually addresses this issue.
And it allows you to separate
your HTML from your CSS
from your JavaScript in different parts
of the file but still in the same file.
And that was their particular solution.
And View and Angular, there are so many
different solutions to these problems.
And unfortunately, once we take
the training wheels of CS50 off,
this is what's ahead of you.
The world is messy.
And the reason there are so many
darn languages and frameworks is
because people like you have
these instincts and think,
this could be done better.
And thus do we iterate and
have new and new technologies.
But this is the kind of
stuff-- and honestly, this

Arabic: 
وهذا حيث لن يوافق الأشخاص 
المنطقيون، وقد أناقش بطريقة ما،
وتتناقشون بطريقة أخرى.
وبصراحة، على الأرجح نكون
جميعًا على حق.
إذن هذا فقط يعبر عن 
تطوير الويب مع مرور الوقت.
وتوجد أُطُر العمل الرائعة 
الآن. وإذا ربطنا الأمور بما سبق
في السؤال حول CS50 وما بعدها،
فالفرصة بعد هذه الدورة التي تنظر
عن كثب في 
برمجة الويب، توجد
أطُر عمل رائعة أكثر هذه الأيام
من Flask ومن ثم Bootstrap
عند محاولة حل هذه المشكلة.
React هو أحد الأطُر الشائعة جدًا
التي قام Facebook بتطويره،
الآن أصبح مفتوح المصدر
ويستخدمه عدة أشخاص
في جميع أنحاء العالم
وبالفعل يعالج هذه المشكلة.
ويتيح لكم فصل
HTML لديكم عن CSS
وعن JavaScript في أجزاء مختلفة
من الملف ولكن ما زال في الملف نفسه.
وكان ذلك هو الحل الخاص بها.
بالإضافة إلى View وAngular، يوجد الكثير من
الحلول المختلفة لهذه المشاكل.
ولسوء الحظ، بمجرد أن نُخرِج
عجلات التدريب من CS50،
هذا ما ستواجهونه.
العالم فوضوي.
والسبب في وجود عدة
لغات وأطُر العمل
هو أن أشخاص مثلكم لديهم
هذه البديهيات ويعتقدون،
أنه يمكن القيام بهذا على نحو أفضل.
وبالتالي نقوم بالتكرار 
ولدينا العديد من التكنولوجيات الجديدة.
ولكن هذا النوع من 
الأشياء-- وبصراحة، هذا

Arabic: 
هو نوع من السخافة
بحيث يتغير مع مرور الوقت.
أساسيات HTTP،
وتعليمة جانب العميل البرمجية،
وتعليمة JavaScript البرمجية، تلك 
الأساسيات ثابتة
حتى على الرغم من تغير 
تفاصيل التنفيذ.
إذن الإجابة المختصرة هي،
هل يمكن أن يكون هذا أفضل؟
من المحتمل.
هل يمكن أن يكون أفضل بكثير؟
لا أعرف.
الآن يصبح الأمر جداليًا 
بشكل أكبر بين المُطورين.
سؤال جيد.
حسنًا، إذن دعونا الآن نستخدم
بعض هذه الكتل البنائية
الأساسية لإنشاء مجموعة
نهائية من الأمثلة التي توضح
ميزة مألوفة جدًا بالنسبة
لمعظمنا وتُذكرنا بما
قمنا به منذ أسبوعين باستخدام بحث Google.
في الوقت الذي بحثنا فيه عن قطط.
اليوم سنُبقي الأمر أبسط 
قليلاً وأقل رسومية
ونبحث فقط عن كلمات.
لأنكم ستتذكرون من
مجموعة مشاكل المدقق الإملائي لدينا،
قمتم بتنفيذ مدقق إملائي
بأكثر من 140000 كلمة إنجليزية.
هذه مجموعة بيانات
هامة حقًا للبحث خلالها،
ومن المحتمل أنكم جميعًا على دراية
بالإكمال التلقائي هذه الأيام.
يوجد بالكاد موقع ويب هذه الأيام
أنه عند بدء كتابته
لا يحاول إنهاء
أفكاركم من أجلكم.
Google، Facebook، أي
عدد من المواقع الأخرى.
إذن الإكمال التلقائي، كيف يعمل ذلك؟

English: 
is the kind of silliness
that changes over time.
The fundamentals of HTTP,
and client side code,
and JavaScript code, those
fundamentals are invariant
even as the implementation
details change.
So the short answer is,
could this be better?
Probably.
Could it be much better?
I don't know.
It really now becomes more
of a debate among developers.
Good question.
All right, so let's now use
some of these basic building
blocks to make a final set
of examples that demonstrates
a feature with which most of us are
pretty familiar reminiscent of what we
did two weeks ago with Google Search.
At the time we searched for cats.
Today we'll keep it a little
simpler and a little less graphical
and just search for words.
Because you'll recall from
our speller problem set,
you implemented a spell checker
with 140,000 plus English words.
That's a pretty juicy
dataset to search over,
and you're probably all familiar
with autocomplete these days.
There's hardly a website these
days that when you start typing it
doesn't try to finish
your thought for you.
Google, Facebook, any a
number of other sites.
So autocomplete, how does that work?

Arabic: 
حسنًا، دعوني أقترح
النموذج العقلي التالي.
إذا كانت لديكم مجموعة من البيانات
مثل قائمة كبيرة من الكلمات،
أو قائمة كبيرة من الأصدقاء على Facebook،
أو قائمة كبيرة من أي شيء،
قد تقومون بتخزين ذلك جانب الخادم
لأن هذه البيانات كثيرة جدًا.
وفي الواقع، الأسبوع المقبل، قد 
تقومون بالتخزين في قاعدة بيانات كبيرة.
ولكن لليوم سنقوم
فقط بالتخزين في ملف
مثلما فعلنا لمجموعة المدقق الإملائي.
ولكن إذا كنتم ترغبون في إنشاء
تجربة تفاعلية
للشخص، ما هي
اللغة التي من المحتمل
أنكم سترغبون في استخدامها حتى
يحصل هو أو هي على ملاحظات فورية؟
على الأرجح JavaScript، أليس كذلك؟
ذلك هو المبدأ بأكمله.
ستقوم تعليمة جانب العميل البرمجية
بالتنفيذ بشكل أسرع لأنه لا يوجد
إنترنت بينكم وبين التعليمة البرمجية.
ولكن باستخدام Python، يمكنكم
الوصول إلى الملفات.
ومع ذلك، باستخدام تعليمة JavaScript البرمجية
يمكنكم الوصول بشكل أقرب إلى المستخدم،
لذا توجد هذه الصعوبات.
إذن كيف يمكننا أن نمضي في بناء موقع
يتيح للشخص عبر الشكل البحث
عبر ذلك الملف عن كلمات؟
حسنًا، دعونا نبدأ على النحو التالي.
إذن في الكلمة 0 لدينا ما يلي.
كبير، وهو مجرد ملف نصي
مُستعار من مجموعة مشاكل المدقق الإملائي،
140000 كلمة، سطر واحد ضعيف فيه.

English: 
Well, let me propose the
following mental model.
If you do have some data set
like a big list of words,
or a big list of Facebook friends,
or a big list of whatever,
you might store that server side
because it's a lot, a lot of data.
And in fact, next week you
might store in a big database.
But for today we'll
just store it in a file
like we did for the speller piece set.
But if you want to create
an interactive experience
for the human, what
language are you're probably
going to want to use so that he
or she gets immediate feedback?
Probably JavaScript, right?
That's the whole principle.
Client side code is just going
to execute faster because there's
no internet between you and the code.
But with Python, you
have access to files.
And yet with JavaScript code you
have closer access to the user,
so there's these tensions.
So how could we go about building a
site that lets a human via form search
across that file for words?
Well, let's start as follows.
So in word 0 we have the following.
Large, which is just a text file
borrowed from the speller problem set,
140,000 words, one poor line therein.

English: 
I'm not even going to
double click and open it
because it's so darn big it'll
take a few seconds to open.
In application.py we have probably
the entry point to this application,
and in templates we have just
three templates this time.
So just when you're reading someone
else's code for the first time,
where should our entry point be?
Where should we start looking
to understand what's going on?
Maybe application.py.
Or honestly, you know what?
If you want to see what
something does, run it.
No harm in doing that.
So lets run Flask run.
Make this a little bit bigger.
Let me open up the URL here,
open, and I see a very simple form
asking me for a query.
Let me go ahead and search
for a and click Search.
And after a moment, OK.
This is a lot of words,
but apparently these
are all the English words
that our dictionary knows
about that start with the letter a.
And if I go all the way
to the bottom, you'll
see it stops with az whatever
with no B words, in fact.
Well, let's make sure this actually
works and isn't just a trick.
Let's search for b words.
OK, so that seems to work, as well.
And notice I borrowed some
inspiration from Google.

Arabic: 
لن أقوم حتى بالنقر 
عليه نقرًا مزدوجًا وفتحه
لأنه كبير جدًا
سيستغرق بضع ثواني لفتحه.
في application.py على الأرجح لدينا
نقطة دخول إلى هذا التطبيق،
وفي القوالب لدينا فقط
ثلاثة قوالب هذه المرة.
إذن فقط عندما تقرأون التعليمة 
البرمجية لشخص آخر لأول مرة،
أين يجب أن تكون نقطة دخولنا؟
أين يجب أن نلقي نظرة
لفهم ما يحدث؟
ربما application.py.
أو بصراحة، أتعرفون ماذا؟
إذا كنتم ترغبون في معرفة
ما يقوم به الشيء، قوموا بتشغيله.
لا ضرر في القيام بذلك.
إذن لنُشغّل Flask.
اجعل هذا أكبر قليلاً.
دعوني أفتح عنوان URL هنا،
وأفتح، وأرى نموذجًا بسيطًا جدًا
يسألني عن استعلام.
دعوني أمضي قدمًا وأبحث
وأنقر فوق Search.
وبعد لحظة، حسنًا.
هذا عدد كبير من الكلمات،
لكن يبدو أن
هذه جميعها الكلمات الإنجليزية
التي يعرفها قاموسنا
بشأن تلك التي تبدأ بحرف a.
وإذا انتقلتُ بنفس الطريقة 
إلى الأسفل، سترى
أنها تتوقف ند az بغض النظر
عن أي كلمة تبدأ بالحرف B، في الواقع.
حسنًا، دعونا نتأكد من أن هذا في الواقع
يعمل وليس مجرد خدعة.
لنبحث عن كلمات تبدأ بحرف b.
حسنًا ، إذن يبدو أن هذا يعمل، أيضًا.
ولاحظوا أنني استعرت بعض
الإلهام من Google.

Arabic: 
لاحظوا أن الطريقة التي استخدمتُها
تُسمى خط مائل search استخدمناها منذ أسبوعين.
هل تأخذ معلمة إشارة للاستعلام،
وb هو أيًا كان ما كتبه الشخص.
لذا إذا كنتَ تريد البحث
عن كلمات تبدأ بالحرف z، enter،
آمل أنه يجب أن أعود الأن إلى الكلمات التي تبدأ بالحرف z.
إذن الآن بخلاف ما قمنا به منذ أسبوعين،
يمكننا تنفيذ كل من واجهة التطبيق
والخلفية لمحرك البحث.
لكن محرك البحث الخاص بنا
يبحث الآن فقط عن الكلمات.
لذا دعونا ننظر في application.py
كما هو مقترح، وهو نقطة الدخول،
ولنرى كيف أقوم بهذا.
إذن هذه هي التعليمة البرمجية
التي استعرتُها من الأسبوع الماضي
عندما قمنا سريعًا بتنفيذ
المدقق الإملائي
في 12 أو 20 سطرًا من تعليمات Python البرمجية.
أنا أُعلن عن متغير
شامل يُدعى كلمات،
وقمتُ بتكبيره فقط
ليذكرنا بالمرة الماضية
ومجموعة المشكلة.
أنا أستخدم هذه الصيغة
التي أشرتُ إليها في وقت سابق
هي تقليدية أكثر أو باثونية.
افتح الملف الكبير في وضع القراءة
واطلب ملف المتغير.
ثم هنا التكرار الحلقي الذي
يمكنك باستخدامه تكرار أكثر من
كل سطر في الملف،
وتقرأ سطر واحد في كل مرة.
ولكن تذكر، ما الذي ينتهي به
كل سطر في هذا الملف؟

English: 
Notice that the route I'm using is
called slash search like two weeks ago.
Does take a cue parameter for query,
and b is whatever the human typed in.
So if I want to search
for z the words, enter,
I should hopefully get back now z words.
So now unlike two weeks ago, we
can implement both the front end
and the back end for a search engine.
But our search engine's
searching now just for words.
So let's look at application.py as
proposed, which is the entry point,
and let's see how I'm doing this.
So this is some code that I
borrowed a little bit from last week
when we quickly implemented
the spell checker
in like 12 or 20 lines of Python code.
I'm declaring a global
variable called words,
and I capitalized it just to
be reminiscent of last time
and the problem set.
I'm using this syntax
which I alluded to earlier
is just more conventional or Pythonic.
Open the large file in Read
mode and call the variable file.
Then here is a for loop via
which you can iterate over
every line in the file,
reading one at a time.
But recall, what does every
line in this file end with?

English: 
Like a backslash n, and we don't
really want those as part of the words.
That's not part of the English word.
So R strip, right strip removes any
whitespace from the end of the string.
And that's why I needed
to add that extra line.
So I'm just cleaning up the
file or massaging the data
as you might do with any sort
of data based application.
So then I just seem to have this
route that renders the template.
If I look in index.html,
let's follow the bread crumbs.
Go into index.html.
OK, not that much going on here.
Looks like an HTML form, the
action of which is slash search,
just like Google's.
The method of which is is
get just like Google's.
There's nothing really private about
the words I'm searching for here,
so I don't care.
There's some fancier features here.
Notice placeholder is the
grayed out text the human sees.
Auto focus.
What does this do again?
This is just a UI feature,
better user experience.
AUDIENCE: Puts the like,
right in the text box.
DAVID MALAN: Yeah, it puts the
cursor right in the text box.
To focus on something in a
web page means make it what's
interacting with the user right now.
And Mac OS, for instance,
highlights it in blue.
So when you first load
the page, the cursoe's

Arabic: 
مثل خط مائل عكسي n، ونحن لا نريد
بالفعل تلك كجزء من الكلمات.
هذا ليس جزءًا من الكلمة الإنجليزية.
لذا R strip، يزيل الشريط الأيمن أي
مسافة من نهاية السلسلة.
وهذا هو سبب وراء أنني أحتاج إلى
إضافة هذا الخط الإضافي.
لذلك أنا أقوم فقط بتنظيف
الملف أو التلاعب بالبيانات
كما قد تفعلون ذلك باستخدام أي نوع
من التطبيقات القائمة على البيانات.
إذن بعد ذلك يبدو أن لدي هذا
الطريق الذي يُقدّم القالب.
إذا نظرتُ في index.html،
دعونا نتبع الآثار.
انتقل إلى index.html.
حسنًا،هذا لن يحدث كثيرًا هنا.
تبدو مثل HTML، حيث يكون
الإجراء الخاص به هو خط مائل search،
تمامًا مثل ذلك الخاص بـ Google.
طريقة ذلك هي get
تمامًا مثل تلك الخاصة بـ Google.
لا يوجد أي شيء خاص حقًا بشأن
الكلمات التي أبحث عنها هنا،
لذا لا أهتم بذلك.
توجد بعض الميزات الرائعة أكثر هنا.
لاحظوا العنصر النائب هو النص
الرمادي الذي يراه الشخص.
تركيز تلقائي.
مجددًا ما الذي يقوم به هذا؟
هذه هي ميزة واجهة المستخدم فقط،
تجربة أفضل للمستخدم.
الجمهور: تضع ما شابه ذلك،
مباشرة في مربع النص.
دايفيد مالان: نعم، إنها تضع المؤشر
مباشرة في مربع النص.
للتركيز على شيء ما في 
صفحة ويب يعني جعله
يتفاعل مع المستخدم في الوقت الحالي.
ويقوم نظام التشغيل Mac، على سبيل المثال،
بتظليله باللون الأزرق.
إذن عندما تقومون أولاً بتحميل
الصفحة، فإن وميض المؤشر

English: 
blinking in the choice of text
boxes that you care about most.
Autocomplete off just disables the
browser's version of autocomplete.
So I don't see past searches,
just because the whole point here
is to implement this
ourselves ultimately,
and then I have my search button.
This is just jinja stuff from
Flask so that I have a layout file.
Lets follow that breadcrumb.
Lay out.html, nothing really
that interesting going on there.
If you've ever wondered why we
have these in a lot of our demos,
this cryptic looking line here
just makes web sites look better
on mobile devices.
Typically by default if you pull up
your phone and look at a website,
if it doesn't have
that kind of line, like
the text is going to be super
tiny unless you pinch and zoom.
By using this line and
variations thereof,
it will increase the
default font size a bit
to make it a little more
tolerable on small screen.
So it's an easy win
for users experience.
OK, I seem to have exhausted all the
interesting stuff in these templates.
Let's look at another and final route.
Here's my search route, and
this is pretty Pythonic.
This is a mouthful, and
will re-implement it
in a different way in just a moment.

Arabic: 
في اختيار مربعات النص
ما تهتمون به بشكل أكبر.
يعمل Autocomplete off فقط على تعطيل
إصدار المتصفح من الإكمال التلقائي.
إذن لا أرى عمليات البحث السابقة،
فقط لأن المغزى هنا
هو تنفيذ هذا
بأنفسنا في نهاية المطاف،
ومن ثم لديّ زر البحث الخاص بي.
هذه أشياء خاصة بلغة jinja من
Flask لكي يكون لديّ ملف تخطيط.
دعونا نتبع تلك الآثار.
layout.html، لا شيء مثير
للاهتمام حقًا يحدث هناك.
إذا فكرتم في السبب حصلونا على هذه
في العديد من عروضنا التوضيحية،
هذا السطر الذي يبدو مشفرًا هنا
يجعل مواقع الويب تبدو أفضل فقط
على أجهزة الهواتف المحمولة.
بشكل افتراضي عادةً، إذا قمتم بسحب
هواتفكم ونظرتم في موقع ويب،
إذا لم يكن يحتوي على
هذا النوع من السطور، على سبيل المثال
سيكون النص صغيرًا
جدًا إلا إذا قمتم بالضغط والتكبير.
باستخدام هذا السطر 
وأشكاله المتنوعة،
سيُزيد حجم
الخط الافتراضي قليلاً
لجعله مقبولاً أكثر قليلاً
على شاشة صغيرة.
إذن هذا نجح سهل
لتجربة المستخدمين.
حسنًا، يبدو أنني اختبرت جميع الأشياء
المثيرة للاهتمام في هذه القوالب.
دعونا ننظر في طريق أخير ونهائي.
ها هو طريق البحث لديّ،
ويُشبه كثيرًا Python.
هذا صعب،
وسنعيد تنفيذه
بطريقة مختلفة في الحال.

Arabic: 
إذن لديّ طريق بحث يستمع إلى
الحصول على طلبات في خط مائل search.
ثم هذا الخط الخيالي هو باثوني
تقريبًا مثل ما تحصل عليه التعليمة البرمجية.
وسأُفسر ماذا 
يفعل هذا ولماذا
هو تقليدي بدلاً من
كونه مباشر للوهلة الأولى.
ومن ثم أقدم القالب،
مع التمرير في هذه الكلمات.
إذن لدى هذه الطبقة على السطر
17 بالفعل تأثير
البحث في 140000
كلمة لأي كلمات
تبدأ بما كتبه المستخدم.
انظروا، سيكون هذا 
أمرًا مزعجًا للقيام به.
في Python، يمكنكم القيام بذلك
حرفيًا باستخدام سطر واحد.
سطر طويل، لكن سطر واحد مع ذلك.
دعوني أوضح هذا أكثر.
إذا كنتُ أبحث عن
كلمات في هذا الملف الكبير،
فقد أقوم بشيء مثل هذا.
الكلمات هي قائمة فارغة.
لذا هذه الكلمات بالأحرف الصغيرة
هي كل الكلمات التي تتطابق،
والتي أريد إرسالها إلى المستخدم.
لذا بشكل افتراضي ليس لدي أي فكرة
عن ما أقوم بإرساله.
لكنني أعرف أنه يمكنني القيام بذلك.
لكلمة في كلمات--
وهو المتغير بالأحرف الكبيرة،
الثابت في الأعلى
الذي يحتوي على الكل--
أو حتى غير ثابت،
لكن المتغير الشامل الذي
يحتوي على كل الكلمات من الملف، هنا

English: 
So I have a search route that listens
for get requests on slash search.
Then this crazy looking line is
about as Pythonic as code gets.
And I'll explain what
this is doing and why
it's conventional as opposed to
straightforward at first glance.
And then I render the template,
passing in these words.
So this one liner on line
17 actually has the effect
of searching 140,000
words for whatever words
start with what the user typed in.
See, this would be a
pain in the neck to do.
In Python you can do it
with literally one line.
A long line, but one line nonetheless.
Let me make this more clear.
If I were to search for
words in this big file,
I might do something like this.
Words is an empty list.
So this lower case words is
all of the words that match,
that I want to send back to the user.
So by default I have no
idea what to send back.
But I do know I can do this.
For word in Words--
which is the capitalized variable,
the constant up at the top
that has the whole--
or not even constant,
but the global variable that has
all of the words from the file, here

Arabic: 
هو التكرار الحلقي فوق هذه.
يمكنني قول شيء من هذا القبيل الآن.
إذا كانت الكلمة الحالية تبدأ
بكل ما كتبه المستخدم-- حسنًا،
فما الذي يكتبه المستخدم؟
حسنًا، q يساوي request.args.get
علامة اقتباس وعلامة إنهاء الاقتباس q،
يعطيني اسم المستخدم، أو سكنه،
أو في هذه الحالة قيمة Q للاستعلام.
لذلك إذا كانت الكلمة التي نقوم حاليًا
بتكرارها تبدأ بالحرف q،
يمكنني المضي قدمًا والإلحاق إلى--
عذرًا، إلحاق هذه الكلمة إلى هذه القائمة.
هل ستقولون أنكم معتادون
على هذه السطور هنا؟
للتلخيص، أعطني قائمة فارغة
حيث يمكنني تخزين نتائج البحث،
قم بتكرار كل 140000 كلمة
الإضافية الممكنة، احصل على--
وفي الواقع، كان هذا أمر غبي.
يجب أن أضع هذا فقط هنا، لأنني
فقط أحتاج إلى التحقق من ذلك مرة واحدة.
لذلك قم بتخزين مدخل المستخدم
في متغير يُسمى q.
لكل كلمة ضمن 140000، تحقّق مما
إذا كانت تبدأ بمدخل المستخدم--
a، b، z، أيًا كان.

English: 
is a for loop over those.
I can now say something like this.
If the current word starts with
whatever the user typed in-- well,
what's the user typing in?
Well, q equals request.args.get
quote-unquote q,
gives me the user's name, dorm,
or in this case Q value for query.
So if the word that we're currently
iterating over starts with q,
I can go ahead and append to my--
whoops, append to this list that word.
Would you say you're comfortable
with these lines here?
To recap, give me an empty list in
which to store the search results,
iterate over all possible
140,000 plus words, get--
and actually, this was stupid.
I should just put this up here, because
I only need to check for that once.
So store the user's input
in a variable called q.
For each word among the 140,000, check
if it starts with the user's input--
a, b, z, whatever.

English: 
And if so, append it to there.
So let's temporarily get rid of
this and just render the template.
So notice this gets the job done,
but this is very C-like logic.
It's not wrong, it's perfectly correct.
But Python is a language
that's meant to be
a little more human readable
and a little more elegant,
if a little more non-obvious.
So this one line does
the exact same thing
using a feature called a
list comprehension, which
is ironic if you don't quite
comprehend how it's working.
But here's the variable I
want to create called Words.
These square brackets
here say give me a list.
What do you want to put in that list?
I want to put a word in this list.
Which word do you want
to put in this list?
The result of inducing this loop
and then only putting in this list
a word if it starts with
what the human typed in.
So it takes some getting
used to, but this is just
a one liner way, a very Pythonic way of
expressing those several lines of very
procedural code into a simple one line.
Is it better?
Not if you can't read it.

Arabic: 
وإذا كان الأمر كذلك، فقم بإلحاقها هناك.
لذا دعونا نتخلص مؤقتًا من
هذا ونقديم القالب فقط.
لذا لاحظوا أن هذا ينهي المهمة،
لكن هذا منطق يشبه لغة C للغاية.
هذا ليس خاطئًا، إنه صحيح تمامًا.
لكن Python هي لغة
من المفترض أن تكون
أكثر قابلية لإن يقرءها الشخص
وأنيقة أكثر قليلاً،
إذا كانت غير واضحة تمامًا.
لذا فإن هذا السطر
يقوم بنفس الشيء بالضبط
باستخدام ميزة تُسمى
فهم القائمة، وهي
مثيرة للسخرية إذا لم
تفهم تمامًا كيفية عملها.
ولكن ها هو المتغير الذي
أريد إنشاؤه باسم كلمات.
تقول هذه الأقواس المربعة
هنا أعطني قائمة.
ما الذي تريد وضعه في تلك القائمة؟
أريد أن أضع كلمة في هذه القائمة.
أي كلمة تريد
وضعها في هذه القائمة؟
نتيجة استنتاج هذا التكرار الحلقي
ومن ثم وضع كلمة فقط في هذه القائمة
إذا كانت تبدأ بما
كتبه الشخص.
لذلك يتطلب الأمر التعود،
ولكن هذه طريقة طبقة واحدة فقط،
وهي طريقة باثونية تمامًا
للتعبير عن تلك السطور العديدة
من التعليمة البرمجية الإجرائية في سطر واحد بسيط.
هل هذا أفضل؟
ليس إذا لم تتمكّنوا من قراءتها.

Arabic: 
لكن بمجرد أن تصبحوا معتادين أكثر
على استخدام Python،
نعم، هذا أفضل لأنه توجد تعليمة برمجية أقل.
أجل؟
الجمهور: لقد قلتَ أن Python تستخدم
التدوين لمعرفة مكان الشروط.
كيف هو [INAUDIBLE]؟
ديفيد مالان، سؤال جيد.
في هذه الحالة من فهم
القائمة، يمكنك فقط
الحصول على سطر واحد أو شرط واحد.
لا يمكنك الحصول على عدة سطور فيها،
لذلك لا يمكنني البدء بالضغط على Enter
ووضع مسافة بادئة هنا.
إنه غير مسموح به فقط.
لذا، ستستخدم هذا فقط-- وأنا
بصراحة أتجاوز الحدود حقًا.
يجب عليك فقط استخدام هذه
الصيغة عندما تناسب شاشتك
أو تناسب شاشة شخص منطقي.
بعد ذلك ربما يجب عليك القيام
بشيء معبر أكثر قليلاً.
أي أسئلة أخرى؟
لكن هذا أمر شائع جدًا لنراه عبر الإنترنت.
لذلك أي برامج تعليمية،
إذا رأيتَ هذا النوع من الطبقة الواحدة،
فحاول أن تفكر فيها من هذا
النهج ما الذي تقوم به في الواقع.
حسنًا، لذا اقترح من منظور
تجربة المستخدم
كيف يمكن أن يكون هذا البرنامج أفضل؟
لأن هذا هو فقط أول إصدار خاص بنا.
لذا ما الذي يمكن أن يكون
أفضل للمستخدم من هذا؟
ما الذي يمكن أن يكون أفضل؟

English: 
But once you get more
comfortable with Python,
yes, it's better because it's less code.
Yeah?
AUDIENCE: You said Python uses
notation to tell where conditions are.
How is [INAUDIBLE]?
DAVID MALAN: Good question.
In this case of a list
comprehension, you can only
have one line or one condition.
You can't have multiple lines therein,
so I cannot start hitting Enter
and indenting here.
It's just not allowed.
So you would only use this-- and I'm
frankly really pushing the limits.
You should only really use this
syntax when it fits on your screen
or fits on a reasonable person's screen.
After that you should probably do
something a little more expressive.
Other questions?
But this is very common to see online.
So any tutorials, if you ever
see this kind of one liner,
just try to think about it from that
approach what it is actually doing.
OK, so propose from a user
experience perspective
how could this program be better?
Because this is just our first version.
So what could be better
for the user than this?
What could be better?

Arabic: 
أجل؟
الجمهور: مجرد الرجوع،
هل يمكنك شرح الكلمات بالأحرف الكبيرة؟
ديفيد مالان: أوه، بالتأكيد.
الكلمات بالأحرف الكبيرة هي المتغير الشامل
الذي قمتُ بتعرفيه هنا والذي يُخزِّن كل 140000
كلمة الإضافية.
هذا ملف كبير حقًا
يُسمى كبير، الملف النصي.
بالأسفل هنا أنا أحتاج إلى متغير محلي.
وإذا كان أكثر وضوحًا، يمكن أن
أطلق عليها نتائج ومن ثم فقط
أقول النتائج تساوي النتائج.
هذه هي المجموعة الفرعية
من الكلمات التي تبدأ بالحرف a أو b،
أو أيًا كان ما يكتبه الشخص.
هذا كل شيء.
سؤال جيد.
أجل؟
الجمهور: لماذا نغير
آخر مرة-- لمَ
يجب أن تغيّر args إلى شكل؟
ديفيد مالان: لماذا قمتُ
بتغيير args الخاصة بي إلى--
الجمهور: أشكال؟
ديفيد مالان: في وقت سابق اليوم
عندما لم أكن أفهم ما يجري،
يجب أن تستخدام request.args
للحصول على طلبات.
يجب أن تستخدام request.form
لنشر طلبات.
الجمهور: لكنه ما يزال .get after؟
ديفيد مالان: إنه دائمًا .get، نعم.
لكنك تغير ما تحصل
عليه من أشياء.

English: 
Yeah?
AUDIENCE: Just going back,
can you explain words in caps?
DAVID MALAN: Oh, sure.
Words in caps is this global variable I
defined up here that stores all 140,000
plus words.
That's the really big file
called large, the text file.
Down here I just need a local variable.
And if it's more clear, I could
call it results and then just
say results equals results.
That is the subset of words
that start with a, or b,
or whatever the human typed in.
That's all.
Good question.
Yeah?
AUDIENCE: Why do we
change the last time-- why
did you have to change args to form?
DAVID MALAN: Why did I
have to change my args to--
AUDIENCE: Forms?
DAVID MALAN: So earlier today when I
didn't understand what was going on,
you should use request.args
for get requests.
You should use request.form
for post requests.
AUDIENCE: But it's still .get after?
DAVID MALAN: It's always .get, yes.
But you change what you're
getting things from.

English: 
In an ideal world, it would have been
something-- oh, I see what you mean.
Get in this sense is the verb.
We humans mean go get something.
Args in this sense,
if they had done get--
I'm making this up, but this
is probably why they did this.
Because get from get seems weird,
whereas get from post is less weird.
But it's just they called
it args and form instead.
OK, so let's actually
improve this, but how?
What could be better for the user?
Yeah?
AUDIENCE: They could search a
word, not just the first letter.
DAVID MALAN: OK, maybe
searching a whole word
would be good, not
just the first letter.
What else could we do?
AUDIENCE: We can create an
index list of letters and words?
DAVID MALAN: OK, we could
create an index list.
So maybe using a hash or some form
of inspiration from our problem
set with Speller and actually use
a more sophisticated data structure
to get these answers more quickly.
And let me propose, too, the goal here
is to actually implement autocomplete,
and this was not auto complete.
This was like old school search.
Type in a query, hit Enter,
get a page of results.

Arabic: 
في عالم مثالي، كان يمكن أن
يكون شيئًا-- أوه، أرى ما تقصده.
الحصول على هذا المعنى هو الفعل.
نحن كبشر نعني الحصول على شيء ما.
Args بهذا المعنى،
إذا استخدمت get--
أنا أقوم بهذا، لكن ربما
هذا هو سبب قيامها بذلك.
لأن get من get يبدو الأمر غريبًا،
في حين أن get من منشور أقل غرابة.
لكنهم فقط يطلقون عليها
args وشكل بدلاً من ذلك.
حسنًا، دعونا نعمل على
تحسين ذلك، لكن كيف؟
ما الذي يمكن أن يكون أفضل للمستخدم؟
أجل؟
الجمهور: يمكنه البحث عن
كلمة، وليس عن الحرف الأول فقط.
ديفيد مالان: حسنًا، ربما
سيكون البحث عن كلمة كاملة
أمرًا جيدًا، وليس فقط
الحرف الأول.
ما الذي يمكن أن نفعله أيضًا؟
الجمهور: يمكننا إنشاء قائمة
فهرس من الأحرف والكلمات؟
ديفيد مالان: حسنًا، يمكننا
إنشاء قائمة فهرس.
لذا ربما نستخدم علامة تجزئة أو
شكلًا من الإلهام من مجموعة مشاكلنا
باستخدام المدقق الإملائي ونستخدم
بالفعل بنية بيانات متطورة أكثر
للحصول على هذه الإجابات بسرعة أكبر.
ودعوني أقترح، أيضًا، الهدف
هنا هو تنفيذ الإكمال التلقائي في الواقع،
ولم يكن هذا إكمال تلقائي.
كان هذا مثل بحث المدرسة القديمة.
اكتب استعلامًا، واضغط على Enter،
واحصل على صفحة النتائج.

Arabic: 
ماذا لو أردنا القيام
بشيء فوري أكثر؟
إذن دعوني أقترح ذلك في الواقع.
قبل النظر في التعليمة البرمجية،
دعوني أنتقل إلى words1.
دعوني أمضي قدمًا
وأقوم بتشغيل Flask في هذا الدليل.
دعوني أمضي قدمًا
وأعيد تحميل الشكل هنا،
ولاحظوا الآن لا يوجد زر Submit
لأنه لن تكون هناك أي
عمليات تقديم فعلية هنا.
لكنني سأمضي قدمًا وأدخل
الحرف A، وأوه، هذا رائع.
دعوني أحذف ذلك، إنه يختفى.
B، ها هي كل الكلمات التي تبدأ بالحرف B.
دعوني أكتب كلمات تبدأ بالحرفين B-A،
كلمات تبدأ بالأحرف B-A-B، كلمات تبدأ بالأحرف B-A-B-A.
هذه هي الطريقة التي يعمل بها الإكمال التلقائي.
لذا يبدو أنه يستجيب بشكل فوري
لمدخلي، لذا يحدث شيء.
لكنني لا أقوم في الواقع
بتقديم الشكل.
لذا أنا استخدمه الآن،
يبدو أن JavaScript من جانب العميل
ربما تتحدث إلى الخادم؟
دعونا نستنتج.
لذا هنا، أيضًا، يجب أن
يعتمد هذا على حدسك.
عندما تحاول فهم كيفية
عمل موقع شخص على الويب،
أو إذا كنتَ تريد أن تتعلم منه أو
تحاكي دالة أساسية معينة،
امضي قدمًا وافحص الصفحة.
ومن المحتمل أن لا تهتم كثيرًا
بشأن HTML حتى الآن.
من أين تأتي هذه البيانات؟

English: 
What if we want to do
something more immediate?
So let me actually propose this.
Before looking at the code,
let me go into words 1.
Let me go ahead and run
Flask in that directory.
Let me go ahead and
reload the form here,
and now notice no Submit button
because there's not going
to be any actual submissions here.
But I'm going to go ahead and hit the
letter A, and ooh, that's kind of cool.
Let me delete that, goes away.
B, there's all the B words.
Let me go B-A words, B-A-B
words, B-A-B-A words.
This is how autocomplete works.
So it seems to be responding immediately
to my input, so something's happening.
But I'm not actually
submitting the form.
So I'm kind of using it now,
it seems client side JavaScript
to maybe talk to the server?
Let's infer.
So here, too, this
should be your instinct.
Whenever you're trying to understand
how someone's website works,
if you want to learn from it or mimic
certain fundamental functionality,
go ahead and inspect the page.
And you don't probably care
too much about the HTML yet.
Where is this data coming from?

English: 
Let me click on the Network tab, which
we looked at a couple of weeks ago.
Let me go ahead and restart this
and let me clear this and start
from the beginning of the story.
Let's see what happens when I
type the letter A. Interesting.
There is a web request.
So if I zoom in down here, notice
that my browser actually searched
for Q equals A, the human's input.
Let me go ahead and-- it
keeps searching because I'm
using keyboard shortcuts here.
But let me go ahead and click this row.
Notice what happened.
I made a request to slash search
question mark q equals a via get.
Let's see what the response was.
The response here, if
I view the source--
or rather, if I read the response--
notice what came back.
It looks like my server returned to me
a fragment of HTML containing hundreds,
maybe thousands of words starting
with A. But notice there's no UL tag,
there's no head tag, no title, no body,
it's just a partial HTML fragment.
But that's interesting, because I know
with Python I can do exactly that.
I can generate anything
I want on the server,

Arabic: 
دعوني أضغط على علامة تبويب الشبكة،
التي ألقينا نظرة عليها منذ أسبوعين.
دعوني أمضي قدمًا وأعيد تشغيل
هذا ودعوني أوضح هذا وأبدأ
من بداية القصة.
لنرى ماذا يحدث عندما
أكتب الحرف A. مثير للإعجاب.
هناك طلب ويب.
لذا إذا قمتُ بالتكبير هنا، فلاحظوا
أن المتصفح بحث في الواقع
عن Q يساوي A، مدخل الشخص.
دعوني أمضي قدمًا و-- إنه
يستمر في البحث لأنني
أستخدم اختصارات لوحة المفاتيح هنا.
لكن دعوني أمضي قدمًا وأضغط على هذا الصف.
لاحظوا ماذا حدث.
لقد قمتُ بطلب إلى خط مائل search
علامة استفهام q يساوي عبر get.
لنرى ماذا كانت الاستجابة.
الرد هنا، إذا
عرضتُ المصدر-- أو بالأحرى،
إذا قرأتُ الاستجابة--
لاحظوا ما الذي تمت إعادته.
يبدو أن خادمي أعاد من أجلي
جزء من HTML يحتوي على المئات،
ربما الآلاف من الكلمات التي تبدأ بالحرف A.
لكن لاحظوا أنه لا توجد علامة UL،
لا توجد علامة رأس، لا يوجد عنوان، لا يوجد بنية،
إنه مجرد جزء HTML جزئي.
لكن هذا مثير للاهتمام، لأنني أعرف
باستخدام Python يمكنني القيام بذلك بالضبط.
يمكنني إنشاء أي شيء
أريده على الخادم،

English: 
and then maybe the browser can just
plug in those changed the results.
So let me go ahead and look
at the code for this page.
If I go now to the browser's
source code, the view page source,
you'll see a few new lines.
So to do this easily, I'm
actually using another library.
This one is called jQuery.
This was for many years
super, super popular.
It's kind of starting
to fall out of vogue,
but it's still so
powerful and so useful.
And it's used by Bootstrap, the
other CSS library we've talked about,
so it's perfectly
reasonable to use it here.
Notice how I'm including
it with the script tag,
and it's hosted on a
third party website so
that I don't have to save a
copy of it myself on my own IDE.
Then let's look at the
code I actually wrote.
So notice that atop this file
is not even a full fledged form,
it is just the HTML input.
Because I don't need a full form.
I don't need an action,
I don't need a method,
because I'm not submitting it
anywhere with the human's cooperation.
I'm going to use my own code.
So in my script tag here, my
JavaScript code, notice what I'm doing.
This is some code from
like two weeks ago.

Arabic: 
ثم ربما يمكن أن يقوم المتصفح فقط
بتوصيل تلك التي غيرت النتائج.
لذا دعوني أمضي قدمًا وألقي نظرة
على تعليمة هذه الصفحة البرمجية.
إذا انتقلتُ الآن إلى تعليمة
مصدر برمجية خاصة بالمتصفح، مصدر صفحة العرض،
فسترون بعض السطور الجديدة.
لذا، للقيام بذلك بسهولة،
فأنا أستخدم بالفعل مكتبة أخرى.
هذه المكتبة تُسمى jQuery.
كانت هذت لسنوات عديدة،
مشهورة للغاية.
إنها نوع من البدء
في الخروج مما هو رائج،
لكنها ما تزال قوية
ومفيدة للغاية.
ويتم استخدامها من قِبل Bootstrap،
مكتبة CSS الأخرى التي تحدثنا عنها،
لذا من المنطقي
للغاية استخدامها هنا.
لاحظوا كيف أقوم بتضمينها
باستخدام علامة النص،
وتمت استضافتها على موقع
ويب تابع لجهة خارجية حتى
لا أضطر إلى حفظ نسخة منها
بنفسي على IDE الخاصة بي.
ثم دعونا ننظر في التعليمة
البرمجية التي كتبتُها بالفعل.
لذا لاحظوا أن الجزء العلوي من هذا الملف
لا يمثل شكلاً كاملاً،
إنه مدخل HTML فقط.
لأنني لا أحتاج إلى شكل كامل.
لا أحتاج إلى إجراء،
لا أحتاج إلى طريقة،
لأنني لا أقدمها في
أي مكان بالتعاون مع الأشخاص.
سأستخدم التعليمة البرمجية الخاصة بي.
لذا في علامة النص هنا، تعليمة JavaScript
البرمجية الخاصة بي، لاحظوا ما أقوم به.
هذه بعض التعليمة البرمجية
منذ أسبوعين تقريبًا.

Arabic: 
سأقوم بالبحث في الشجرة
التي تمثل صفحة الويب هذه.
وبالفعل، من المفترض أن تكون شجرة.
تذكرون من ذلك الوقت عندما
نظرنا في صفحة HTML،
هناك في الذاكرة، وذلك بفضل
المتصفح، شيء يشبه الشجرة--
DOM، نموذج كائن المستند--
الذي يمثل صفحتك.
باستخدام JavaScript، هل يمكننا تغيير
هذه الصفحة بعد حدوثها؟
إذن ماذا سأفعل؟
سأقوم بإخبار المتصفح متى سمع
هذا المدخل حدثًا يستدعي مفتاحًا إلى الأعلى--
لذا كلما كان التركيز على الحقل--
إنه باللون الأزرق في نظام التشغيل Mac--
ويضغط الشخص على
المفتاح ومن ثم لننتقل،
وتنتقل الكلمة الرئيسية إلى الأعلى، امضي قدمًا
واطلب الدالة المجهولة التالية.
ما الذي تريد القيام به؟
الآن، هذه التعليمة البرمجية
مشفرة قليلاً، لكن دعوني
أنتقل خلالها لأنها
ثلاثة سطور فقط.
تستخدم هذه التعليمة البرمجية
هنا ميزة خاصة--
علامة الدولار-- والتي تأتي من
هذه المكتبة التي تُسمى jQuery.
المزيد حول ذلك في غضون لحظات.
تحتوي تلك المكتبة، واسمها مربك
إلى حد ما، على دالة تُسمى get،
والتي ليس لها علاقة مع Python
أو تلك التي تحدثنا عنها للتو.
ولكن يجب القيام بهذا باستخدام HTTP get.

English: 
I'm going to search the tree
that represents this web page.
And indeed, it is meant to be a tree.
Recall from that time when
we looked at an HTML page,
there is in memory, thanks to
the browser, something treelike--
a DOM, document object model--
that represents your page.
Using JavaScript, can we change
that page after the fact?
So what am I going to do?
I'm going to tell the browser whenever
this input hears an event called on key
up-- so whenever the field has
focus-- it's blue in Mac OS--
and the human hits the
key and then let's go,
and the key goes up, go ahead and
call the following anonymous function.
What do you want that to do?
Now, this code is a
little cryptic, but let
me walk us through it because
it's only three lines.
This code here is using
a special feature--
dollar sign-- that comes from
this library called jQuery.
More on that in a moment.
That library, somewhat confusingly
named, has a function called get,
which has nothing to do with Python
or the one we just talked about.
But this has to do with an HTTP get.

English: 
With this line of code,
you can tell a browser,
even after a web page has been loaded,
go get me this other URL, please.
So what URL do you want to get?
Go ahead and get me from the same
server slash search q equals,
and then what does plus mean
in JavaScript if you recall?
Concatenation.
So it means just append
one string to the other.
So this is like saying,
go ahead and get me
the URL that ends with slash search,
question mark, Q equals A, or Q equals
B, or Q equals Z. Whatever
the human typed and just gets
slapped onto the end.
And then that's where
we're getting it from.
Input.value is the user's
input, the value thereof.
And then the last line-- and
this is perhaps the fanciest--
notice that I have an
anonymous function.
In this library called
jQuery, there is this function
called get that gets a URL.
When the server responds to your request
with a virtual envelope of its own,
this anonymous function gets
called and the response envelope

Arabic: 
باستخدام هذا السطر من التعليمة البرمجية،
يمكنك إخبار المتصفح،
حتى بعد تحميل صفحة ويب،
انتقل إلى عنوان URL هذا، من فضلك.
إذن ما هو عنوان URL الذي تريده؟
امضي قدمًا وأعطني من
الخادم نفسه خط مائل search q يساوي،
ومن ثم ما الذي يعنيه زائد في
JavaScript إذا كنتم تتذكرون؟
تسلسل.
لذا هذا يعني فقط
إلحاق سلسلة واحدة إلى السلسلة الأخرى.
لذا هذا مثل قول،
امضي قدمًا وأعطني
عنوان URL الذي ينتهي بخط مائل search،
علامة استفهام، Q يساوي A، أو Q يساوي B،
أو Q يساوي Z. أيًا
كان ما يكتبه الشخص
ويتلقى صفعة في النهاية.
ومن ثم هنا نحصل
عليها.
Input.value هو مدخل
المستخدم، القيمة نفسها.
ثم السطر الأخير-- وربما
هذا هو الأكثر روعة--
لاحظوا أن لدي
دالة مجهولة.
في هذه المكتبة التي
تُسمى jQuery، هناك هذه
الدالة التي تُسمى get التي تحصل على عنوان URL.
عندما يستجيب الخادم لطلبك
باستخدام ظرف افتراضي خاص به،
يتم استدعاء هذه الدالة المجهولة
ويتم تسليم ظرف الاستجابة

English: 
gets handed to you, so to speak, as
a data argument, as a data variable.
Then what you can you do?
Document.queryselector UL.
What is UL?
It's an unordered list that by default
on this page has nothing in it.
But recall that what the server is
sending back is a bunch of LI tags.
That's great, because I want to put
those LI tags right in between here.
So how do I do that?
I go into the so-called
inner HTML of the UL tag,
and you might not have seen this before.
But you can change the contents
of an existing tag inside of it
by using inner HTML and
just plop the data in there.
And so what's happening is this.
Let me go ahead and open
up Chrome's inspector.
Reload the page so it's empty.
Let me open up Chrome's inspector.
Go to elements, as is the
default. And notice on this page,
notice that UL tag is opened and
closed with nothing inside of it.
The moment, though, I search for
something, watch what happens.
If I search for a, all of a sudden--
ooh, it blinked, it's a little small.
Now there's a little triangle there.
What's inside of it?

Arabic: 
إليك، إذا جاز التعبير،
كوسيطة بيانات، كمتغير بيانات.
ثم ما الذي يمكنكم فعله؟
Document.queryselector UL.
ما هو UL؟
إنها قائمة غير مرتبة بشكل افتراضي
في هذه الصفحة لا يوجد بها أي شيء.
ولكن تذكرون أن ما يرسله الخادم
هو مجموعة من علامات LI.
هذا رائع، لأنني أريد وضع
علامات LI هذه بين هنا.
إذن كيف أفعل ذلك؟
أنتقل إلى ما تُسمى
HTML الداخلية من علامة UL،
وربما لم تشاهدوا هذا من قبل.
لكن يمكنك تغيير محتويات
العلامة الموجودة بداخلها
باستخدام HTML الداخلية
وفقط إسقاط البيانات هناك.
ولذا هذا هو ما يحدث.
دعوني أمضي قدمًا
وأفتح مركز تحكم Chrome.
أعد تحميل الصفحة
بحيث تكون فارغة.
دعوني أفتح مركز تحكم Chrome.
انتقل إلى العناصر، كما هو
الافتراضي. ولاحظوا في هذه الصفحة،
لاحظوا أن علامة UL مفتوحة
ومغلقة ولا يوجد بداخلها شيء.
لكن في اللحظة التي أبحث فيها
عن شيء ما، شاهدوا ماذا يحدث.
إذا قمتُ بالبحث عن، فجأة-- أوه،
إنه يومض، إنه صغير بعض الشيء.
الآن هناك مثلث صغير هناك.
ما الذي يوجد بداخله؟

English: 
All of those LI tags that
came from the server.
So with JavaScript, we
have this amazing power now
to change what's inside of a web page
by just asking the server for more data.
So if you've ever used
Facebook, or you've
used Google Chat, or any websites that's
dynamically changing every second,
every minute and each time you
get a message, you can literally,
if you get a little nosy, open up
Chrome's inspector and watch the DOM,
watch this elements tab.
And you'll see new stuff
popping up every time
you get a message, or a chat, or any
other such notification on the screen.
Now as an aside, this is a little
sloppy to be returning HTML,
but let's see how it's done.
Let me go into application.py for
words one, which is this example here.
And in application.py, notice
what I'm doing is this.
Rather than return a
whole page of results,
I'm returning a template
called search.html.
All of the rest of this
code is identical to before.
If I go into my templates and go into
search.html, look how terribly simple
the code is on the server.

Arabic: 
كل علامات LI تلك
التي جاءت من الخادم.
لذا باستخدام JavaScript،
لدينا هذه القوة المدهشة الآن
لتغيير ما هو موجود داخل صفحة الويب
فقط من خلال طلب المزيد من البيانات من الخادم.
لذا إذا استخدمتم Facebook،
أو استخدمتم
Google Chat، أو أي مواقع ويب
تتغير بشكل ديناميكي كل ثانية، وكل دقيقة
وفي كل مرة تتلقون فيها
رسالة، يمكنكم حرفيًا،
إذا أصبحتم فضوليين قليلاً،
فتح مركز تحكم Chrome ومشاهدة DOM،
ومشاهدة علامة تبويب العناصر هذه.
وسترون أشياء جديدة
تنبثق كل مرة تتلقون
فيها رسالة، أو دردشة، أو أي
إشعار آخر على الشاشة.
الآن كملاحظة جانبية،
هذا أمر سيئ قليلاً لإرجاع HTML،
ولكن دعونا نرى كيف يتم ذلك.
دعوني أنتقل إلى application.py للكلمات
الأولى، وهي هذا المثال هنا.
وفي application.py،
لاحظوا ما أقوم به هو هذا.
بدلاً من إرجاع
صفحة كاملة من النتائج،
سأقوم بإرجاع قالب
يُسمى search.html.
جميع ما تبقى من هذه التعليمة
البرمجية متطابق مع ما سبق.
إذا انتقلتُ إلى القوالب الخاصة بي
وانتقلتُ إلى search.html، وتعرّفتُ على كيفية
وجود التعليمة البرمجية على الخادم بشكل بسيط للغاية.

English: 
If all you want to do is spit
out a bunch of list items,
this is all you need.
There's no template.
Like there's no extends layout because
you're not returning a whole web page,
you're returning a tiny,
tiny, tiny fragment of HTML.
But this is arguably a little
sloppy, because there's
a lot of redundancy
in what's coming back.
If I look at this tag that's
coming back from the server,
what is obviously redundant about all
of this information that's coming back?
And if I look at the Network tab,
you really see it under response.
What's redundant?
AUDIENCE: You're doing a bunch of calls
to the same address and to the same--
DAVID MALAN: This was just because I
hit some, like, zoom in and zoom out,
so it pretended to
make multiple requests.
So red herring there.
Focus only on this part here.
What's redundant about all
of the data coming back?
It's just keeps saying list
item, word, close list item.
List item, word, clothes list item.
I mean come on, just use
a more efficient syntax.
Just separate things with commas
or something lighter weight.
This is sending way many bytes.
I mean, look.
There's thousands of bytes.
This is kilobytes by
definition of information

Arabic: 
إذا كان كل ما تريد القيام به هو
إظهار مجموعة من عناصر القائمة،
فهذا كل ما تحتاج إليه.
لا يوجد قالب.
على سبيل المثال لا توجد عمليات توسيع للتخطيط
لأنك لا تقوم بإرجاع صفحة ويب كاملة،
أنت تعيد جزءًا صغيرًا
جدًا من HTML.
ولكن يمكن القول أن هذا الأمر
سيء قليلاً، لأن هناك الكثير
من التكرار في
الشيء الذي يرجع.
إذا نظرتُ في هذه العلامة
التي تعود من الخادم،
فما هو الشيء المُكرّر بشكل واضح
بشأن جميع هذه المعلومات التي ترجع؟
وإذا نظرتم في علامة تبويب الشبكة،
سترون ذلك بالفعل أسفل الاستجابة.
ما هو التكرار؟
الجمهور: كنت تقوم بمجموعة من عمليات الاستدعاء
لنفس العنوان و--
ديفيد مالان: لقد كان هذا فقط لأنني
ضغطتُ على بعض، على سبيل المثال، التكبير والتصغير،
لذلك تظاهر بتقديم
طلبات متعددة.
لذا التظليل باللون الأحمر هنا.
ركزوا فقط على هذا الجزء هنا.
ما هو الشيء المُكرّر بشأن جميع
البيانات التي يتم إرجاعها؟
إنه فقط يقول عنصر القائمة،
كلمة، إغلاق عنصر القائمة.
عنصر القائمة، كلمة، إغلاق عنصر قائمة.
أعني هيا، فقط
استخدم صيغة فعّالة أكثر.
فقط افصل الأشياء بفواصل
أو شيء أخف وزنًا.
يقوم هذا بإرسال العديد من وحدات البايت.
أعني، انظروا.
توجد الآلاف من وحدات البايت.
هذه هي وحدات الكيلوبايت حسب
التعريف من المعلومات

English: 
that we're sending just
to send open bracket,
LI close bracket again and again.
This is not very efficient.
And so the world actually has
adopted a different approach,
and I'm going to show this in words 2
that actually returns something called
JavaScript Object Notation, which is
a more succinct representation of this
as follows.
Let me go into words
2, run Flask in there.
Search for the same kind
of thing and then watch
what happens over the
network panel this time.
When I search for A, immediately
get back the same visual result.
But if I look at this search
query, now look what comes back.
I claim that this is a much more compact
representation of the same information.
It's a little annoying
that there's double quotes,
because those are a little redundant.
But at least double quotes
are a lot more efficient
than open bracket, LI, closed bracket,
and then the opposite at the end.
So this is what's called
JavaScript Object Notation.
And as this square
bracket here and thousands
of words later the square
bracket on the end implies,
this is a JavaScript array that's
being sent back from the server.
So the only thing that's
changed here is as follows.

Arabic: 
التي نرسلها فقط
لإرسال قوس مفتوح،
LI قوس مغلق مرارًا وتكرارًا.
هذا ليس فعّال جدًا.
وهكذا تبنّى العالم
بالفعل نهجًا مختلفًا،
وسأشرح ذلك في words2
الذي يعيد بالفعل شيئًا يُسمى
تدوين كائن JavaScript،
وهو تمثيل موجز أكثر من هذا
على النحو التالي.
دعوني أنتقل إلى words2،
وأقوم بتشغيل Flask هناك.
ابحث عن نفس النوع
من الأشياء ومن ثم شاهدوا ما
يحدث على لوحة
الشبكة هذه المرة.
عندما أبحث عن A، استرجع
النتيجة المرئية نفسها على الفور.
ولكن إذا نظرتُ في استعلام
البحث هذا، فابحث الآن عما يعود.
أنا أزعم أن هذا هو تمثيل
محكم أكثر بكثير من المعلومات نفسها.
من المزعج بعض الشيء
أنه توجد علامتي اقتباس،
لأن هذا الشيء مكرر قليلاً.
ولكن علامتي الاقتباس
على الأقل فعّالتان أكثر بكثير
من قوس مفتوح، LI، قوس مغلق،
ومن ثم المقابل في النهاية.
لذا هذا ما يُسمى
بتدوين كائن JavaScript.
وبينما هذا القوس
المربع هنا وآلاف
الكلمات في وقت لاحق
يشير القوس المربع في النهاية إلى،
هذه هي مصفوفة JavaScript
التي يتم إرسالها من الخادم.
لذا فإن الشيء الوحيد الذي
تغير هنا هو كما يلي.

Arabic: 
في words2، هذا المثال،
لاحظوا أنني لا
أحتاج إلى إرجاع قالب بعد الآن.
هذه التعليمة البرمجية هي
نفسها كما وردت في المثالين السابقين.
هذه هي الطريقة التي أبحث
بها عن 140000 كلمة بسرعة.
ولكن إذا قمتُ الآن بتضمين دالة رائعة
من Flask تُسمى jsonify--
وهي ليست كلمة بالفعل.
لكن jsonify، التي
تأخذ أي بنية بيانات
لديكم بيانات في على سبيل المثال هذه
القائمة من الكلمات، التطابقات،
ويتضح أن هذا النص الذي يعتمد على
التمثيل باستخدام علامات اقتباس وفواصل.
ولا يجب أن
تكتب قالبًا بنفسك.
وبالفعل، لقد تخلصتُ من search.html.
الشيء الوحيد الذي يجب أن تفعله
لتمنح نفسك حق الوصول إلى هذه الميزة
هو استيراد ليس فقط
تقديم قالب، وطلب،
وFlask، ولكن jsonify أيضًا،
من مكتبة Flask.
وهي مجرد ميزة واحدة أخرى.
أي أسئلة حول ذلك قبل
أن نجمعها معًا في مثال واحد أخير؟
أجل؟
الجمهور: هل يمكن أن تقسّم علامتي الاقتباس
ذلك إلى [INAUDIBLE]؟؟
ديفيد مالان: هل يمكن أن تقسّم علامتي الاقتباس
ذلك؟

English: 
In words 2, this example,
notice that I don't even
need to return a template anymore.
This code is the same as
the past two examples.
This is how I'm searching
140,000 words quickly.
But if I include now a fancier
function from Flask called jsonify--
which is not really a word.
But jsonify, that takes
any data structure
you have data in like this
list of words, the matches,
and it turns it into that text based
representation with quotes and commas.
And you don't even have to
write a template yourself.
And indeed, I got rid of search.html.
The only thing you have to do to
give yourself access to this feature
is import not just render
template, and request,
and Flask, but jsonify, as
well, from the Flask library.
Which is just one more feature.
Any questions on that before we bring
it all together with one final example?
Yeah?
AUDIENCE: Can double quotes
break that into [INAUDIBLE]??
DAVID MALAN: Can double
quotes break that?

English: 
Good question, great instincts.
No because the author of
jsonify was smart about this.
And if that author notices a quote
like an apostrophe, or like something
in your own name that has a quote,
it will escape it in some way,
usually with a backslash.
Good instincts.
But that's why you probably wouldn't
want to write this code yourself
because then you have to think of
all of those corner cases as opposed
to focusing on the parts you care about.
All right, so there's one final example.
And it's perhaps to come full circle
here, do we even need the server?
These 140,000 words right now
are in a file called large.
My web application loads that file
into memory and then searches it.
But who else could search
over a big list of files?
Where else could we put this logic?
The browser, right?
Browser gives you JavaScript,
JavaScript's a language,
languages can search things.
So let me try this instead.

Arabic: 
سؤال جيد، بديهيات رائعة.
لا لأن مؤلف jsonify
كان ذكيًا بشأن هذا.
وإذا لاحظ المؤلف علامة اقتباس
مثل الفاصلة، أو مثل شيء
في اسمك يحتوي على علامة اقتباس،
فسيطلقه بطريقة ما،
عادة باستخدام خط مائل عكسي.
بديهيات جيدة.
ولكن هذا هو السبب في أنك على الأرجح
لا ترغب في كتابة هذه التعليمة البرمجية بنفسك
لأنه يجب أن تفكّر في
كل هذه الحالات الحرجة بدلاً من
التركيز على الأجزاء التي تهتم بها.
حسنًا، لذا يوجد مثال واحد أخير.
ومن المحتمل أنه سيكون دائرة كاملة
هنا، هل نحتاج إلى الخادم؟
هذه 140000 كلمة الآن
في ملف يُسمى كبير.
يحمّل تطبيق الويب الخاص بي هذا
الملف في الذاكرة ثم يبحث عنه.
ولكن مَن يمكنه أيضًا البحث
في قائمة كبيرة من الملفات؟
أين يمكننا أن نضع هذا المنطق؟
المتصفح، أليس كذلك؟
يمنحكم المتصفح JavaScript، 
JavaScript لغة،
واللغات يمكنها البحث عن أشياء.
إذن دعوني أقوم بهذا بدلاً من ذلك.

English: 
In our words 3 example here,
notice that I've got one new file.
In advance, you know, I took my big text
file that just had one word per line
and I put it into a standard
format just because it
makes my life a little easier.
And I called it large.json.
And in there, actually, where if I open
up this folder, you'll see large.js,
which is a second file,
this time a JavaScript file,
in which I've just declared a
JavaScript array of all 140,000 words
for better or for worse.
I just put them into a
slightly different format
with commas, and quotes,
and square brackets,
and I gave this whole thing a variable
name at the very top of the file.
Now, why is this useful?
Well, if I go into
index.html, notice that there
is no more application.py or
templates for this example whatsoever.
We've gotten rid of
Python entirely, I don't
know if it's for the better
or worse, but we'll now see.
So in this file, notice we
have an input tag as before,
a placeholder for all of
the ULs, but we're also
now including this large.js file.

Arabic: 
في مثال words3 لدينا هنا،
لاحظوا أن لديّ ملف واحد جديد.
مُقدمًا، كما تعلمون، أخذتُ ملف النص الكبير الخاص بي
الذي كان يحتوي على كلمة واحدة فقط لكل سطر
ووضعته في تنسيق
قياسي فقط لأنه
يجعل حياتي أسهل قليلاً.
وأطلقتُ عليه اسم large.json.
وهناك، في الواقع، حيث إذا قمتُ بفتح
هذا المجلد، سترون large.js،
وهو ملف ثاني،
هذه المرة ملف JavaScript،
حيث أعلنتُ فقط عن
مصفوفة JavaScript من جميع 140000 كلمة
للأفضل أو للأسوأ.
لقد وضعتُها فقط في
تنسيق مختلف قليلاً
بفواصل، وعلامات اقتباس
وأقواس مربعة،
وأعطيتُ هذا الشيء بأكمله اسم
متغير في أعلى الملف.
الآن، لماذا هذا مفيد؟
حسنًا، إذا انتقلتُ إلى
index.html، لاحظوا أنه
لم يعد هناك application.py أو
قوالب لهذا المثال على الإطلاق.
لقد تخلصنا من
Python تمامًا، لا
أعرف إذا كان ذلك للأفضل
أو للأسوأ، لكننا سنرى الآن.
إذن في هذا الملف، لاحظوا أن
لدينا علامة مدخل كما سبق،
عنصر نائب لجميع 
واجهات المستخدم، لكننا أيضًا
نقوم الآن بتضمين ملف large.js هذا.

English: 
Thereby telling the browser
please download all 140,000 words
and then search them locally.
How am I going to search it locally?
I've essentially converted the
language I wrote in Python a bit
ago into JavaScript as follows.
Here says the browser go get me the
input that the user can type into.
This tells the browser, go
ahead and listen for key up.
Whenever that happens,
please call this function
which has no name, because I want
you to just call it immediately,
I don't need its name.
This function is defined
by these several lines.
These several lines have to do
a bit more work than before.
Because before the server
was doing all the hard work
sending back all of the data, and
we just jammed it into the web page.
But here I'm going to build up
a list a little more manually.
So I'm going to let a
variable called html
equals quote unquote, because I want
to build up the unordered list myself.
Then if the human, indeed,
types something in--
so if their input is non null, so
if they type at least one character,
do the following.
This is weird in
JavaScript, but when you
iterate over an array in JavaScript,
you use the preposition of not in.

Arabic: 
وبالتالي نقول للمتصفح
من فضلك قم بتنزيل جميع 140000 كلمة
ومن ثم ابحث عنها محليًا.
كيف سأبحث عنها محليًا؟
لقد قمتُ بشكل أساسي بتحويل اللغة
التي كتبتُها في Python منذ
قليل إلى JavaScript على النحو التالي.
هنا يقول المتصفح احصل على
المدخل الذي يمكن أن يكتبه المستخدم.
هذا يخبر المتصفح، امضي
قدمًا واستمع إلى الكلمة الرئيسية بالأعلى.
متى يحدث ذلك،
من فضلك استدعي هذه الدالة
التي ليس لها اسم، لأنني أريدك
 فقط أن تستدعيها على الفور،
لا أحتاج إلى اسمها.
يتم تعريف هذه الدالة
عبر هذه السطور المتعددة.
يجب أن تقوم هذه السطور المتعددة 
بعمل أكثر قليلاً من ذي قبل.
لأنه قبل أن يقوم الخادم
بكل العمل الجاد
لإرسال جميع البيانات،
وقمنا فقط بتكديسها في صفحة الويب.
ولكن هنا سأقوم بإنشاء 
قائمة بشكل يدوي أكثر قليلاً.
إذن سأكتب
متغير يُسمى html
يساوي علامة اقتباس وعلامة إنهاء الاقتباس، لأنني أريد
إنشاء القائمة غير المرتبة بنفسي.
ثم إذا قام الشخص، في الواقع،
بكتابة شيء--
حتى إذا كان مدخله غير فارغ، إذن
إذا قام بكتابة حرف واحد على الأقل،
قُم بما يلي.
هذا غريب في
JavaScript، ولكن عندما تقومون
بتكرار مصفوفة في JavaScript،
تستخدمون حرف الجر of وليس in.

Arabic: 
إذن for word من words، امضي
قدمًا وقُم بما يلي.
إذا بدأت الكلمة الحالية بـ--
لاحظوا حرف W كبير-- أيضًا
مختلف عن Python، لكن الفكرة 
نفسها، فقط تهجئة مختلفة--
إذا كانت الكلمة التي أقوم بتكرارها تبدأ
بأي مما أدخله الشخص،
وجدنا تطابُق.
امضي قدمًا وقم بإلحاق
متغير HTML هذا،
قوس مفتوح LI قوس مغلق،
ادمج الكلمة فيه،
ومن ثم قوس مُغلق، أيضًا.
إذن سأقوم بإنشاء متغير
في ذاكرة المتصفح
تحتوي على HTML التي أريد
تكديسها في DOM في نهاية المطاف.
كيف يمكنني فعل ذلك.
حسنًا، في السطر الأخير أنا أقول
للمستند، حدّد علامة UL،
انتقل داخل HTML الخاص به،
وقم بتغيير أي شيء
يوجد في هذه السلسلة من HTML،
والتي من المفترض أنها صفر أو علامات LI أكثر
الآن تعتمد على نتائج البحث تلك.
إذن الآن دعوني أعود إلى words1--
بدلاً من ذلك، دعوني أعود
إلى هذا المثال هنا.
دعوني أمضي قدمًا وأُقدم هذا.
لم يعد Flask بعد الآن، إذن يجب أن أستخدم
الخادم الخاص بنا منذ أسبوعين،

English: 
So for word of words, go
ahead and do the following.
If the current word starts with--
notice the capitalized w-- also
different from Python, but same
idea, just different spelling--
if the word I'm iterating over starts
with whatever the human inputted,
we found a match.
Go ahead and append
to this HTML variable,
open bracket LI closed bracket,
concatenate the word to it,
and then close bracket, as well.
So I'm constructing a variable
in the browser's memory
containing HTML that I want to
jam into the DOM ultimately.
How do I do that.
Well, at the very last line I say
to the document, select the UL tag,
go inside of its HTML,
and change whatever
is there to this string of HTML,
which is presumably 0 or more LI tags
now based on those search results.
So now let me go back to words 1--
rather, let me go back
to this example here.
Let me go ahead and serve this up.
It's not Flask anymore, so I have to
use our server from two weeks ago,

Arabic: 
خادم HTTP، لتقديم HTML.
دعوني أمضي قدمًا وأُعيد تحميل الشاشة
هنا، وأفتح index.html، والآن
لاحظوا أننا مستعدون.
ما الذي تريدون البحث عنه؟
A، وB، وC. ثم دعونا نفتح
علامة تبويب الشبكة.
فحص، الشبكة.
دعونا نرى ما يحدث
في كل مرة أبحث فيها.
Z، وY، وQ، وA. لماذا لا يوجد
نقل بيانات الشبكة الآن؟
الجمهور: لا يوجد نقل بيانات الشبكة.
ديفيد مالان: حسنًا، لكن هذا ما قلتُه.
لكن لماذا لا يوجد نقل بيانات الشبكة؟
إنها لا تُرسل أي طرق، إنها لا 
تتحدّث إلى خادم طرف خلفي.
لماذا؟
لأن جميع البيانات التي قد 
أحتاج إليها محلية بالفعل.
إذن رسائل مختلطة هنا، أيضًا.
أيهما أفضل، أيهما صحيح؟
ما هو الفارق؟
كيف تفكرون في هذا؟
لأنه الآن، حيث كانت الكثير من برامجنا
في وقت سابق من الفصل الدراسي
صغيرة بشكل نسبي على الرغم من
أنها لم تبدو هكذا في ذلك الوقت،
الآن لدينا المزيد 
من احتمالات التصميم.
والإجابات
غير واضحة بشكل متزايد،
وهذا هو السبب في أنكم 
كمبرمجين فقط
ستعتادون أكثر على
التقاليد، ربما

English: 
HTTP server, to serve up HTML.
Let me go ahead and reload the screen
here, open up index.html, and now
notice we're good to go.
What do you want to search for?
A, B, C. And let's open
up the Network tab.
Inspect, Network.
Let's see what happens
every time I search.
Z, Y, Q, A. Why is there
no network traffic now?
AUDIENCE: There's no network traffic.
DAVID MALAN: OK, but that's what I said.
But why is there no network traffic?
It's not sending any routes, it's
not talking to a backend server.
Why?
Because all the data I
might need is already local.
So mixed messages here, too.
Which is better, which is right?
What's the takeaway?
How do you think about this?
Because now, whereas a lot of our
programs early on in the semester
were relatively small even though
they didn't feel that way at the time,
now we have even more
design possibilities.
And the answers are
increasingly non-obvious,
and this is why you as
programmers will just
get more comfortable with
conventions, you'll maybe

English: 
practice what you've
seen preached first,
then you'll decide as you
might be already saying,
I don't like that, I'm going
to do this some other way.
So how do you think about which of
these several words examples is best?
Version 0 was let the
server do all the work
and just send back a full new page
of results like Google in 1999 did.
Then version 1, we added
a bit of JavaScript
that used jQuery the library
to talk to the server using
a technique called Ajax--
asynchronous JavaScript and XML--
but that just means go get me more
data and we returned LI elements.
Then we decided that's
a little sloppy, don't
seem to send me all
these useless tags, just
send a comma separated list of words.
That was version 2.
And then this last version
gets rid of all of that
and just sends all the
words to the browser
and lets it deal with it entirely.
Who likes which best, 0, 1, 2, or 3?
What do you think?
AUDIENCE: So if you aren't
supposed to trust the user in case
they turn off the JavaScript, then
their decision of the functionality
of the website works.
DAVID MALAN: That's a good trade-off.

Arabic: 
ستمارسون ما 
علمتكم إياه أولاً،
عندها ستقررون 
وقد تقولون بالفعل،
أنا لا أرغب في ذلك، سأقوم
بهذا بطريقة أخرى.
إذن كيف تفكّرون بشأن أي من أمثلة الكلمات
المتعددة هذه هو الأفضل؟
أتاح الإصدار 0 للخادم
القيام بالعمل كله
وإرسال صفحة جديدة كاملة
من النتائج فقط كما فعل Google في عام 1999.
ثم الإصدار 1، قمنا بإضافة
القليل من JavaScript
التي استخدمت مكتبة jQuery 
للتحدّث إلى الخادم باستخدام
تقنية تُسمى Ajax--
XML وJavaScript غير متزامنة--
ولكن هذا فقط يعني أعطني المزيد من
البيانات ولكننا قمنا بإرجاع عناصر LI.
ثم قررنا أن هذا
سيئ قليلاً، لا
يبدو أن إرسال جميع
هذه العلامات غير المفيدة إلي، فقط
ارسل قائمة من الكلمات مفصولة بفاصلة.
كان هذا الإصدار 2.
ومن ثم يتخلص هذا الإصدار
الأخير من كل ذلك
ويُرسل فقط جميع الكلمات
إلى المتصفح
ويتيح له معالجتها بالكامل.
مَن يعجبه ما هو أفضل، 0، أو 1، أو 2، أو 3؟
ما هو رأيكم؟
الجمهور: لذا إذا لا يُفترض
أن تثقوا بالمستخدم في حالة
إيقافه تشغيل JavaScript، إذن
ينجح قراره بشأن
موقع الويب.
ديفيد مالان: هذه مقايضة جيدة.

English: 
So if the user turns off JavaScript, 3--
OK, it won't offend anyone--
3 2, and 1 won't work anymore
because JavaScript's disabled.
Now, do you care about that?
Maybe not.
It's a small number of
users on the internet who
are so concerned with this they
just turn off JavaScript altogether,
and the reality is so many websites just
break these days without JavaScript.
That might be a reasonable
cost of doing business.
Other thoughts?
Yeah?
AUDIENCE: Is the last
version the fastest?
DAVID MALAN: Is the last
version the fastest?
I don't know, how could we assess that?
Yeah, I mean, we can
literally measure it.
And honestly, built into Chrome in
other tabs that I've not even clicked on
are a lot of performance
tools where you can actually
monitor how long everything's taking.
This is called benchmarking
more generally,
and this is what you did
essentially in the speller problems
that even though we wrote the
code that timed everything
and measured everything,
to answer that question,
you could just try timing
every one of the examples
and then decide for yourself
which is best, sure.
Yeah?
AUDIENCE: The last thing I
have with problematic issue
is like my phone's old, and it
doesn't have a lot of memory,

Arabic: 
لذا إذا أوقف المستخدم تشغيل JavaScript،
3-- حسنًا، لن يسيء لأي أحد--
لن يعمل 3، و2، و1 بعد الآن
لأنه تم تعطيل JavaScript.
في الوقت الحالي، هل يهمكم ذلك؟
ربما لا.
يوجد عدد صغير من
المستخدمين على الإنترنت
يثيرهم القلق للغاية بشأن هذا فيقومون فقط
بإيقاف تشغيل JavaScript كليًا،
والواقع أن معظم مواقع الويب تقوم بالتقسيم
دون استخدام JavaScript هذه الأيام.
قد تكون هذه تكلفة معقولة
للقيام بهذا.
أي أفكار أخرى؟
أجل؟
الجمهور: هل
الإصدار الأخير هو الأسرع؟
ديفيد مالان: هل
الإصدار الأخير هو الأسرع؟
لا أعرف، كيف يمكننا تقييم ذلك؟
نعم، أعني، يمكننا
حرفيًا تدبر الأمر.
وبصراحة،ما تم دمجه في Chrome في
علامات تبويب أخرى لم أنقر عليها حتى
عبارة عن أدوات خاصة بالأداء
حيث يمكنكم في الواقع
مراقبة مقدار الوقت الذي يستغرقه كل شيء.
وهذا ما يُسمى بقياس الأداء
بشكل عام أكثر،
وهذا ما قمتم بفعله
بشكل أساسي في مشاكل المدقق الإملائي
على الرغم من أننا كتبنا التعليمة البرمجية
التي قامت بإعداد توقيت كل شيء
وقياس كل شيء،
للإجابة على ذلك السؤال،
يمكنكم فقط محاولة إعداد توقيت
كل مثال من هذه الأمثلة
ومن ثم تقررون لأنفسكم
ما هو أفضل، بالتأكيد.
أجل؟
الجمهور: الشيء الأخير الذي كان لديّ
بمشكلة جدلية
هي أن هاتفي قديم، ولا
يحتوي على مساحة كبيرة من الذاكرة،

Arabic: 
وقد لا تكون لديّ
أسرع خطة على الأرض.
إذن قد تُكلفني المزيد من البيانات،
وقد تجعل هاتفي بطيئًا.
ديفيد مالان: سبب منطقي جدًا.
دعوني أنتقل إلى ملف القاموس لدينا
هنا وأُدرج حجم هذا.
هذا الملف large.js مساحته 2.2
ميغابايت، على أجهزة الهاتف المحمولة،
خاصة في الأماكن التي تكون فيها الإشارة
بطيئة، أو فيها وحدات البايت باهظة الثمن،
أو أن لديكم فقط
وصول مُتقطِع، أعني،
أن تُرسل وحدتي ميغابايت إلى المستخدم
أمر بغيض بعض الشيء
إذا تمكنتم من تجنب ذلك، خاصة عندما
يمكنكم إرسال مجموعة فرعية فقط من النتائج،
ربما بعض وحدات الكيلوبايت،
من النتائج المتطابقة بدلاً من ذلك.
إذن هذا سبب منطقي جدًا.
التكلفة، تجربة المستخدم، الأداء.
أي أفكار أخرى؟
ما هو أفضل للأشخاص في الجامعة
وحرم الجامعي الذين يميلون عادة
أن يكون لديهم وصول جيد إلى الإنترنت؟
قل ذلك مجددًا؟
3، حسنًا.
ولكن ماذا لو أنها ليست
140000 كلمة، ولكنها
مثل مليار صورة من
القطط التي يقوم Google بفهرستها؟
أو المئات أو الآلاف من الأصدقاء
وجميع بيانات ملفاتهم الشخصية؟

English: 
and I may not have the
fastest plan on Earth.
So you might be charging me more data,
you might be slowing my phone down.
DAVID MALAN: Very reasonable concern.
Let me go into our dictionary file
here and list the size of this.
That large.js file is 2.2
megabytes, which on mobile devices,
especially in places where your signal
is slow, or your bytes are expensive,
or you only have
intermittent access, I mean,
that's kind of obnoxious to
send two megabytes to the user
if you can avoid it, especially when
you can send only the subset of results,
a few kilobytes maybe,
of matches instead.
So a very reasonable concern.
Cost, user experience, performance.
Other thoughts?
Which is better for people on university
and corporate campuses who tend
to have really good internet access?
Say again?
3, OK.
But what if it's not
140,000 words, but it's
like a billion pictures of
cats that Google indexes?
Or hundreds or thousands of friends
and all of their profile data?

English: 
Like at some point there's
this inflection point
where too much data, right?
It's not reasonable, it's too much.
You don't want to just get a
copy of your corporate database
to every one of your users just
for them to search more locally.
So again, these are the
non-obvious questions.
And one of the goals of,
frankly, the final project
if you do something web based, or
mobile based, or C based, or anything,
is all of these questions
now boil down to you.
Like we have no
well-defined answers in mind
as to what your final project should
do and how it should do it best.
But in the weeks ahead, you'll be
pre-proposing some project ideas,
proposing an actual project idea, and
then designing and implementing this.
And you, too, will
probably feel this tension
where the answer is not always obvious,
your teaching fellow might not even
know how to answer your
question, because he or she will
have thoughts of their own.
But it's ultimately up to you.
And we're now at the point
of a level of coding maturity
where we're taking the training
wheels off and more of the decisions
are now left to you.
Let's end here.
Stick around for one on
one questions, and we'll
see you next week for databases.

Arabic: 
على سبيل المثال في مرحلة ما توجد
نقطة الانعطاف هذه
حيث توجد بيانات كثيرة جدًا، أليس كذلك؟
إنه غير منطقي، إنه كثير جدًا.
لا تريدون فقط الحصول على نسخة
من قاعدة بيانات شركتكم
لكل المستخدمين لديكم فقط إليهم
ليبحثوا محليًا بشكل أكبر.
إذن مجددًا، هذه هي
الأسئلة غير الواضحة.
وأحد أهداف
المشروع النهائي، بصراحة،
إذا كنتم تقومون بشيء قائم على الويب، أو
على الهاتف المحمول، أو على C، أو أي شيء،
هو أن تلخيص كل هذه الأسئلة
الآن من أجلكم.
على سبيل المثال ليست لدينا
إجابات مُحددَة جيدًا نتذكرها
بشأن ما يجب أن يقوم به مشروعكم النهائي
وكيف يقوم به على أفضل وجه.
لكن في الأسابيع القادمة، ستقومون 
باقتراح مُسبق لبعض أفكار المشروعات،
اقتراح فكرة مشروع فعلي
ثم تصميم هذا وتنفيذه.
ومن المحتمل أنكم أيضًا،
ستشعرون بهذه الصعوبة
حيث الإجابة ليست واضحة دائمًا،
قد لا يعرف زميلكم في التدريس حتى
كيفية الإجابة عن سؤالكم، 
لأن لديه أو لديها
أفكار خاصة.
لكن الأمر متروك لكم في نهاية المطاف.
ونحن الآن في مرحلة
مستوى نضج الترميز
حيث نأخذ عجلات 
التدريب والمزيد من القرارات
التي ستُترك لكم الآن.
دعونا نتوقف هنا.
سأبقى هنا لبعض الوقت من
أجل الأسئلة الفردية،
وسأراكم الأسبوع القادم من أجل قواعد البيانات.
