**کار ها:**
* نوشتن مدل نویسنده - ۱۳ نمره
* نوشتن مدل پُستِ بلاگ - ۱۳ نمره
* نوشتن مدل نظر - ۱۳ نمره
* نوشتن تابع کپی پُست - ۲۰ نمره
در این سوال میخواهیم مدل های اصلی یک بلاگ را پیاده سازی کنیم. برای این کار شما باید یک پروژه بسازید و یک App به نام `blog` در آن ایجاد کنید. برای راحتی شما ما این پروژه خام را ساخته ایم و شما میتوانید آن را به عنوان قالب از [اینجا](http://bayanbox.ir/download/4488874724606199194/blog.zip) دانلود کنید و کد خود را در آن بنویسید.
در این سوال شما فقط با فایل `models.py` که در پوشه blog قرار دارد، کار خواهید کرد.
شما باید ۳ مدل(model) به این فایل اضافه کنید:
۱. مدل نویسنده: `Author`
+ این مدل فقط دارای یک فیلدبه نام `name` است که از جنس رشته با حداکثر طول ۵۰ کارکتر است.
۲. مدل پستِ بلاگ: `BlogPost`
+ این مدل دارای فیلد های زیر است:
+ عنوان `title`: از جنس رشته با حداکثر طول ۲۵۰ کارکتر است.
+ متن `body`: از جنس رشته با طول نا محدود است.
+ نویسنده `author`: که یک کلید خارجی به یک نویسنده است که نویسنده پست را مشخص میکند.
+ تاریخ ایجاد پست `date_created`: از نوع DateTimeField است که زمان دقیق ساخته شدن پست را نشان میدهد و توسط کاربر وارد **نمیشود**.
۳. مدل نظر: `Comment`
+ این مدل دارای دو فیلد زیر است:
+ پست `blog_post`: این فیلد یک کلید خارجی به پستی است که این کامنت متعلق به آن است.
+ متن `text`: متن کامنت است که از نوع رشته با حدکثر طول ۵۰۰ کارکتر میباشد.
**توجه:** این مدل ها باید به گونه ای نوشته شوند که اگر پست ای پاک شد همهی کامنت های مربوط به آن پست نیز پاک شود. همچنین اگر نویسنده ای پاک شد، همه پست های آن نویسنده به همراه کامنت هایش پاک شود.
**تابع کپی:**
بعد از ساختن مدل های بالا یک تابع به نام `()copy` به مدل BlogPost اضافه کنید. این تابع آرگومان ورودی ندارد و یک کپی از مدل موردنظر میگیرد. به این صورت که کل پست به همراه همه کامنت هایش را کاملا کپی میکند. تاریخ پست کپی شده جدید، به تاریخ فعلی تغییر میکند. **این تابع در نهایت id بلاگ پست جدید را باز میگرداند.**
*برای مثال اگر تنها یک نویسنده به نام محمد و یک پست با تاریخ ۱۸ مهر به همراه ۳ کامنت در پایگاه داده وجود داشته باشد، بعد از کپی شدن پست در تاریخ ۲۰ مهر، هنوز یک نویسنده در پایگاه داده هست ولی تعداد پست ها ۲ و تعداد کامنت ها ۶ خواهد بود (هر پست ۳ کامنت مجزا) که تاریخ پست جدید ۲۰ مهر است.*
**فایل آپلودی**
یک فایل zip. که درون آن یک پوشه `blog` وجود دارد و در این پوشه فقط یک فایل `models.py` قرار دارد. توجه کنید در صورتی که فایلهای اضافی ارسال کنید، حذف خواهند شد.
```
<Your-zip-name>.zip
└── blog
└── models.py
```
میخواهیم یک سایت برای خودکار کردن فرایند فروش بلیتهای سینما بنویسیم.
در این سایت امکان مشاهده فیلمهای در حال اکران وجود دارد.
کاربران میتوانند عضو سایت شوند و پس از ورود به سایت
برای هر فیلم صندلی موردنظر را رزرو کند.
بخشی از این پروژه نوشته شده است. از شما میخواهیم این پروژه را تکمیل کنید.
# پروژه اولیه
پروژه اولیه را از [اینجا](http://bayanbox.ir/download/5545408568741586764/cinema.zip) دانلود کنید. ساختار این پروژه به شرح زیر است:
```
cinema
├── app
│ ├── migrations
│ │ ├── __init__.py
│ │ └── 0001_initial.py
│ ├── templates
│ │ └── app
│ │ ├── movies.html
│ │ └── seats.html
│ ├── __init__.py
│ ├── admin.py
│ ├── apps.py
│ ├── models.py
│ ├── urls.py
│ └── views.py
├── Cinema
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
├── templates
│ └── registration
│ ├── login.html
│ └── signup.html
├── manage.py
└── requirements.txt
```
# جزئیات
در این سؤال تنها لازم است تغییراتی در `app/views.py` و `app/fixtures` ایجاد کنید.
در فایل `models.py` سه مدل به شرح زیر وجود دارد:
۱. مدل `Movie` شامل فیلدهای زیر:
* `title`: نام فیلم
* `release_year`: سال انتشار فیلم
* `play_time`: زمان اکران فیلم در سالن
۲. مدل `Seat` شامل فیلد زیر:
* `number`: شماره صندلی
۳. مدل `Ticket`شامل فیلدهای زیر:
* `movie`: فیلمی که این بلیت برای آن فروخته شده است
* `user`: کاربری که این بلیت را خریده است
* `seat`: صندلی مربوط به این بلیت
* `date_bought`: تاریخی که بلیت خریده شده است
قرار است همه صندلیهای سالن و لیست فیلمها در ابتدا با استفاده از fixture
به پایگاه داده اضافه شود. سپس به ازای هر بلیتی که فروخته میشود
یک شیٔ از مدل `Ticket` ساخته میشود.
مواردی که باید انجام دهید:
### ۱. نوشتن fixture
از شما میخواهیم دو فایل *fixture* با نامهای
`movies` و `seats`
در مسیر `app/fixtures`
بنویسید. این *fixture* ها را میتوانید به فرمت
`JSON` یا `YAML`
بنویسید.
+ فایل `movies` باید شامل دادههای زیر باشد.
زمان اکران را به صورت naive (بدون TimeZone) تعریف کنید.
| id | نام فیلم | سال انتشار | تاریخ اکران | ساعت اکران |
|:---:|:----------:|:-------------:|:-------------:|:-------------------:|
| 1 | Children of heaven | 1997 | 2018/4/20 | 22:00 |
| 2 | About Elly | 2009 | 2018/4/20 | 20:00 |
| 3 | A separation | 2011 | 2018/4/22 | 18:00 |
| 4 | The salesman | 2016 | 2018/4/21 | 18:00 |
| 5 | The Elephant king | 2017 | 2018/4/21 | 20:00 |
+ فایل `seats` نیز باید شامل ۱۰ صندلی با `id` های ۱ تا ۱۰
و با شماره صندلیهای ۳۱ تا ۴۰ (به ترتیب `id` ها) باشد.
### ۲. نمایش صندلیها
در این قسمت باید view نمایش صندلیها (`list_seats`) را به گونهای تغییر دهید
که فقط صندلیهایی که برای فیلم موردنظر رزرو نشدهاند نمایش داده شوند.
### ۳. رزرو صندلی
با توجه به توضیحات زیر، view ها را تکمیل کنید.
برای رزرو صندلی، کاربر مراحل زیر را انجام میدهد:
+ ابتدا از آدرس `/movie` بازدید میکند که لیست فیلمهایی که در حال اکران هستند
را نمایش میدهد. سپس روی فیلم مورد نظر خود کلیک کرده و صفحهی بعدی صندلیهای رزرو
نشده برای آن فیلم را نمایش میدهد. تا این مرحله کاربر نیازی به login بودن ندارد.
+ وقتی کاربر روی یکی از صندلیها کلیک کرد:
+ اگر کاربر login است، صندلی برای کاربر
رزرو شده و دوباره به صفحهی صندلیهای همان فیلم *redirect* میشود تا
بتواند صندلیهای دیگری را نیز رزرو کند.
+ اگر کاربر login نیست،
به صفحهی *login* هدایت میشود و پس از وارد شدن به سایت،
بلافاصله به صفحهی قبلی (صفحه لیست صندلیها) *redirect* میشود،
بدون این که صندلی رزرو شود.
+ در صفحهی *login* اگر کاربر روی لینک *signup* کلیک کرد و در سایت
عضو شد، باید بلافاصله پس از عضویت به طور خودکار در سایت login شود
و به صفحه لیست فیلمها *redirect* شود.
### ۴. گزارش گیری سایت
در این قسمت شما باید view مربوط به آدرس `stats` را به نحوی کامل کنید
که در پاسخ برای همه صندلیهای که حداقل
برای یک فیلم رزرو شدهاند (به ترتیب `id` صندلی)،
یک خروجی JSON به شکل زیر بازگردد:
```json
[{"seat__number": 31, "total": 3}, {"seat__number": 32, "total": 1}, ... ]
```
+ مقدار *total*، تعداد رزروهای صندلی مشخص شده است.
+ این *view* تنها باید برای مدیران (superuser ها) فعال باشد و برای سایر افراد
خطای ۴۰۳ (Forbidden) برگرداند.
# نکات
+ شما تنها مجاز به تغییر در `app/views.py` و `app/fixtures` هستید.
اگر تغییری در سایر فایلها ایجاد کنید، این تغییرات نادیده گرفته خواهد شد.
+ پس از اعمال تغییرات، کل پروژه را Zip کرده و ارسال کنید.
+ نام فایل Zip اهمیت ندارد.