├── .gitignore ├── Chapter01 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── mysite │ ├── blog │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── blog.css │ │ ├── templates │ │ │ └── blog │ │ │ │ ├── base.html │ │ │ │ └── post │ │ │ │ ├── detail.html │ │ │ │ └── list.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ └── mysite │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py └── requirements.txt ├── Chapter02 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── mysite │ ├── blog │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_alter_post_slug.py │ │ │ ├── 0003_comment_comment_blog_commen_created_0e6ed4_idx.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── blog.css │ │ ├── templates │ │ │ ├── blog │ │ │ │ ├── base.html │ │ │ │ └── post │ │ │ │ │ ├── comment.html │ │ │ │ │ ├── detail.html │ │ │ │ │ ├── includes │ │ │ │ │ └── comment_form.html │ │ │ │ │ ├── list.html │ │ │ │ │ └── share.html │ │ │ └── pagination.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ └── mysite │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py └── requirements.txt ├── Chapter03 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── mysite │ ├── blog │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── feeds.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_alter_post_slug.py │ │ │ ├── 0003_comment_comment_blog_commen_created_0e6ed4_idx.py │ │ │ ├── 0004_post_tags.py │ │ │ ├── 0005_trigram_ext.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── sitemaps.py │ │ ├── static │ │ │ └── css │ │ │ │ └── blog.css │ │ ├── templates │ │ │ ├── blog │ │ │ │ ├── base.html │ │ │ │ └── post │ │ │ │ │ ├── comment.html │ │ │ │ │ ├── detail.html │ │ │ │ │ ├── includes │ │ │ │ │ └── comment_form.html │ │ │ │ │ ├── latest_posts.html │ │ │ │ │ ├── list.html │ │ │ │ │ ├── search.html │ │ │ │ │ └── share.html │ │ │ └── pagination.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── blog_tags.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ └── mysite │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py ├── prompts │ └── task.md └── requirements.txt ├── Chapter04 ├── Dockerfile ├── bookmarks │ ├── account │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── account │ │ │ │ ├── dashboard.html │ │ │ │ ├── edit.html │ │ │ │ ├── login.html │ │ │ │ ├── register.html │ │ │ │ └── register_done.html │ │ │ ├── base.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ ├── login.html │ │ │ │ ├── password_change_done.html │ │ │ │ ├── password_change_form.html │ │ │ │ ├── password_reset_complete.html │ │ │ │ ├── password_reset_confirm.html │ │ │ │ ├── password_reset_done.html │ │ │ │ ├── password_reset_email.html │ │ │ │ └── password_reset_form.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── bookmarks │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── manage.py ├── do.sh ├── docker-compose.yml └── requirements.txt ├── Chapter05 ├── Dockerfile ├── bookmarks │ ├── account │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── authentication.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── account │ │ │ │ ├── dashboard.html │ │ │ │ ├── edit.html │ │ │ │ ├── login.html │ │ │ │ ├── register.html │ │ │ │ └── register_done.html │ │ │ ├── base.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ ├── login.html │ │ │ │ ├── password_change_done.html │ │ │ │ ├── password_change_form.html │ │ │ │ ├── password_reset_complete.html │ │ │ │ ├── password_reset_confirm.html │ │ │ │ ├── password_reset_done.html │ │ │ │ ├── password_reset_email.html │ │ │ │ └── password_reset_form.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── bookmarks │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── manage.py ├── do.sh ├── docker-compose.yml └── requirements.txt ├── Chapter06 ├── Dockerfile ├── bookmarks │ ├── account │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── authentication.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── account │ │ │ │ ├── dashboard.html │ │ │ │ ├── edit.html │ │ │ │ ├── login.html │ │ │ │ ├── register.html │ │ │ │ └── register_done.html │ │ │ ├── base.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ ├── login.html │ │ │ │ ├── password_change_done.html │ │ │ │ ├── password_change_form.html │ │ │ │ ├── password_reset_complete.html │ │ │ │ ├── password_reset_confirm.html │ │ │ │ ├── password_reset_done.html │ │ │ │ ├── password_reset_email.html │ │ │ │ └── password_reset_form.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── bookmarks │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── images │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ ├── css │ │ │ │ └── bookmarklet.css │ │ │ └── js │ │ │ │ └── bookmarklet.js │ │ ├── templates │ │ │ ├── bookmarklet_launcher.js │ │ │ └── images │ │ │ │ └── image │ │ │ │ ├── create.html │ │ │ │ ├── detail.html │ │ │ │ ├── list.html │ │ │ │ └── list_images.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── manage.py ├── do.sh ├── docker-compose.yml └── requirements.txt ├── Chapter07 ├── Dockerfile ├── bookmarks │ ├── account │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── authentication.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_contact.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── account │ │ │ │ ├── dashboard.html │ │ │ │ ├── edit.html │ │ │ │ ├── login.html │ │ │ │ ├── register.html │ │ │ │ ├── register_done.html │ │ │ │ └── user │ │ │ │ │ ├── detail.html │ │ │ │ │ └── list.html │ │ │ ├── base.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ ├── login.html │ │ │ │ ├── password_change_done.html │ │ │ │ ├── password_change_form.html │ │ │ │ ├── password_reset_complete.html │ │ │ │ ├── password_reset_confirm.html │ │ │ │ ├── password_reset_done.html │ │ │ │ ├── password_reset_email.html │ │ │ │ └── password_reset_form.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── actions │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── actions │ │ │ │ └── action │ │ │ │ └── detail.html │ │ ├── tests.py │ │ ├── utils.py │ │ └── views.py │ ├── bookmarks │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── images │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_image_total_likes_and_more.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── signals.py │ │ ├── static │ │ │ ├── css │ │ │ │ └── bookmarklet.css │ │ │ └── js │ │ │ │ └── bookmarklet.js │ │ ├── templates │ │ │ ├── bookmarklet_launcher.js │ │ │ └── images │ │ │ │ └── image │ │ │ │ ├── create.html │ │ │ │ ├── detail.html │ │ │ │ ├── list.html │ │ │ │ ├── list_images.html │ │ │ │ └── ranking.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── manage.py ├── do.sh ├── docker-compose.yml ├── prompts │ └── task.md └── requirements.txt ├── Chapter08 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── myshop │ ├── cart │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── cart.py │ │ ├── context_processors.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── cart │ │ │ │ └── detail.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ ├── myshop │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── celery.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── orders │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ └── orders │ │ │ │ └── order │ │ │ │ ├── create.html │ │ │ │ └── created.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── shop │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ ├── 0001_initial.py │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ ├── css │ │ │ ├── base.css │ │ │ └── pdf.css │ │ └── img │ │ │ └── no_image.png │ │ ├── templates │ │ └── shop │ │ │ ├── base.html │ │ │ └── product │ │ │ ├── detail.html │ │ │ └── list.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py └── requirements.txt ├── Chapter09 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── myshop │ ├── cart │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── cart.py │ │ ├── context_processors.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── cart │ │ │ │ └── detail.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ ├── myshop │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── celery.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── orders │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_order_stripe_id.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ ├── admin │ │ │ │ └── orders │ │ │ │ │ └── order │ │ │ │ │ └── detail.html │ │ │ └── orders │ │ │ │ └── order │ │ │ │ ├── create.html │ │ │ │ ├── created.html │ │ │ │ └── pdf.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── payment │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ └── payment │ │ │ │ ├── canceled.html │ │ │ │ ├── completed.html │ │ │ │ └── process.html │ │ ├── tests.py │ │ ├── urls.py │ │ ├── views.py │ │ └── webhooks.py │ ├── shop │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ ├── css │ │ │ │ ├── base.css │ │ │ │ └── pdf.css │ │ │ └── img │ │ │ │ └── no_image.png │ │ ├── templates │ │ │ └── shop │ │ │ │ ├── base.html │ │ │ │ └── product │ │ │ │ ├── detail.html │ │ │ │ └── list.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── static │ │ ├── admin │ │ ├── css │ │ │ ├── autocomplete.css │ │ │ ├── base.css │ │ │ ├── changelists.css │ │ │ ├── dark_mode.css │ │ │ ├── dashboard.css │ │ │ ├── fonts.css │ │ │ ├── forms.css │ │ │ ├── login.css │ │ │ ├── nav_sidebar.css │ │ │ ├── responsive.css │ │ │ ├── responsive_rtl.css │ │ │ ├── rtl.css │ │ │ ├── vendor │ │ │ │ └── select2 │ │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ │ ├── select2.css │ │ │ │ │ └── select2.min.css │ │ │ └── widgets.css │ │ ├── fonts │ │ │ ├── LICENSE.txt │ │ │ ├── README.txt │ │ │ ├── Roboto-Bold-webfont.woff │ │ │ ├── Roboto-Light-webfont.woff │ │ │ └── Roboto-Regular-webfont.woff │ │ ├── img │ │ │ ├── LICENSE │ │ │ ├── README.txt │ │ │ ├── calendar-icons.svg │ │ │ ├── gis │ │ │ │ ├── move_vertex_off.svg │ │ │ │ └── move_vertex_on.svg │ │ │ ├── icon-addlink.svg │ │ │ ├── icon-alert.svg │ │ │ ├── icon-calendar.svg │ │ │ ├── icon-changelink.svg │ │ │ ├── icon-clock.svg │ │ │ ├── icon-deletelink.svg │ │ │ ├── icon-hidelink.svg │ │ │ ├── icon-no.svg │ │ │ ├── icon-unknown-alt.svg │ │ │ ├── icon-unknown.svg │ │ │ ├── icon-viewlink.svg │ │ │ ├── icon-yes.svg │ │ │ ├── inline-delete.svg │ │ │ ├── search.svg │ │ │ ├── selector-icons.svg │ │ │ ├── sorting-icons.svg │ │ │ ├── tooltag-add.svg │ │ │ └── tooltag-arrowright.svg │ │ └── js │ │ │ ├── SelectBox.js │ │ │ ├── SelectFilter2.js │ │ │ ├── actions.js │ │ │ ├── admin │ │ │ ├── DateTimeShortcuts.js │ │ │ └── RelatedObjectLookups.js │ │ │ ├── autocomplete.js │ │ │ ├── calendar.js │ │ │ ├── cancel.js │ │ │ ├── change_form.js │ │ │ ├── collapse.js │ │ │ ├── core.js │ │ │ ├── filters.js │ │ │ ├── inlines.js │ │ │ ├── jquery.init.js │ │ │ ├── nav_sidebar.js │ │ │ ├── popup_response.js │ │ │ ├── prepopulate.js │ │ │ ├── prepopulate_init.js │ │ │ ├── theme.js │ │ │ ├── urlify.js │ │ │ └── vendor │ │ │ ├── jquery │ │ │ ├── LICENSE.txt │ │ │ ├── jquery.js │ │ │ └── jquery.min.js │ │ │ ├── select2 │ │ │ ├── LICENSE.md │ │ │ ├── i18n │ │ │ │ ├── af.js │ │ │ │ ├── ar.js │ │ │ │ ├── az.js │ │ │ │ ├── bg.js │ │ │ │ ├── bn.js │ │ │ │ ├── bs.js │ │ │ │ ├── ca.js │ │ │ │ ├── cs.js │ │ │ │ ├── da.js │ │ │ │ ├── de.js │ │ │ │ ├── dsb.js │ │ │ │ ├── el.js │ │ │ │ ├── en.js │ │ │ │ ├── es.js │ │ │ │ ├── et.js │ │ │ │ ├── eu.js │ │ │ │ ├── fa.js │ │ │ │ ├── fi.js │ │ │ │ ├── fr.js │ │ │ │ ├── gl.js │ │ │ │ ├── he.js │ │ │ │ ├── hi.js │ │ │ │ ├── hr.js │ │ │ │ ├── hsb.js │ │ │ │ ├── hu.js │ │ │ │ ├── hy.js │ │ │ │ ├── id.js │ │ │ │ ├── is.js │ │ │ │ ├── it.js │ │ │ │ ├── ja.js │ │ │ │ ├── ka.js │ │ │ │ ├── km.js │ │ │ │ ├── ko.js │ │ │ │ ├── lt.js │ │ │ │ ├── lv.js │ │ │ │ ├── mk.js │ │ │ │ ├── ms.js │ │ │ │ ├── nb.js │ │ │ │ ├── ne.js │ │ │ │ ├── nl.js │ │ │ │ ├── pl.js │ │ │ │ ├── ps.js │ │ │ │ ├── pt-BR.js │ │ │ │ ├── pt.js │ │ │ │ ├── ro.js │ │ │ │ ├── ru.js │ │ │ │ ├── sk.js │ │ │ │ ├── sl.js │ │ │ │ ├── sq.js │ │ │ │ ├── sr-Cyrl.js │ │ │ │ ├── sr.js │ │ │ │ ├── sv.js │ │ │ │ ├── th.js │ │ │ │ ├── tk.js │ │ │ │ ├── tr.js │ │ │ │ ├── uk.js │ │ │ │ ├── vi.js │ │ │ │ ├── zh-CN.js │ │ │ │ └── zh-TW.js │ │ │ ├── select2.full.js │ │ │ └── select2.full.min.js │ │ │ └── xregexp │ │ │ ├── LICENSE.txt │ │ │ ├── xregexp.js │ │ │ └── xregexp.min.js │ │ ├── css │ │ ├── base.css │ │ └── pdf.css │ │ └── img │ │ └── no_image.png └── requirements.txt ├── Chapter10 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── myshop │ ├── cart │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── cart.py │ │ ├── context_processors.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── cart │ │ │ │ └── detail.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── coupons │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── manage.py │ ├── myshop │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── celery.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── orders │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_order_stripe_id.py │ │ │ ├── 0003_order_coupon_order_discount.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ ├── admin │ │ │ │ └── orders │ │ │ │ │ └── order │ │ │ │ │ └── detail.html │ │ │ └── orders │ │ │ │ └── order │ │ │ │ ├── create.html │ │ │ │ ├── created.html │ │ │ │ └── pdf.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── payment │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ └── payment │ │ │ │ ├── canceled.html │ │ │ │ ├── completed.html │ │ │ │ └── process.html │ │ ├── tests.py │ │ ├── urls.py │ │ ├── views.py │ │ └── webhooks.py │ ├── shop │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── recommender.py │ │ ├── static │ │ │ ├── css │ │ │ │ ├── base.css │ │ │ │ └── pdf.css │ │ │ └── img │ │ │ │ └── no_image.png │ │ ├── templates │ │ │ └── shop │ │ │ │ ├── base.html │ │ │ │ └── product │ │ │ │ ├── detail.html │ │ │ │ └── list.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── static │ │ ├── admin │ │ ├── css │ │ │ ├── autocomplete.css │ │ │ ├── base.css │ │ │ ├── changelists.css │ │ │ ├── dark_mode.css │ │ │ ├── dashboard.css │ │ │ ├── fonts.css │ │ │ ├── forms.css │ │ │ ├── login.css │ │ │ ├── nav_sidebar.css │ │ │ ├── responsive.css │ │ │ ├── responsive_rtl.css │ │ │ ├── rtl.css │ │ │ ├── vendor │ │ │ │ └── select2 │ │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ │ ├── select2.css │ │ │ │ │ └── select2.min.css │ │ │ └── widgets.css │ │ ├── fonts │ │ │ ├── LICENSE.txt │ │ │ ├── README.txt │ │ │ ├── Roboto-Bold-webfont.woff │ │ │ ├── Roboto-Light-webfont.woff │ │ │ └── Roboto-Regular-webfont.woff │ │ ├── img │ │ │ ├── LICENSE │ │ │ ├── README.txt │ │ │ ├── calendar-icons.svg │ │ │ ├── gis │ │ │ │ ├── move_vertex_off.svg │ │ │ │ └── move_vertex_on.svg │ │ │ ├── icon-addlink.svg │ │ │ ├── icon-alert.svg │ │ │ ├── icon-calendar.svg │ │ │ ├── icon-changelink.svg │ │ │ ├── icon-clock.svg │ │ │ ├── icon-deletelink.svg │ │ │ ├── icon-hidelink.svg │ │ │ ├── icon-no.svg │ │ │ ├── icon-unknown-alt.svg │ │ │ ├── icon-unknown.svg │ │ │ ├── icon-viewlink.svg │ │ │ ├── icon-yes.svg │ │ │ ├── inline-delete.svg │ │ │ ├── search.svg │ │ │ ├── selector-icons.svg │ │ │ ├── sorting-icons.svg │ │ │ ├── tooltag-add.svg │ │ │ └── tooltag-arrowright.svg │ │ └── js │ │ │ ├── SelectBox.js │ │ │ ├── SelectFilter2.js │ │ │ ├── actions.js │ │ │ ├── admin │ │ │ ├── DateTimeShortcuts.js │ │ │ └── RelatedObjectLookups.js │ │ │ ├── autocomplete.js │ │ │ ├── calendar.js │ │ │ ├── cancel.js │ │ │ ├── change_form.js │ │ │ ├── collapse.js │ │ │ ├── core.js │ │ │ ├── filters.js │ │ │ ├── inlines.js │ │ │ ├── jquery.init.js │ │ │ ├── nav_sidebar.js │ │ │ ├── popup_response.js │ │ │ ├── prepopulate.js │ │ │ ├── prepopulate_init.js │ │ │ ├── theme.js │ │ │ ├── urlify.js │ │ │ └── vendor │ │ │ ├── jquery │ │ │ ├── LICENSE.txt │ │ │ ├── jquery.js │ │ │ └── jquery.min.js │ │ │ ├── select2 │ │ │ ├── LICENSE.md │ │ │ ├── i18n │ │ │ │ ├── af.js │ │ │ │ ├── ar.js │ │ │ │ ├── az.js │ │ │ │ ├── bg.js │ │ │ │ ├── bn.js │ │ │ │ ├── bs.js │ │ │ │ ├── ca.js │ │ │ │ ├── cs.js │ │ │ │ ├── da.js │ │ │ │ ├── de.js │ │ │ │ ├── dsb.js │ │ │ │ ├── el.js │ │ │ │ ├── en.js │ │ │ │ ├── es.js │ │ │ │ ├── et.js │ │ │ │ ├── eu.js │ │ │ │ ├── fa.js │ │ │ │ ├── fi.js │ │ │ │ ├── fr.js │ │ │ │ ├── gl.js │ │ │ │ ├── he.js │ │ │ │ ├── hi.js │ │ │ │ ├── hr.js │ │ │ │ ├── hsb.js │ │ │ │ ├── hu.js │ │ │ │ ├── hy.js │ │ │ │ ├── id.js │ │ │ │ ├── is.js │ │ │ │ ├── it.js │ │ │ │ ├── ja.js │ │ │ │ ├── ka.js │ │ │ │ ├── km.js │ │ │ │ ├── ko.js │ │ │ │ ├── lt.js │ │ │ │ ├── lv.js │ │ │ │ ├── mk.js │ │ │ │ ├── ms.js │ │ │ │ ├── nb.js │ │ │ │ ├── ne.js │ │ │ │ ├── nl.js │ │ │ │ ├── pl.js │ │ │ │ ├── ps.js │ │ │ │ ├── pt-BR.js │ │ │ │ ├── pt.js │ │ │ │ ├── ro.js │ │ │ │ ├── ru.js │ │ │ │ ├── sk.js │ │ │ │ ├── sl.js │ │ │ │ ├── sq.js │ │ │ │ ├── sr-Cyrl.js │ │ │ │ ├── sr.js │ │ │ │ ├── sv.js │ │ │ │ ├── th.js │ │ │ │ ├── tk.js │ │ │ │ ├── tr.js │ │ │ │ ├── uk.js │ │ │ │ ├── vi.js │ │ │ │ ├── zh-CN.js │ │ │ │ └── zh-TW.js │ │ │ ├── select2.full.js │ │ │ └── select2.full.min.js │ │ │ └── xregexp │ │ │ ├── LICENSE.txt │ │ │ ├── xregexp.js │ │ │ └── xregexp.min.js │ │ ├── css │ │ ├── base.css │ │ └── pdf.css │ │ └── img │ │ └── no_image.png └── requirements.txt ├── Chapter11 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── myshop │ ├── cart │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── cart.py │ │ ├── context_processors.py │ │ ├── forms.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ │ └── cart │ │ │ │ └── detail.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── coupons │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── locale │ │ ├── en │ │ │ └── LC_MESSAGES │ │ │ │ └── django.po │ │ └── es │ │ │ └── LC_MESSAGES │ │ │ └── django.po │ ├── manage.py │ ├── myshop │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── celery.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── orders │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── locale │ │ │ ├── en │ │ │ │ └── LC_MESSAGES │ │ │ │ │ └── django.po │ │ │ └── es │ │ │ │ └── LC_MESSAGES │ │ │ │ └── django.po │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_order_stripe_id.py │ │ │ ├── 0003_order_coupon_order_discount.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ ├── admin │ │ │ │ └── orders │ │ │ │ │ └── order │ │ │ │ │ └── detail.html │ │ │ └── orders │ │ │ │ └── order │ │ │ │ ├── create.html │ │ │ │ ├── created.html │ │ │ │ └── pdf.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── payment │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── tasks.py │ │ ├── templates │ │ │ └── payment │ │ │ │ ├── canceled.html │ │ │ │ ├── completed.html │ │ │ │ └── process.html │ │ ├── tests.py │ │ ├── urls.py │ │ ├── views.py │ │ └── webhooks.py │ ├── shop │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_translations.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── recommender.py │ │ ├── static │ │ │ ├── css │ │ │ │ ├── base.css │ │ │ │ └── pdf.css │ │ │ └── img │ │ │ │ └── no_image.png │ │ ├── templates │ │ │ └── shop │ │ │ │ ├── base.html │ │ │ │ └── product │ │ │ │ ├── detail.html │ │ │ │ └── list.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ └── static │ │ ├── admin │ │ ├── css │ │ │ ├── autocomplete.css │ │ │ ├── base.css │ │ │ ├── changelists.css │ │ │ ├── dark_mode.css │ │ │ ├── dashboard.css │ │ │ ├── fonts.css │ │ │ ├── forms.css │ │ │ ├── login.css │ │ │ ├── nav_sidebar.css │ │ │ ├── responsive.css │ │ │ ├── responsive_rtl.css │ │ │ ├── rtl.css │ │ │ ├── vendor │ │ │ │ └── select2 │ │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ │ ├── select2.css │ │ │ │ │ └── select2.min.css │ │ │ └── widgets.css │ │ ├── fonts │ │ │ ├── LICENSE.txt │ │ │ ├── README.txt │ │ │ ├── Roboto-Bold-webfont.woff │ │ │ ├── Roboto-Light-webfont.woff │ │ │ └── Roboto-Regular-webfont.woff │ │ ├── img │ │ │ ├── LICENSE │ │ │ ├── README.txt │ │ │ ├── calendar-icons.svg │ │ │ ├── gis │ │ │ │ ├── move_vertex_off.svg │ │ │ │ └── move_vertex_on.svg │ │ │ ├── icon-addlink.svg │ │ │ ├── icon-alert.svg │ │ │ ├── icon-calendar.svg │ │ │ ├── icon-changelink.svg │ │ │ ├── icon-clock.svg │ │ │ ├── icon-deletelink.svg │ │ │ ├── icon-hidelink.svg │ │ │ ├── icon-no.svg │ │ │ ├── icon-unknown-alt.svg │ │ │ ├── icon-unknown.svg │ │ │ ├── icon-viewlink.svg │ │ │ ├── icon-yes.svg │ │ │ ├── icon_searchbox_rosetta.png │ │ │ ├── inline-delete.svg │ │ │ ├── search.svg │ │ │ ├── selector-icons.svg │ │ │ ├── sorting-icons.svg │ │ │ ├── tooltag-add.svg │ │ │ └── tooltag-arrowright.svg │ │ └── js │ │ │ ├── SelectBox.js │ │ │ ├── SelectFilter2.js │ │ │ ├── actions.js │ │ │ ├── admin │ │ │ ├── DateTimeShortcuts.js │ │ │ └── RelatedObjectLookups.js │ │ │ ├── autocomplete.js │ │ │ ├── calendar.js │ │ │ ├── cancel.js │ │ │ ├── change_form.js │ │ │ ├── collapse.js │ │ │ ├── core.js │ │ │ ├── filters.js │ │ │ ├── inlines.js │ │ │ ├── jquery.init.js │ │ │ ├── nav_sidebar.js │ │ │ ├── popup_response.js │ │ │ ├── prepopulate.js │ │ │ ├── prepopulate_init.js │ │ │ ├── theme.js │ │ │ ├── urlify.js │ │ │ └── vendor │ │ │ ├── jquery │ │ │ ├── LICENSE.txt │ │ │ ├── jquery.js │ │ │ └── jquery.min.js │ │ │ ├── select2 │ │ │ ├── LICENSE.md │ │ │ ├── i18n │ │ │ │ ├── af.js │ │ │ │ ├── ar.js │ │ │ │ ├── az.js │ │ │ │ ├── bg.js │ │ │ │ ├── bn.js │ │ │ │ ├── bs.js │ │ │ │ ├── ca.js │ │ │ │ ├── cs.js │ │ │ │ ├── da.js │ │ │ │ ├── de.js │ │ │ │ ├── dsb.js │ │ │ │ ├── el.js │ │ │ │ ├── en.js │ │ │ │ ├── es.js │ │ │ │ ├── et.js │ │ │ │ ├── eu.js │ │ │ │ ├── fa.js │ │ │ │ ├── fi.js │ │ │ │ ├── fr.js │ │ │ │ ├── gl.js │ │ │ │ ├── he.js │ │ │ │ ├── hi.js │ │ │ │ ├── hr.js │ │ │ │ ├── hsb.js │ │ │ │ ├── hu.js │ │ │ │ ├── hy.js │ │ │ │ ├── id.js │ │ │ │ ├── is.js │ │ │ │ ├── it.js │ │ │ │ ├── ja.js │ │ │ │ ├── ka.js │ │ │ │ ├── km.js │ │ │ │ ├── ko.js │ │ │ │ ├── lt.js │ │ │ │ ├── lv.js │ │ │ │ ├── mk.js │ │ │ │ ├── ms.js │ │ │ │ ├── nb.js │ │ │ │ ├── ne.js │ │ │ │ ├── nl.js │ │ │ │ ├── pl.js │ │ │ │ ├── ps.js │ │ │ │ ├── pt-BR.js │ │ │ │ ├── pt.js │ │ │ │ ├── ro.js │ │ │ │ ├── ru.js │ │ │ │ ├── sk.js │ │ │ │ ├── sl.js │ │ │ │ ├── sq.js │ │ │ │ ├── sr-Cyrl.js │ │ │ │ ├── sr.js │ │ │ │ ├── sv.js │ │ │ │ ├── th.js │ │ │ │ ├── tk.js │ │ │ │ ├── tr.js │ │ │ │ ├── uk.js │ │ │ │ ├── vi.js │ │ │ │ ├── zh-CN.js │ │ │ │ └── zh-TW.js │ │ │ ├── select2.full.js │ │ │ └── select2.full.min.js │ │ │ └── xregexp │ │ │ ├── LICENSE.txt │ │ │ ├── xregexp.js │ │ │ └── xregexp.min.js │ │ ├── css │ │ ├── base.css │ │ └── pdf.css │ │ ├── img │ │ └── no_image.png │ │ └── parler │ │ └── admin │ │ └── parler_admin.css ├── prompts │ └── task.md └── requirements.txt ├── Chapter12 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── educa │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── tests.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── manage.py └── requirements.txt ├── Chapter13 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── educa │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── courses │ │ │ │ └── manage │ │ │ │ │ ├── content │ │ │ │ │ └── form.html │ │ │ │ │ ├── course │ │ │ │ │ ├── delete.html │ │ │ │ │ ├── form.html │ │ │ │ │ └── list.html │ │ │ │ │ └── module │ │ │ │ │ ├── content_list.html │ │ │ │ │ └── formset.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── course.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ └── manage.py └── requirements.txt ├── Chapter14 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── educa │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ ├── 0004_course_students.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── courses │ │ │ │ ├── content │ │ │ │ │ ├── file.html │ │ │ │ │ ├── image.html │ │ │ │ │ ├── text.html │ │ │ │ │ └── video.html │ │ │ │ ├── course │ │ │ │ │ ├── detail.html │ │ │ │ │ └── list.html │ │ │ │ └── manage │ │ │ │ │ ├── content │ │ │ │ │ └── form.html │ │ │ │ │ ├── course │ │ │ │ │ ├── delete.html │ │ │ │ │ ├── form.html │ │ │ │ │ └── list.html │ │ │ │ │ └── module │ │ │ │ │ ├── content_list.html │ │ │ │ │ └── formset.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── course.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── manage.py │ └── students │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── students │ │ │ ├── course │ │ │ ├── detail.html │ │ │ └── list.html │ │ │ └── student │ │ │ └── registration.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py └── requirements.txt ├── Chapter15 ├── Dockerfile ├── api_examples │ └── enroll_all.py ├── do.sh ├── docker-compose.yml ├── educa │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ ├── permissions.py │ │ │ ├── serializers.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ ├── 0004_course_students.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── courses │ │ │ │ ├── content │ │ │ │ │ ├── file.html │ │ │ │ │ ├── image.html │ │ │ │ │ ├── text.html │ │ │ │ │ └── video.html │ │ │ │ ├── course │ │ │ │ │ ├── detail.html │ │ │ │ │ └── list.html │ │ │ │ └── manage │ │ │ │ │ ├── content │ │ │ │ │ └── form.html │ │ │ │ │ ├── course │ │ │ │ │ ├── delete.html │ │ │ │ │ ├── form.html │ │ │ │ │ └── list.html │ │ │ │ │ └── module │ │ │ │ │ ├── content_list.html │ │ │ │ │ └── formset.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── course.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── manage.py │ └── students │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── students │ │ │ ├── course │ │ │ ├── detail.html │ │ │ └── list.html │ │ │ └── student │ │ │ └── registration.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py └── requirements.txt ├── Chapter16 ├── Dockerfile ├── do.sh ├── docker-compose.yml ├── educa │ ├── chat │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── consumers.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── routing.py │ │ ├── templates │ │ │ └── chat │ │ │ │ └── room.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ ├── permissions.py │ │ │ ├── serializers.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── forms.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ ├── 0004_course_students.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── courses │ │ │ │ ├── content │ │ │ │ │ ├── file.html │ │ │ │ │ ├── image.html │ │ │ │ │ ├── text.html │ │ │ │ │ └── video.html │ │ │ │ ├── course │ │ │ │ │ ├── detail.html │ │ │ │ │ └── list.html │ │ │ │ └── manage │ │ │ │ │ ├── content │ │ │ │ │ └── form.html │ │ │ │ │ ├── course │ │ │ │ │ ├── delete.html │ │ │ │ │ ├── form.html │ │ │ │ │ └── list.html │ │ │ │ │ └── module │ │ │ │ │ ├── content_list.html │ │ │ │ │ └── formset.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── course.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── manage.py │ └── students │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── students │ │ │ ├── course │ │ │ ├── detail.html │ │ │ └── list.html │ │ │ └── student │ │ │ └── registration.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py └── requirements.txt ├── Chapter17 ├── Dockerfile ├── config │ ├── nginx │ │ └── default.conf.template │ └── uwsgi │ │ └── uwsgi.ini ├── docker-compose.yml ├── educa │ ├── chat │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── consumers.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── routing.py │ │ ├── templates │ │ │ └── chat │ │ │ │ └── room.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── courses │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── api │ │ │ ├── __init__.py │ │ │ ├── pagination.py │ │ │ ├── permissions.py │ │ │ ├── serializers.py │ │ │ ├── urls.py │ │ │ └── views.py │ │ ├── apps.py │ │ ├── fields.py │ │ ├── fixtures │ │ │ └── subjects.json │ │ ├── forms.py │ │ ├── middleware.py │ │ ├── migrations │ │ │ ├── 0001_initial.py │ │ │ ├── 0002_video_text_image_file_content.py │ │ │ ├── 0003_alter_content_options_alter_module_options_and_more.py │ │ │ ├── 0004_course_students.py │ │ │ └── __init__.py │ │ ├── models.py │ │ ├── static │ │ │ └── css │ │ │ │ └── base.css │ │ ├── templates │ │ │ ├── base.html │ │ │ ├── courses │ │ │ │ ├── content │ │ │ │ │ ├── file.html │ │ │ │ │ ├── image.html │ │ │ │ │ ├── text.html │ │ │ │ │ └── video.html │ │ │ │ ├── course │ │ │ │ │ ├── detail.html │ │ │ │ │ └── list.html │ │ │ │ └── manage │ │ │ │ │ ├── content │ │ │ │ │ └── form.html │ │ │ │ │ ├── course │ │ │ │ │ ├── delete.html │ │ │ │ │ ├── form.html │ │ │ │ │ └── list.html │ │ │ │ │ └── module │ │ │ │ │ ├── content_list.html │ │ │ │ │ └── formset.html │ │ │ └── registration │ │ │ │ ├── logged_out.html │ │ │ │ └── login.html │ │ ├── templatetags │ │ │ ├── __init__.py │ │ │ └── course.py │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py │ ├── educa │ │ ├── __init__.py │ │ ├── asgi.py │ │ ├── settings │ │ │ ├── __init__.py │ │ │ ├── base.py │ │ │ ├── local.py │ │ │ └── prod.py │ │ ├── urls.py │ │ └── wsgi.py │ ├── manage.py │ ├── ssl │ │ ├── educa.crt │ │ └── educa.key │ ├── static │ │ ├── admin │ │ │ ├── css │ │ │ │ ├── autocomplete.css │ │ │ │ ├── base.css │ │ │ │ ├── changelists.css │ │ │ │ ├── dark_mode.css │ │ │ │ ├── dashboard.css │ │ │ │ ├── fonts.css │ │ │ │ ├── forms.css │ │ │ │ ├── login.css │ │ │ │ ├── nav_sidebar.css │ │ │ │ ├── responsive.css │ │ │ │ ├── responsive_rtl.css │ │ │ │ ├── rtl.css │ │ │ │ ├── vendor │ │ │ │ │ └── select2 │ │ │ │ │ │ ├── LICENSE-SELECT2.md │ │ │ │ │ │ ├── select2.css │ │ │ │ │ │ └── select2.min.css │ │ │ │ └── widgets.css │ │ │ ├── fonts │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── README.txt │ │ │ │ ├── Roboto-Bold-webfont.woff │ │ │ │ ├── Roboto-Light-webfont.woff │ │ │ │ └── Roboto-Regular-webfont.woff │ │ │ ├── img │ │ │ │ ├── LICENSE │ │ │ │ ├── README.txt │ │ │ │ ├── calendar-icons.svg │ │ │ │ ├── gis │ │ │ │ │ ├── move_vertex_off.svg │ │ │ │ │ └── move_vertex_on.svg │ │ │ │ ├── icon-addlink.svg │ │ │ │ ├── icon-alert.svg │ │ │ │ ├── icon-calendar.svg │ │ │ │ ├── icon-changelink.svg │ │ │ │ ├── icon-clock.svg │ │ │ │ ├── icon-deletelink.svg │ │ │ │ ├── icon-hidelink.svg │ │ │ │ ├── icon-no.svg │ │ │ │ ├── icon-unknown-alt.svg │ │ │ │ ├── icon-unknown.svg │ │ │ │ ├── icon-viewlink.svg │ │ │ │ ├── icon-yes.svg │ │ │ │ ├── inline-delete.svg │ │ │ │ ├── search.svg │ │ │ │ ├── selector-icons.svg │ │ │ │ ├── sorting-icons.svg │ │ │ │ ├── tooltag-add.svg │ │ │ │ └── tooltag-arrowright.svg │ │ │ └── js │ │ │ │ ├── SelectBox.js │ │ │ │ ├── SelectFilter2.js │ │ │ │ ├── actions.js │ │ │ │ ├── admin │ │ │ │ ├── DateTimeShortcuts.js │ │ │ │ └── RelatedObjectLookups.js │ │ │ │ ├── autocomplete.js │ │ │ │ ├── calendar.js │ │ │ │ ├── cancel.js │ │ │ │ ├── change_form.js │ │ │ │ ├── collapse.js │ │ │ │ ├── core.js │ │ │ │ ├── filters.js │ │ │ │ ├── inlines.js │ │ │ │ ├── jquery.init.js │ │ │ │ ├── nav_sidebar.js │ │ │ │ ├── popup_response.js │ │ │ │ ├── prepopulate.js │ │ │ │ ├── prepopulate_init.js │ │ │ │ ├── theme.js │ │ │ │ ├── urlify.js │ │ │ │ └── vendor │ │ │ │ ├── jquery │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── jquery.js │ │ │ │ └── jquery.min.js │ │ │ │ ├── select2 │ │ │ │ ├── LICENSE.md │ │ │ │ ├── i18n │ │ │ │ │ ├── af.js │ │ │ │ │ ├── ar.js │ │ │ │ │ ├── az.js │ │ │ │ │ ├── bg.js │ │ │ │ │ ├── bn.js │ │ │ │ │ ├── bs.js │ │ │ │ │ ├── ca.js │ │ │ │ │ ├── cs.js │ │ │ │ │ ├── da.js │ │ │ │ │ ├── de.js │ │ │ │ │ ├── dsb.js │ │ │ │ │ ├── el.js │ │ │ │ │ ├── en.js │ │ │ │ │ ├── es.js │ │ │ │ │ ├── et.js │ │ │ │ │ ├── eu.js │ │ │ │ │ ├── fa.js │ │ │ │ │ ├── fi.js │ │ │ │ │ ├── fr.js │ │ │ │ │ ├── gl.js │ │ │ │ │ ├── he.js │ │ │ │ │ ├── hi.js │ │ │ │ │ ├── hr.js │ │ │ │ │ ├── hsb.js │ │ │ │ │ ├── hu.js │ │ │ │ │ ├── hy.js │ │ │ │ │ ├── id.js │ │ │ │ │ ├── is.js │ │ │ │ │ ├── it.js │ │ │ │ │ ├── ja.js │ │ │ │ │ ├── ka.js │ │ │ │ │ ├── km.js │ │ │ │ │ ├── ko.js │ │ │ │ │ ├── lt.js │ │ │ │ │ ├── lv.js │ │ │ │ │ ├── mk.js │ │ │ │ │ ├── ms.js │ │ │ │ │ ├── nb.js │ │ │ │ │ ├── ne.js │ │ │ │ │ ├── nl.js │ │ │ │ │ ├── pl.js │ │ │ │ │ ├── ps.js │ │ │ │ │ ├── pt-BR.js │ │ │ │ │ ├── pt.js │ │ │ │ │ ├── ro.js │ │ │ │ │ ├── ru.js │ │ │ │ │ ├── sk.js │ │ │ │ │ ├── sl.js │ │ │ │ │ ├── sq.js │ │ │ │ │ ├── sr-Cyrl.js │ │ │ │ │ ├── sr.js │ │ │ │ │ ├── sv.js │ │ │ │ │ ├── th.js │ │ │ │ │ ├── tk.js │ │ │ │ │ ├── tr.js │ │ │ │ │ ├── uk.js │ │ │ │ │ ├── vi.js │ │ │ │ │ ├── zh-CN.js │ │ │ │ │ └── zh-TW.js │ │ │ │ ├── select2.full.js │ │ │ │ └── select2.full.min.js │ │ │ │ └── xregexp │ │ │ │ ├── LICENSE.txt │ │ │ │ ├── xregexp.js │ │ │ │ └── xregexp.min.js │ │ ├── css │ │ │ └── base.css │ │ ├── debug_toolbar │ │ │ ├── css │ │ │ │ ├── print.css │ │ │ │ └── toolbar.css │ │ │ └── js │ │ │ │ ├── history.js │ │ │ │ ├── redirect.js │ │ │ │ ├── timer.js │ │ │ │ ├── toolbar.js │ │ │ │ └── utils.js │ │ ├── redisboard │ │ │ ├── admin.css │ │ │ └── favicon.ico │ │ └── rest_framework │ │ │ ├── css │ │ │ ├── bootstrap-theme.min.css │ │ │ ├── bootstrap-theme.min.css.map │ │ │ ├── bootstrap-tweaks.css │ │ │ ├── bootstrap.min.css │ │ │ ├── bootstrap.min.css.map │ │ │ ├── default.css │ │ │ ├── font-awesome-4.0.3.css │ │ │ └── prettify.css │ │ │ ├── docs │ │ │ ├── css │ │ │ │ ├── base.css │ │ │ │ ├── highlight.css │ │ │ │ └── jquery.json-view.min.css │ │ │ ├── img │ │ │ │ ├── favicon.ico │ │ │ │ └── grid.png │ │ │ └── js │ │ │ │ ├── api.js │ │ │ │ ├── highlight.pack.js │ │ │ │ └── jquery.json-view.min.js │ │ │ ├── fonts │ │ │ ├── fontawesome-webfont.eot │ │ │ ├── fontawesome-webfont.svg │ │ │ ├── fontawesome-webfont.ttf │ │ │ ├── fontawesome-webfont.woff │ │ │ ├── glyphicons-halflings-regular.eot │ │ │ ├── glyphicons-halflings-regular.svg │ │ │ ├── glyphicons-halflings-regular.ttf │ │ │ ├── glyphicons-halflings-regular.woff │ │ │ └── glyphicons-halflings-regular.woff2 │ │ │ ├── img │ │ │ ├── glyphicons-halflings-white.png │ │ │ ├── glyphicons-halflings.png │ │ │ └── grid.png │ │ │ └── js │ │ │ ├── ajax-form.js │ │ │ ├── bootstrap.min.js │ │ │ ├── coreapi-0.1.1.js │ │ │ ├── csrf.js │ │ │ ├── default.js │ │ │ ├── jquery-3.5.1.min.js │ │ │ └── prettify-min.js │ └── students │ │ ├── __init__.py │ │ ├── admin.py │ │ ├── apps.py │ │ ├── forms.py │ │ ├── management │ │ ├── __init__.py │ │ └── commands │ │ │ ├── __init__.py │ │ │ └── enroll_reminder.py │ │ ├── migrations │ │ └── __init__.py │ │ ├── models.py │ │ ├── templates │ │ └── students │ │ │ ├── course │ │ │ ├── detail.html │ │ │ └── list.html │ │ │ └── student │ │ │ └── registration.html │ │ ├── tests.py │ │ ├── urls.py │ │ └── views.py ├── prompts │ └── task.md ├── requirements.txt └── wait-for-it.sh ├── LICENSE └── README.md /Chapter01/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | 16 | COPY . . -------------------------------------------------------------------------------- /Chapter01/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/mysite/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/mysite/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate -------------------------------------------------------------------------------- /Chapter01/mysite/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter01/mysite/blog/__init__.py -------------------------------------------------------------------------------- /Chapter01/mysite/blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'blog' 7 | -------------------------------------------------------------------------------- /Chapter01/mysite/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter01/mysite/blog/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter01/mysite/blog/templates/blog/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | {% block title %}{% endblock %} 6 | 7 | 8 | 9 |
10 | {% block content %} 11 | {% endblock %} 12 |
13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Chapter01/mysite/blog/templates/blog/post/detail.html: -------------------------------------------------------------------------------- 1 | {% extends "blog/base.html" %} 2 | 3 | {% block title %}{{ post.title }}{% endblock %} 4 | 5 | {% block content %} 6 |

{{ post.title }}

7 |

8 | Published {{ post.publish }} by {{ post.author }} 9 |

10 | {{ post.body|linebreaks }} 11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter01/mysite/blog/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter01/mysite/blog/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'blog' 6 | 7 | urlpatterns = [ 8 | # post views 9 | path('', views.post_list, name='post_list'), 10 | path('/', views.post_detail, name='post_detail'), 11 | ] 12 | -------------------------------------------------------------------------------- /Chapter01/mysite/mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter01/mysite/mysite/__init__.py -------------------------------------------------------------------------------- /Chapter01/mysite/mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter01/mysite/mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter01/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | -------------------------------------------------------------------------------- /Chapter02/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | 16 | COPY . . -------------------------------------------------------------------------------- /Chapter02/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | env_file: 5 | - .env 6 | volumes: 7 | - .:/code 8 | web_migrate: 9 | extends: 10 | service: web 11 | command: python /code/mysite/manage.py migrate 12 | web_run: 13 | extends: 14 | service: web 15 | command: python /code/mysite/manage.py runserver 0.0.0.0:8000 16 | ports: 17 | - "8000:8000" 18 | depends_on: 19 | - web_migrate -------------------------------------------------------------------------------- /Chapter02/mysite/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter02/mysite/blog/__init__.py -------------------------------------------------------------------------------- /Chapter02/mysite/blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'blog' 7 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Comment 4 | 5 | 6 | class EmailPostForm(forms.Form): 7 | name = forms.CharField(max_length=25) 8 | email = forms.EmailField() 9 | to = forms.EmailField() 10 | comments = forms.CharField( 11 | required=False, 12 | widget=forms.Textarea 13 | ) 14 | 15 | 16 | class CommentForm(forms.ModelForm): 17 | class Meta: 18 | model = Comment 19 | fields = ['name', 'email', 'body'] 20 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/migrations/0002_alter_post_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('blog', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='post', 15 | name='slug', 16 | field=models.SlugField(max_length=250, unique_for_date='publish'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter02/mysite/blog/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter02/mysite/blog/templates/blog/base.html: -------------------------------------------------------------------------------- 1 | {% load static %} 2 | 3 | 4 | 5 | {% block title %}{% endblock %} 6 | 7 | 8 | 9 |
10 | {% block content %} 11 | {% endblock %} 12 |
13 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/templates/blog/post/comment.html: -------------------------------------------------------------------------------- 1 | {% extends "blog/base.html" %} 2 | 3 | {% block title %}Add a comment{% endblock %} 4 | 5 | {% block content %} 6 | {% if comment %} 7 |

Your comment has been added.

8 |

Back to the post

9 | {% else %} 10 | {% include "blog/post/includes/comment_form.html" %} 11 | {% endif %} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/templates/blog/post/includes/comment_form.html: -------------------------------------------------------------------------------- 1 |

Add a new comment

2 |
3 |
4 | {{ form.name.as_field_group }} 5 |
6 |
7 | {{ form.email.as_field_group }} 8 |
9 | {{ form.body.as_field_group }} 10 | {% csrf_token %} 11 |

12 |
13 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/templates/pagination.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /Chapter02/mysite/blog/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter02/mysite/mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter02/mysite/mysite/__init__.py -------------------------------------------------------------------------------- /Chapter02/mysite/mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter02/mysite/mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter02/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | python-decouple==3.8 5 | -------------------------------------------------------------------------------- /Chapter03/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter03/mysite/blog/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter03/mysite/blog/__init__.py -------------------------------------------------------------------------------- /Chapter03/mysite/blog/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class BlogConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'blog' 7 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/migrations/0002_alter_post_slug.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('blog', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AlterField( 14 | model_name='post', 15 | name='slug', 16 | field=models.SlugField(max_length=250, unique_for_date='publish'), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/migrations/0005_trigram_ext.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.contrib.postgres.operations import TrigramExtension 4 | from django.db import migrations 5 | 6 | 7 | class Migration(migrations.Migration): 8 | 9 | dependencies = [ 10 | ('blog', '0004_post_tags'), 11 | ] 12 | 13 | operations = [ 14 | TrigramExtension() 15 | ] 16 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter03/mysite/blog/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter03/mysite/blog/sitemaps.py: -------------------------------------------------------------------------------- 1 | from django.contrib.sitemaps import Sitemap 2 | 3 | from .models import Post 4 | 5 | 6 | class PostSitemap(Sitemap): 7 | changefreq = 'weekly' 8 | priority = 0.9 9 | 10 | def items(self): 11 | return Post.published.all() 12 | 13 | def lastmod(self, obj): 14 | return obj.updated 15 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/templates/blog/post/comment.html: -------------------------------------------------------------------------------- 1 | {% extends "blog/base.html" %} 2 | 3 | {% block title %}Add a comment{% endblock %} 4 | 5 | {% block content %} 6 | {% if comment %} 7 |

Your comment has been added.

8 |

Back to the post

9 | {% else %} 10 | {% include "blog/post/includes/comment_form.html" %} 11 | {% endif %} 12 | {% endblock %} 13 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/templates/blog/post/includes/comment_form.html: -------------------------------------------------------------------------------- 1 |

Add a new comment

2 |
3 |
4 | {{ form.name.as_field_group }} 5 |
6 |
7 | {{ form.email.as_field_group }} 8 |
9 | {{ form.body.as_field_group }} 10 | {% csrf_token %} 11 |

12 |
13 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/templates/blog/post/latest_posts.html: -------------------------------------------------------------------------------- 1 | 8 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/templates/pagination.html: -------------------------------------------------------------------------------- 1 | 14 | -------------------------------------------------------------------------------- /Chapter03/mysite/blog/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter03/mysite/blog/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter03/mysite/blog/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter03/mysite/mysite/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter03/mysite/mysite/__init__.py -------------------------------------------------------------------------------- /Chapter03/mysite/mysite/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for mysite project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter03/mysite/mysite/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for mysite project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'mysite.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter03/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | python-decouple==3.8 5 | django-taggit==5.0.1 6 | Markdown==3.6 7 | psycopg==3.1.18 8 | -------------------------------------------------------------------------------- /Chapter04/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter04/bookmarks/account/__init__.py -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Profile 4 | 5 | 6 | @admin.register(Profile) 7 | class ProfileAdmin(admin.ModelAdmin): 8 | list_display = ['user', 'date_of_birth', 'photo'] 9 | raw_id_fields = ['user'] 10 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'account' 7 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter04/bookmarks/account/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/account/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Dashboard{% endblock %} 4 | 5 | {% block content %} 6 |

Dashboard

7 |

8 | Welcome to your dashboard. You can edit your profile or change your password. 9 |

10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/account/edit.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Edit your account{% endblock %} 4 | 5 | {% block content %} 6 |

Edit your account

7 |

You can edit your account using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {{ profile_form.as_p }} 11 | {% csrf_token %} 12 |

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Log-in{% endblock %} 4 | 5 | {% block content %} 6 |

Log-in

7 |

Please, use the following form to log-in:

8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/account/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |

Create an account

7 |

Please, sign up using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/account/register_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Welcome{% endblock %} 4 | 5 | {% block content %} 6 |

Welcome {{ new_user.first_name }}!

7 |

8 | Your account has been successfully created. 9 | Now you can log in. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |

8 | You have been successfully logged out. 9 | You can log-in again. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password changed{% endblock %} 4 | 5 | {% block content %} 6 |

Password changed

7 |

Your password has been successfully changed.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Change your password{% endblock %} 4 | 5 | {% block content %} 6 |

Change your password

7 |

Use the form below to change your password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password reset{% endblock %} 4 | 5 | {% block content %} 6 |

Password set

7 |

Your password has been set. You can log in now

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Reset your password

7 |

We've emailed you instructions for setting your password.

8 |

If you don't receive an email, please make sure you've entered the address you registered with.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | Someone asked for password reset for email {{ email }}. Follow the link below: 2 | {{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %} 3 | Your username, in case you've forgotten: {{ user.get_username }} 4 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Forgotten your password?

7 |

Enter your e-mail address to obtain a new password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/account/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/bookmarks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter04/bookmarks/bookmarks/__init__.py -------------------------------------------------------------------------------- /Chapter04/bookmarks/bookmarks/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for bookmarks project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter04/bookmarks/bookmarks/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for bookmarks project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter04/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/bookmarks/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/bookmarks/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate 18 | -------------------------------------------------------------------------------- /Chapter04/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | -------------------------------------------------------------------------------- /Chapter05/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter05/bookmarks/account/__init__.py -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Profile 4 | 5 | 6 | @admin.register(Profile) 7 | class ProfileAdmin(admin.ModelAdmin): 8 | list_display = ['user', 'date_of_birth', 'photo'] 9 | raw_id_fields = ['user'] 10 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'account' 7 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter05/bookmarks/account/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/account/dashboard.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Dashboard{% endblock %} 4 | 5 | {% block content %} 6 |

Dashboard

7 |

8 | Welcome to your dashboard. You can edit your profile or change your password. 9 |

10 | {% endblock %} 11 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/account/edit.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Edit your account{% endblock %} 4 | 5 | {% block content %} 6 |

Edit your account

7 |

You can edit your account using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {{ profile_form.as_p }} 11 | {% csrf_token %} 12 |

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Log-in{% endblock %} 4 | 5 | {% block content %} 6 |

Log-in

7 |

Please, use the following form to log-in:

8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/account/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |

Create an account

7 |

Please, sign up using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/account/register_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Welcome{% endblock %} 4 | 5 | {% block content %} 6 |

Welcome {{ new_user.first_name }}!

7 |

8 | Your account has been successfully created. 9 | Now you can log in. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |

8 | You have been successfully logged out. 9 | You can log-in again. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password changed{% endblock %} 4 | 5 | {% block content %} 6 |

Password changed

7 |

Your password has been successfully changed.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Change your password{% endblock %} 4 | 5 | {% block content %} 6 |

Change your password

7 |

Use the form below to change your password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password reset{% endblock %} 4 | 5 | {% block content %} 6 |

Password set

7 |

Your password has been set. You can log in now

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Reset your password

7 |

We've emailed you instructions for setting your password.

8 |

If you don't receive an email, please make sure you've entered the address you registered with.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | Someone asked for password reset for email {{ email }}. Follow the link below: 2 | {{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %} 3 | Your username, in case you've forgotten: {{ user.get_username }} 4 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Forgotten your password?

7 |

Enter your e-mail address to obtain a new password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/account/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/bookmarks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter05/bookmarks/bookmarks/__init__.py -------------------------------------------------------------------------------- /Chapter05/bookmarks/bookmarks/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for bookmarks project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Chapter05/bookmarks/bookmarks/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for bookmarks project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter05/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/bookmarks/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/bookmarks/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate -------------------------------------------------------------------------------- /Chapter05/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | python-decouple==3.8 6 | social-auth-app-django==5.4.0 7 | django-extensions==3.2.3 8 | werkzeug==3.0.2 9 | pyOpenSSL==24.1.0 10 | -------------------------------------------------------------------------------- /Chapter06/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter06/bookmarks/account/__init__.py -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Profile 4 | 5 | 6 | @admin.register(Profile) 7 | class ProfileAdmin(admin.ModelAdmin): 8 | list_display = ['user', 'date_of_birth', 'photo'] 9 | raw_id_fields = ['user'] 10 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'account' 7 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter06/bookmarks/account/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/models.py: -------------------------------------------------------------------------------- 1 | from django.conf import settings 2 | from django.db import models 3 | 4 | 5 | class Profile(models.Model): 6 | user = models.OneToOneField( 7 | settings.AUTH_USER_MODEL, 8 | on_delete=models.CASCADE 9 | ) 10 | date_of_birth = models.DateField(blank=True, null=True) 11 | photo = models.ImageField(upload_to='users/%Y/%m/%d/', blank=True) 12 | 13 | def __str__(self): 14 | return f'Profile of {self.user.username}' 15 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/account/edit.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Edit your account{% endblock %} 4 | 5 | {% block content %} 6 |

Edit your account

7 |

You can edit your account using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {{ profile_form.as_p }} 11 | {% csrf_token %} 12 |

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Log-in{% endblock %} 4 | 5 | {% block content %} 6 |

Log-in

7 |

Please, use the following form to log-in:

8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/account/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |

Create an account

7 |

Please, sign up using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/account/register_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Welcome{% endblock %} 4 | 5 | {% block content %} 6 |

Welcome {{ new_user.first_name }}!

7 |

8 | Your account has been successfully created. 9 | Now you can log in. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |

8 | You have been successfully logged out. 9 | You can log-in again. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password changed{% endblock %} 4 | 5 | {% block content %} 6 |

Password changed

7 |

Your password has been successfully changed.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Change your password{% endblock %} 4 | 5 | {% block content %} 6 |

Change your password

7 |

Use the form below to change your password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password reset{% endblock %} 4 | 5 | {% block content %} 6 |

Password set

7 |

Your password has been set. You can log in now

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Reset your password

7 |

We've emailed you instructions for setting your password.

8 |

If you don't receive an email, please make sure you've entered the address you registered with.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | Someone asked for password reset for email {{ email }}. Follow the link below: 2 | {{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %} 3 | Your username, in case you've forgotten: {{ user.get_username }} 4 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Forgotten your password?

7 |

Enter your e-mail address to obtain a new password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/account/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/bookmarks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter06/bookmarks/bookmarks/__init__.py -------------------------------------------------------------------------------- /Chapter06/bookmarks/bookmarks/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for bookmarks project. 3 | 4 | It exposes the ASGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.asgi import get_asgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 15 | 16 | application = get_asgi_application() 17 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/bookmarks/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for bookmarks project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter06/bookmarks/images/__init__.py -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Image 4 | 5 | 6 | @admin.register(Image) 7 | class ImageAdmin(admin.ModelAdmin): 8 | list_display = ['title', 'slug', 'image', 'created'] 9 | list_filter = ['created'] 10 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ImagesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'images' 7 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter06/bookmarks/images/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/templates/bookmarklet_launcher.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | if(!window.bookmarklet) { 3 | bookmarklet_js = document.body.appendChild(document.createElement('script')); 4 | bookmarklet_js.src = '//127.0.0.1:8000/static/js/bookmarklet.js?r='+Math.floor(Math.random()*9999999999999999); 5 | window.bookmarklet = true; 6 | } 7 | else { 8 | bookmarkletLaunch(); 9 | } 10 | })(); 11 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/templates/images/image/create.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Bookmark an image{% endblock %} 4 | 5 | {% block content %} 6 |

Bookmark an image

7 | 8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 | 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter06/bookmarks/images/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'images' 6 | 7 | urlpatterns = [ 8 | path('create/', views.image_create, name='create'), 9 | path( 10 | 'detail///', 11 | views.image_detail, 12 | name='detail', 13 | ), 14 | path('like/', views.image_like, name='like'), 15 | path('', views.image_list, name='list'), 16 | ] 17 | -------------------------------------------------------------------------------- /Chapter06/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/bookmarks/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/bookmarks/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate 18 | -------------------------------------------------------------------------------- /Chapter06/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | python-decouple==3.8 6 | social-auth-app-django==5.4.0 7 | django-extensions==3.2.3 8 | werkzeug==3.0.2 9 | pyOpenSSL==24.1.0 10 | requests==2.31.0 11 | easy-thumbnails==2.8.5 12 | -------------------------------------------------------------------------------- /Chapter07/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/account/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Profile 4 | 5 | 6 | @admin.register(Profile) 7 | class ProfileAdmin(admin.ModelAdmin): 8 | list_display = ['user', 'date_of_birth', 'photo'] 9 | raw_id_fields = ['user'] 10 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class AccountConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'account' 7 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/account/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/account/edit.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Edit your account{% endblock %} 4 | 5 | {% block content %} 6 |

Edit your account

7 |

You can edit your account using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {{ profile_form.as_p }} 11 | {% csrf_token %} 12 |

13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/account/login.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Log-in{% endblock %} 4 | 5 | {% block content %} 6 |

Log-in

7 |

Please, use the following form to log-in:

8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/account/register.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Create an account{% endblock %} 4 | 5 | {% block content %} 6 |

Create an account

7 |

Please, sign up using the following form:

8 |
9 | {{ user_form.as_p }} 10 | {% csrf_token %} 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/account/register_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Welcome{% endblock %} 4 | 5 | {% block content %} 6 |

Welcome {{ new_user.first_name }}!

7 |

8 | Your account has been successfully created. 9 | Now you can log in. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |

8 | You have been successfully logged out. 9 | You can log-in again. 10 |

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_change_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password changed{% endblock %} 4 | 5 | {% block content %} 6 |

Password changed

7 |

Your password has been successfully changed.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_change_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Change your password{% endblock %} 4 | 5 | {% block content %} 6 |

Change your password

7 |

Use the form below to change your password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_reset_complete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Password reset{% endblock %} 4 | 5 | {% block content %} 6 |

Password set

7 |

Your password has been set. You can log in now

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_reset_done.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Reset your password

7 |

We've emailed you instructions for setting your password.

8 |

If you don't receive an email, please make sure you've entered the address you registered with.

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_reset_email.html: -------------------------------------------------------------------------------- 1 | Someone asked for password reset for email {{ email }}. Follow the link below: 2 | {{ protocol }}://{{ domain }}{% url "password_reset_confirm" uidb64=uid token=token %} 3 | Your username, in case you've forgotten: {{ user.get_username }} 4 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/templates/registration/password_reset_form.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Reset your password{% endblock %} 4 | 5 | {% block content %} 6 |

Forgotten your password?

7 |

Enter your e-mail address to obtain a new password.

8 |
9 | {{ form.as_p }} 10 |

11 | {% csrf_token %} 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/account/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/actions/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Action 4 | 5 | 6 | @admin.register(Action) 7 | class ActionAdmin(admin.ModelAdmin): 8 | list_display = ['user', 'verb', 'target', 'created'] 9 | list_filter = ['created'] 10 | search_fields = ['verb'] 11 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ActionsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'actions' 7 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/actions/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/actions/views.py: -------------------------------------------------------------------------------- 1 | # Create your views here. 2 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/bookmarks/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/bookmarks/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/bookmarks/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for bookmarks project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/bookmarks/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for bookmarks project. 3 | 4 | It exposes the WSGI callable as a module-level variable named ``application``. 5 | 6 | For more information on this file, see 7 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 8 | """ 9 | 10 | import os 11 | 12 | from django.core.wsgi import get_wsgi_application 13 | 14 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'bookmarks.settings') 15 | 16 | application = get_wsgi_application() 17 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/images/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Image 4 | 5 | 6 | @admin.register(Image) 7 | class ImageAdmin(admin.ModelAdmin): 8 | list_display = ['title', 'slug', 'image', 'created'] 9 | list_filter = ['created'] 10 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ImagesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'images' 7 | 8 | def ready(self): 9 | # import signal handlers 10 | import images.signals 11 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter07/bookmarks/images/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/signals.py: -------------------------------------------------------------------------------- 1 | from django.db.models.signals import m2m_changed 2 | from django.dispatch import receiver 3 | 4 | from .models import Image 5 | 6 | 7 | @receiver(m2m_changed, sender=Image.users_like.through) 8 | def users_like_changed(sender, instance, **kwargs): 9 | instance.total_likes = instance.users_like.count() 10 | instance.save() 11 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/templates/bookmarklet_launcher.js: -------------------------------------------------------------------------------- 1 | (function(){ 2 | if(!window.bookmarklet) { 3 | bookmarklet_js = document.body.appendChild(document.createElement('script')); 4 | bookmarklet_js.src = '//127.0.0.1:8000/static/js/bookmarklet.js?r='+Math.floor(Math.random()*9999999999999999); 5 | window.bookmarklet = true; 6 | } 7 | else { 8 | bookmarkletLaunch(); 9 | } 10 | })(); 11 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/templates/images/image/create.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Bookmark an image{% endblock %} 4 | 5 | {% block content %} 6 |

Bookmark an image

7 | 8 |
9 | {{ form.as_p }} 10 | {% csrf_token %} 11 | 12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/templates/images/image/ranking.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Images ranking{% endblock %} 4 | 5 | {% block content %} 6 |

Images ranking

7 |
    8 | {% for image in most_viewed %} 9 |
  1. 10 | 11 | {{ image.title }} 12 | 13 |
  2. 14 | {% endfor %} 15 |
16 | {% endblock %} 17 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter07/bookmarks/images/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'images' 6 | 7 | urlpatterns = [ 8 | path('create/', views.image_create, name='create'), 9 | path( 10 | 'detail///', 11 | views.image_detail, 12 | name='detail', 13 | ), 14 | path('like/', views.image_like, name='like'), 15 | path('', views.image_list, name='list'), 16 | path('ranking/', views.image_ranking, name='ranking'), 17 | ] 18 | -------------------------------------------------------------------------------- /Chapter07/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | python-decouple==3.8 6 | social-auth-app-django==5.4.0 7 | django-extensions==3.2.3 8 | werkzeug==3.0.2 9 | pyOpenSSL==24.1.0 10 | requests==2.31.0 11 | easy-thumbnails==2.8.5 12 | django-debug-toolbar==4.3.0 13 | redis==5.0.4 14 | -------------------------------------------------------------------------------- /Chapter08/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter08/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/myshop/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/myshop/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate 18 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/cart/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/cart/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CartConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'cart' 7 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/context_processors.py: -------------------------------------------------------------------------------- 1 | from .cart import Cart 2 | 3 | 4 | def cart(request): 5 | return {'cart': Cart(request)} 6 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)] 4 | 5 | 6 | class CartAddProductForm(forms.Form): 7 | quantity = forms.TypedChoiceField( 8 | choices=PRODUCT_QUANTITY_CHOICES, 9 | coerce=int 10 | ) 11 | override = forms.BooleanField( 12 | required=False, 13 | initial=False, 14 | widget=forms.HiddenInput 15 | ) 16 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/cart/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/cart/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter08/myshop/cart/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'cart' 6 | 7 | urlpatterns = [ 8 | path('', views.cart_detail, name='cart_detail'), 9 | path('add//', views.cart_add, name='cart_add'), 10 | path( 11 | 'remove//', 12 | views.cart_remove, 13 | name='cart_remove', 14 | ), 15 | ] 16 | -------------------------------------------------------------------------------- /Chapter08/myshop/myshop/__init__.py: -------------------------------------------------------------------------------- 1 | # import celery 2 | from .celery import app as celery_app 3 | 4 | __all__ = ['celery_app'] 5 | -------------------------------------------------------------------------------- /Chapter08/myshop/myshop/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for myshop project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter08/myshop/myshop/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | # set the default Django settings module for the 'celery' program. 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 7 | 8 | app = Celery('myshop') 9 | app.config_from_object('django.conf:settings', namespace='CELERY') 10 | app.autodiscover_tasks() 11 | -------------------------------------------------------------------------------- /Chapter08/myshop/myshop/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for myshop project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter08/myshop/orders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/orders/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/orders/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrdersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'orders' 7 | -------------------------------------------------------------------------------- /Chapter08/myshop/orders/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Order 4 | 5 | 6 | class OrderCreateForm(forms.ModelForm): 7 | class Meta: 8 | model = Order 9 | fields = [ 10 | 'first_name', 11 | 'last_name', 12 | 'email', 13 | 'address', 14 | 'postal_code', 15 | 'city', 16 | ] 17 | -------------------------------------------------------------------------------- /Chapter08/myshop/orders/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/orders/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/orders/templates/orders/order/created.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %} 4 | Thank you 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Thank you

9 |

Your order has been successfully completed. Your order number is 10 | {{ order.id }}.

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter08/myshop/orders/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter08/myshop/orders/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'orders' 7 | 8 | urlpatterns = [ 9 | path('create/', views.order_create, name='order_create'), 10 | ] 11 | -------------------------------------------------------------------------------- /Chapter08/myshop/shop/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/shop/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/shop/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ShopConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'shop' 7 | -------------------------------------------------------------------------------- /Chapter08/myshop/shop/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/shop/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter08/myshop/shop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter08/myshop/shop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter08/myshop/shop/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter08/myshop/shop/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'shop' 6 | 7 | urlpatterns = [ 8 | path('', views.product_list, name='product_list'), 9 | path( 10 | '/', 11 | views.product_list, 12 | name='product_list_by_category', 13 | ), 14 | path( 15 | '//', 16 | views.product_detail, 17 | name='product_detail', 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /Chapter08/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | flower==2.0.1 6 | celery==5.4.0 7 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/cart/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/cart/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CartConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'cart' 7 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/context_processors.py: -------------------------------------------------------------------------------- 1 | from .cart import Cart 2 | 3 | 4 | def cart(request): 5 | return {'cart': Cart(request)} 6 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)] 4 | 5 | 6 | class CartAddProductForm(forms.Form): 7 | quantity = forms.TypedChoiceField( 8 | choices=PRODUCT_QUANTITY_CHOICES, 9 | coerce=int 10 | ) 11 | override = forms.BooleanField( 12 | required=False, 13 | initial=False, 14 | widget=forms.HiddenInput 15 | ) 16 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/cart/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/cart/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/cart/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'cart' 6 | 7 | urlpatterns = [ 8 | path('', views.cart_detail, name='cart_detail'), 9 | path('add//', views.cart_add, name='cart_add'), 10 | path( 11 | 'remove//', 12 | views.cart_remove, 13 | name='cart_remove', 14 | ), 15 | ] 16 | -------------------------------------------------------------------------------- /Chapter09/myshop/myshop/__init__.py: -------------------------------------------------------------------------------- 1 | # import celery 2 | from .celery import app as celery_app 3 | 4 | __all__ = ['celery_app'] 5 | -------------------------------------------------------------------------------- /Chapter09/myshop/myshop/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for myshop project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter09/myshop/myshop/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | # set the default Django settings module for the 'celery' program. 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 7 | 8 | app = Celery('myshop') 9 | app.config_from_object('django.conf:settings', namespace='CELERY') 10 | app.autodiscover_tasks() 11 | -------------------------------------------------------------------------------- /Chapter09/myshop/myshop/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for myshop project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/orders/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/orders/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrdersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'orders' 7 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Order 4 | 5 | 6 | class OrderCreateForm(forms.ModelForm): 7 | class Meta: 8 | model = Order 9 | fields = [ 10 | 'first_name', 11 | 'last_name', 12 | 'email', 13 | 'address', 14 | 'postal_code', 15 | 'city', 16 | ] 17 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/migrations/0002_order_stripe_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('orders', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='order', 15 | name='stripe_id', 16 | field=models.CharField(blank=True, max_length=250), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/orders/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/orders/templates/orders/order/created.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %} 4 | Thank you 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Thank you

9 |

Your order has been successfully completed. Your order number is 10 | {{ order.id }}.

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/orders/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'orders' 7 | 8 | 9 | urlpatterns = [ 10 | path('create/', views.order_create, name='order_create'), 11 | path( 12 | 'admin/order//', 13 | views.admin_order_detail, 14 | name='admin_order_detail', 15 | ), 16 | path( 17 | 'admin/order//pdf/', 18 | views.admin_order_pdf, 19 | name='admin_order_pdf', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/payment/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/payment/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PaymentConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'payment' 7 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/payment/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/payment/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/templates/payment/canceled.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %}Payment canceled{% endblock %} 4 | 5 | {% block content %} 6 |

Your payment has not been processed

7 |

There was a problem processing your payment.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/templates/payment/completed.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %}Payment successful{% endblock %} 4 | 5 | {% block content %} 6 |

Your payment was successful

7 |

Your payment has been processed successfully.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/payment/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views, webhooks 4 | 5 | app_name = 'payment' 6 | 7 | urlpatterns = [ 8 | path('process/', views.payment_process, name='process'), 9 | path('completed/', views.payment_completed, name='completed'), 10 | path('canceled/', views.payment_canceled, name='canceled'), 11 | path('webhook/', webhooks.stripe_webhook, name='stripe-webhook'), 12 | ] 13 | -------------------------------------------------------------------------------- /Chapter09/myshop/shop/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/shop/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/shop/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ShopConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'shop' 7 | -------------------------------------------------------------------------------- /Chapter09/myshop/shop/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/shop/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter09/myshop/shop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/shop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter09/myshop/shop/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter09/myshop/shop/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'shop' 6 | 7 | urlpatterns = [ 8 | path('', views.product_list, name='product_list'), 9 | path( 10 | '/', 11 | views.product_list, 12 | name='product_list_by_category', 13 | ), 14 | path( 15 | '//', 16 | views.product_detail, 17 | name='product_detail', 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /Chapter09/myshop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter09/myshop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter09/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | flower==2.0.1 6 | celery==5.4.0 7 | stripe==9.3.0 8 | python-decouple==3.8 9 | WeasyPrint==61.2 -------------------------------------------------------------------------------- /Chapter10/myshop/cart/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/cart/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/cart/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CartConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'cart' 7 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/context_processors.py: -------------------------------------------------------------------------------- 1 | from .cart import Cart 2 | 3 | 4 | def cart(request): 5 | return {'cart': Cart(request)} 6 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | PRODUCT_QUANTITY_CHOICES = [(i, str(i)) for i in range(1, 21)] 4 | 5 | 6 | class CartAddProductForm(forms.Form): 7 | quantity = forms.TypedChoiceField( 8 | choices=PRODUCT_QUANTITY_CHOICES, 9 | coerce=int 10 | ) 11 | override = forms.BooleanField( 12 | required=False, 13 | initial=False, 14 | widget=forms.HiddenInput 15 | ) 16 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/cart/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/cart/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/cart/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'cart' 6 | 7 | urlpatterns = [ 8 | path('', views.cart_detail, name='cart_detail'), 9 | path('add//', views.cart_add, name='cart_add'), 10 | path( 11 | 'remove//', 12 | views.cart_remove, 13 | name='cart_remove', 14 | ), 15 | ] 16 | -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/coupons/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Coupon 4 | 5 | 6 | @admin.register(Coupon) 7 | class CouponAdmin(admin.ModelAdmin): 8 | list_display = [ 9 | 'code', 10 | 'valid_from', 11 | 'valid_to', 12 | 'discount', 13 | 'active', 14 | ] 15 | list_filter = ['active', 'valid_from', 'valid_to'] 16 | search_fields = ['code'] 17 | -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CouponsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'coupons' 7 | -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | 4 | class CouponApplyForm(forms.Form): 5 | code = forms.CharField() 6 | -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/coupons/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/coupons/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'coupons' 6 | 7 | urlpatterns = [ 8 | path('apply/', views.coupon_apply, name='apply'), 9 | ] 10 | -------------------------------------------------------------------------------- /Chapter10/myshop/myshop/__init__.py: -------------------------------------------------------------------------------- 1 | # import celery 2 | from .celery import app as celery_app 3 | 4 | __all__ = ['celery_app'] 5 | -------------------------------------------------------------------------------- /Chapter10/myshop/myshop/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for myshop project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter10/myshop/myshop/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | # set the default Django settings module for the 'celery' program. 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 7 | 8 | app = Celery('myshop') 9 | app.config_from_object('django.conf:settings', namespace='CELERY') 10 | app.autodiscover_tasks() 11 | -------------------------------------------------------------------------------- /Chapter10/myshop/myshop/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for myshop project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/orders/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/orders/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrdersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'orders' 7 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from .models import Order 4 | 5 | 6 | class OrderCreateForm(forms.ModelForm): 7 | class Meta: 8 | model = Order 9 | fields = [ 10 | 'first_name', 11 | 'last_name', 12 | 'email', 13 | 'address', 14 | 'postal_code', 15 | 'city', 16 | ] 17 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/migrations/0002_order_stripe_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('orders', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='order', 15 | name='stripe_id', 16 | field=models.CharField(blank=True, max_length=250), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/orders/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/orders/templates/orders/order/created.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %} 4 | Thank you 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Thank you

9 |

Your order has been successfully completed. Your order number is 10 | {{ order.id }}.

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/orders/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'orders' 7 | 8 | 9 | urlpatterns = [ 10 | path('create/', views.order_create, name='order_create'), 11 | path( 12 | 'admin/order//', 13 | views.admin_order_detail, 14 | name='admin_order_detail', 15 | ), 16 | path( 17 | 'admin/order//pdf/', 18 | views.admin_order_pdf, 19 | name='admin_order_pdf', 20 | ), 21 | ] 22 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/payment/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/payment/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PaymentConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'payment' 7 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/payment/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/payment/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/templates/payment/canceled.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %}Payment canceled{% endblock %} 4 | 5 | {% block content %} 6 |

Your payment has not been processed

7 |

There was a problem processing your payment.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/templates/payment/completed.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %}Payment successful{% endblock %} 4 | 5 | {% block content %} 6 |

Your payment was successful

7 |

Your payment has been processed successfully.

8 | {% endblock %} 9 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/payment/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views, webhooks 4 | 5 | app_name = 'payment' 6 | 7 | urlpatterns = [ 8 | path('process/', views.payment_process, name='process'), 9 | path('completed/', views.payment_completed, name='completed'), 10 | path('canceled/', views.payment_canceled, name='canceled'), 11 | path('webhook/', webhooks.stripe_webhook, name='stripe-webhook'), 12 | ] 13 | -------------------------------------------------------------------------------- /Chapter10/myshop/shop/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/shop/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/shop/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ShopConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'shop' 7 | -------------------------------------------------------------------------------- /Chapter10/myshop/shop/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/shop/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter10/myshop/shop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/shop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter10/myshop/shop/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter10/myshop/shop/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'shop' 6 | 7 | urlpatterns = [ 8 | path('', views.product_list, name='product_list'), 9 | path( 10 | '/', 11 | views.product_list, 12 | name='product_list_by_category', 13 | ), 14 | path( 15 | '//', 16 | views.product_detail, 17 | name='product_detail', 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /Chapter10/myshop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter10/myshop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter10/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | flower==2.0.1 6 | celery==5.4.0 7 | stripe==9.3.0 8 | python-decouple==3.8 9 | WeasyPrint==61.2 10 | redis==5.0.4 11 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/cart/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/cart/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CartConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'cart' 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/context_processors.py: -------------------------------------------------------------------------------- 1 | from .cart import Cart 2 | 3 | 4 | def cart(request): 5 | return {'cart': Cart(request)} 6 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/cart/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/cart/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/cart/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'cart' 6 | 7 | urlpatterns = [ 8 | path('', views.cart_detail, name='cart_detail'), 9 | path('add//', views.cart_add, name='cart_add'), 10 | path( 11 | 'remove//', 12 | views.cart_remove, 13 | name='cart_remove', 14 | ), 15 | ] 16 | -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/coupons/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from .models import Coupon 4 | 5 | 6 | @admin.register(Coupon) 7 | class CouponAdmin(admin.ModelAdmin): 8 | list_display = [ 9 | 'code', 10 | 'valid_from', 11 | 'valid_to', 12 | 'discount', 13 | 'active', 14 | ] 15 | list_filter = ['active', 'valid_from', 'valid_to'] 16 | search_fields = ['code'] 17 | -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CouponsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'coupons' 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from django.utils.translation import gettext_lazy as _ 3 | 4 | 5 | class CouponApplyForm(forms.Form): 6 | code = forms.CharField(label=_('Coupon')) 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/coupons/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/coupons/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'coupons' 6 | 7 | urlpatterns = [ 8 | path('apply/', views.coupon_apply, name='apply'), 9 | ] 10 | -------------------------------------------------------------------------------- /Chapter11/myshop/myshop/__init__.py: -------------------------------------------------------------------------------- 1 | # import celery 2 | from .celery import app as celery_app 3 | 4 | __all__ = ['celery_app'] 5 | -------------------------------------------------------------------------------- /Chapter11/myshop/myshop/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for myshop project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter11/myshop/myshop/celery.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | from celery import Celery 4 | 5 | # set the default Django settings module for the 'celery' program. 6 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 7 | 8 | app = Celery('myshop') 9 | app.config_from_object('django.conf:settings', namespace='CELERY') 10 | app.autodiscover_tasks() 11 | -------------------------------------------------------------------------------- /Chapter11/myshop/myshop/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for myshop project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'myshop.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter11/myshop/orders/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/orders/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/orders/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class OrdersConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'orders' 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/orders/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | from localflavor.us.forms import USZipCodeField 3 | 4 | from .models import Order 5 | 6 | 7 | class OrderCreateForm(forms.ModelForm): 8 | postal_code = USZipCodeField() 9 | 10 | class Meta: 11 | model = Order 12 | fields = [ 13 | 'first_name', 14 | 'last_name', 15 | 'email', 16 | 'address', 17 | 'postal_code', 18 | 'city', 19 | ] 20 | -------------------------------------------------------------------------------- /Chapter11/myshop/orders/migrations/0002_order_stripe_id.py: -------------------------------------------------------------------------------- 1 | # Generated by Django 5.0.4 on 2024-04-04 18:44 2 | 3 | from django.db import migrations, models 4 | 5 | 6 | class Migration(migrations.Migration): 7 | 8 | dependencies = [ 9 | ('orders', '0001_initial'), 10 | ] 11 | 12 | operations = [ 13 | migrations.AddField( 14 | model_name='order', 15 | name='stripe_id', 16 | field=models.CharField(blank=True, max_length=250), 17 | ), 18 | ] 19 | -------------------------------------------------------------------------------- /Chapter11/myshop/orders/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/orders/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/orders/templates/orders/order/created.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | 3 | {% block title %} 4 | Thank you 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Thank you

9 |

Your order has been successfully completed. Your order number is 10 | {{ order.id }}.

11 | {% endblock %} 12 | -------------------------------------------------------------------------------- /Chapter11/myshop/orders/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/payment/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/payment/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class PaymentConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'payment' 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/payment/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/payment/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/templates/payment/canceled.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %}{% translate "Payment canceled" %}{% endblock %} 5 | 6 | {% block content %} 7 |

{% translate "Your payment has not been processed" %}

8 |

{% translate "There was a problem processing your payment." %}

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/templates/payment/completed.html: -------------------------------------------------------------------------------- 1 | {% extends "shop/base.html" %} 2 | {% load i18n %} 3 | 4 | {% block title %}{% translate "Payment successful" %}{% endblock %} 5 | 6 | {% block content %} 7 |

{% translate "Your payment was successful" %}

8 |

{% translate "Your payment has been processed successfully." %}

9 | {% endblock %} 10 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/payment/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | from django.utils.translation import gettext_lazy as _ 3 | 4 | from . import views 5 | 6 | app_name = 'payment' 7 | 8 | urlpatterns = [ 9 | path(_('process/'), views.payment_process, name='process'), 10 | path(_('completed/'), views.payment_completed, name='completed'), 11 | path(_('canceled/'), views.payment_canceled, name='canceled'), 12 | ] 13 | -------------------------------------------------------------------------------- /Chapter11/myshop/shop/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/shop/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/shop/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ShopConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'shop' 7 | -------------------------------------------------------------------------------- /Chapter11/myshop/shop/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/shop/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter11/myshop/shop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/shop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter11/myshop/shop/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter11/myshop/shop/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | app_name = 'shop' 6 | 7 | urlpatterns = [ 8 | path('', views.product_list, name='product_list'), 9 | path( 10 | '/', 11 | views.product_list, 12 | name='product_list_by_category', 13 | ), 14 | path( 15 | '//', 16 | views.product_detail, 17 | name='product_detail', 18 | ), 19 | ] 20 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/icon_searchbox_rosetta.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/static/admin/img/icon_searchbox_rosetta.png -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /Chapter11/myshop/static/img/no_image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter11/myshop/static/img/no_image.png -------------------------------------------------------------------------------- /Chapter11/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | flower==2.0.1 6 | celery==5.4.0 7 | stripe==9.3.0 8 | python-decouple==3.8 9 | WeasyPrint==61.2 10 | redis==5.0.4 11 | django-rosetta==0.10.0 12 | django-parler==2.3 13 | django-localflavor==4.0 14 | -------------------------------------------------------------------------------- /Chapter12/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter12/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/educa/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/educa/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate 18 | -------------------------------------------------------------------------------- /Chapter12/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter12/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter12/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter12/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter12/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter12/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter12/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter12/educa/courses/views.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your views here. 3 | -------------------------------------------------------------------------------- /Chapter12/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter12/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter12/educa/educa/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for educa project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter12/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter12/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | -------------------------------------------------------------------------------- /Chapter13/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter13/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | web: 3 | build: . 4 | volumes: 5 | - .:/code 6 | web_migrate: 7 | extends: 8 | service: web 9 | command: python /code/educa/manage.py migrate 10 | web_run: 11 | extends: 12 | service: web 13 | command: python /code/educa/manage.py runserver 0.0.0.0:8000 14 | ports: 15 | - "8000:8000" 16 | depends_on: 17 | - web_migrate 18 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter13/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter13/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms.models import inlineformset_factory 2 | 3 | from .models import Course, Module 4 | 5 | ModuleFormSet = inlineformset_factory( 6 | Course, 7 | Module, 8 | fields=['title', 'description'], 9 | extra=2, 10 | can_delete=True, 11 | ) 12 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter13/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter13/educa/courses/templates/courses/manage/course/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Delete course{% endblock %} 4 | 5 | {% block content %} 6 |

Delete course "{{ object.title }}"

7 |
8 |
9 | {% csrf_token %} 10 |

Are you sure you want to delete "{{ object }}"?

11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/templates/courses/manage/module/formset.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Edit "{{ course.title }}" 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Edit "{{ course.title }}"

9 |
10 |

Course modules

11 |
12 | {{ formset }} 13 | {{ formset.management_form }} 14 | {% csrf_token %} 15 | 16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter13/educa/courses/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter13/educa/courses/templatetags/course.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def model_name(obj): 8 | try: 9 | return obj._meta.model_name 10 | except AttributeError: 11 | return None 12 | -------------------------------------------------------------------------------- /Chapter13/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter13/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter13/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter13/educa/educa/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for educa project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter13/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter13/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | django-braces==1.15.0 6 | -------------------------------------------------------------------------------- /Chapter14/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter14/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms.models import inlineformset_factory 2 | 3 | from .models import Course, Module 4 | 5 | ModuleFormSet = inlineformset_factory( 6 | Course, 7 | Module, 8 | fields=['title', 'description'], 9 | extra=2, 10 | can_delete=True, 11 | ) 12 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/content/file.html: -------------------------------------------------------------------------------- 1 |

2 | Download file 3 |

4 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/content/image.html: -------------------------------------------------------------------------------- 1 |

2 | {{ item.title }} 3 |

4 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/content/text.html: -------------------------------------------------------------------------------- 1 | {{ item.content|linebreaks }} 2 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/content/video.html: -------------------------------------------------------------------------------- 1 | {% load embed_video_tags %} 2 | {% video item.url "small" %} 3 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/manage/course/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Delete course{% endblock %} 4 | 5 | {% block content %} 6 |

Delete course "{{ object.title }}"

7 |
8 |
9 | {% csrf_token %} 10 |

Are you sure you want to delete "{{ object }}"?

11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/courses/manage/module/formset.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Edit "{{ course.title }}" 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

Edit "{{ course.title }}"

9 |
10 |

Course modules

11 |
12 | {{ formset }} 13 | {{ formset.management_form }} 14 | {% csrf_token %} 15 | 16 |
17 |
18 | {% endblock %} 19 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/courses/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/courses/templatetags/course.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def model_name(obj): 8 | try: 9 | return obj._meta.model_name 10 | except AttributeError: 11 | return None 12 | -------------------------------------------------------------------------------- /Chapter14/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter14/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/educa/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for educa project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter14/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter14/educa/students/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/students/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/students/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter14/educa/students/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class StudentsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'students' 7 | -------------------------------------------------------------------------------- /Chapter14/educa/students/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from courses.models import Course 4 | 5 | 6 | class CourseEnrollForm(forms.Form): 7 | course = forms.ModelChoiceField( 8 | queryset=Course.objects.none(), 9 | widget=forms.HiddenInput 10 | ) 11 | 12 | def __init__(self, *args, **kwargs): 13 | super(CourseEnrollForm, self).__init__(*args, **kwargs) 14 | self.fields['course'].queryset = Course.objects.all() 15 | -------------------------------------------------------------------------------- /Chapter14/educa/students/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter14/educa/students/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter14/educa/students/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter14/educa/students/templates/students/student/registration.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Sign up 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

9 | Sign up 10 |

11 |
12 |

Enter your details to create an account:

13 |
14 | {{ form.as_p }} 15 | {% csrf_token %} 16 |

17 |
18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /Chapter14/educa/students/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter14/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | django-braces==1.15.0 6 | django-embed-video==1.4.9 7 | pymemcache==4.0.0 8 | django-debug-toolbar==4.3.0 9 | redis==5.0.4 10 | django-redisboard==8.4.0 11 | -------------------------------------------------------------------------------- /Chapter15/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter15/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/courses/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/courses/api/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/courses/api/pagination.py: -------------------------------------------------------------------------------- 1 | from rest_framework.pagination import PageNumberPagination 2 | 3 | 4 | class StandardPagination(PageNumberPagination): 5 | page_size = 10 6 | page_size_query_param = 'page_size' 7 | max_page_size = 50 8 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/api/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import BasePermission 2 | 3 | 4 | class IsEnrolled(BasePermission): 5 | def has_object_permission(self, request, view, obj): 6 | return obj.students.filter(id=request.user.id).exists() 7 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms.models import inlineformset_factory 2 | 3 | from .models import Course, Module 4 | 5 | ModuleFormSet = inlineformset_factory( 6 | Course, 7 | Module, 8 | fields=['title', 'description'], 9 | extra=2, 10 | can_delete=True, 11 | ) 12 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/courses/content/file.html: -------------------------------------------------------------------------------- 1 |

2 | Download file 3 |

4 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/courses/content/image.html: -------------------------------------------------------------------------------- 1 |

2 | {{ item.title }} 3 |

4 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/courses/content/text.html: -------------------------------------------------------------------------------- 1 | {{ item.content|linebreaks }} 2 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/courses/content/video.html: -------------------------------------------------------------------------------- 1 | {% load embed_video_tags %} 2 | {% video item.url "small" %} 3 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/courses/manage/course/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Delete course{% endblock %} 4 | 5 | {% block content %} 6 |

Delete course "{{ object.title }}"

7 |
8 |
9 | {% csrf_token %} 10 |

Are you sure you want to delete "{{ object }}"?

11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/courses/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/courses/templatetags/course.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def model_name(obj): 8 | try: 9 | return obj._meta.model_name 10 | except AttributeError: 11 | return None 12 | -------------------------------------------------------------------------------- /Chapter15/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter15/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/educa/asgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | ASGI config for educa project. 3 | 4 | It exposes the ASGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.asgi import get_asgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_asgi_application() 18 | -------------------------------------------------------------------------------- /Chapter15/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter15/educa/students/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/students/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/students/admin.py: -------------------------------------------------------------------------------- 1 | # Register your models here. 2 | -------------------------------------------------------------------------------- /Chapter15/educa/students/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class StudentsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'students' 7 | -------------------------------------------------------------------------------- /Chapter15/educa/students/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from courses.models import Course 4 | 5 | 6 | class CourseEnrollForm(forms.Form): 7 | course = forms.ModelChoiceField( 8 | queryset=Course.objects.none(), 9 | widget=forms.HiddenInput 10 | ) 11 | 12 | def __init__(self, *args, **kwargs): 13 | super(CourseEnrollForm, self).__init__(*args, **kwargs) 14 | self.fields['course'].queryset = Course.objects.all() 15 | -------------------------------------------------------------------------------- /Chapter15/educa/students/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter15/educa/students/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter15/educa/students/models.py: -------------------------------------------------------------------------------- 1 | # Create your models here. 2 | -------------------------------------------------------------------------------- /Chapter15/educa/students/templates/students/student/registration.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Sign up 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

9 | Sign up 10 |

11 |
12 |

Enter your details to create an account:

13 |
14 | {{ form.as_p }} 15 | {% csrf_token %} 16 |

17 |
18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /Chapter15/educa/students/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter15/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | Pillow==10.3.0 4 | sqlparse==0.5.0 5 | django-braces==1.15.0 6 | django-embed-video==1.4.9 7 | pymemcache==4.0.0 8 | django-debug-toolbar==4.3.0 9 | redis==5.0.4 10 | django-redisboard==8.4.0 11 | djangorestframework==3.15.1 12 | requests==2.31.0 13 | -------------------------------------------------------------------------------- /Chapter16/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM python:3.12.3-slim 2 | 3 | RUN apt-get update -qq \ 4 | && rm -rf /var/lib/apt/lists/* 5 | 6 | # Set environment variables 7 | ENV PIP_DISABLE_PIP_VERSION_CHECK 1 8 | ENV PYTHONDONTWRITEBYTECODE 1 9 | ENV PYTHONUNBUFFERED 1 10 | 11 | WORKDIR /code 12 | 13 | COPY requirements.txt . 14 | RUN python -m pip install -r requirements.txt 15 | RUN python -m pip install psycopg[binary] 16 | 17 | COPY . . -------------------------------------------------------------------------------- /Chapter16/educa/chat/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/chat/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/chat/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from chat.models import Message 4 | 5 | 6 | @admin.register(Message) 7 | class MessageAdmin(admin.ModelAdmin): 8 | list_display = ['sent_on', 'user', 'course', 'content'] 9 | list_filter = ['sent_on', 'course'] 10 | search_fields = ['content'] 11 | raw_id_fields = ['user', 'course'] 12 | -------------------------------------------------------------------------------- /Chapter16/educa/chat/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ChatConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'chat' 7 | -------------------------------------------------------------------------------- /Chapter16/educa/chat/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/chat/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/chat/routing.py: -------------------------------------------------------------------------------- 1 | from django.urls import re_path 2 | 3 | from . import consumers 4 | 5 | 6 | websocket_urlpatterns = [ 7 | re_path( 8 | r'ws/chat/room/(?P\d+)/$', 9 | consumers.ChatConsumer.as_asgi(), 10 | ), 11 | ] 12 | -------------------------------------------------------------------------------- /Chapter16/educa/chat/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter16/educa/chat/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'chat' 7 | 8 | urlpatterns = [ 9 | path( 10 | 'room//', 11 | views.course_chat_room, 12 | name='course_chat_room', 13 | ), 14 | ] 15 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/courses/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/courses/api/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/courses/api/pagination.py: -------------------------------------------------------------------------------- 1 | from rest_framework.pagination import PageNumberPagination 2 | 3 | 4 | class StandardPagination(PageNumberPagination): 5 | page_size = 10 6 | page_size_query_param = 'page_size' 7 | max_page_size = 50 8 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/api/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import BasePermission 2 | 3 | 4 | class IsEnrolled(BasePermission): 5 | def has_object_permission(self, request, view, obj): 6 | return obj.students.filter(id=request.user.id).exists() 7 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms.models import inlineformset_factory 2 | 3 | from .models import Course, Module 4 | 5 | ModuleFormSet = inlineformset_factory( 6 | Course, 7 | Module, 8 | fields=['title', 'description'], 9 | extra=2, 10 | can_delete=True, 11 | ) 12 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/courses/content/file.html: -------------------------------------------------------------------------------- 1 |

2 | Download file 3 |

4 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/courses/content/image.html: -------------------------------------------------------------------------------- 1 |

2 | {{ item.title }} 3 |

4 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/courses/content/text.html: -------------------------------------------------------------------------------- 1 | {{ item.content|linebreaks }} 2 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/courses/content/video.html: -------------------------------------------------------------------------------- 1 | {% load embed_video_tags %} 2 | {% video item.url "small" %} 3 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/courses/manage/course/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Delete course{% endblock %} 4 | 5 | {% block content %} 6 |

Delete course "{{ object.title }}"

7 |
8 |
9 | {% csrf_token %} 10 |

Are you sure you want to delete "{{ object }}"?

11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/courses/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/courses/templatetags/course.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def model_name(obj): 8 | try: 9 | return obj._meta.model_name 10 | except AttributeError: 11 | return None 12 | -------------------------------------------------------------------------------- /Chapter16/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter16/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter16/educa/students/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/students/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/students/admin.py: -------------------------------------------------------------------------------- 1 | # Register your models here. 2 | -------------------------------------------------------------------------------- /Chapter16/educa/students/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class StudentsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'students' 7 | -------------------------------------------------------------------------------- /Chapter16/educa/students/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from courses.models import Course 4 | 5 | 6 | class CourseEnrollForm(forms.Form): 7 | course = forms.ModelChoiceField( 8 | queryset=Course.objects.none(), 9 | widget=forms.HiddenInput 10 | ) 11 | 12 | def __init__(self, *args, **kwargs): 13 | super(CourseEnrollForm, self).__init__(*args, **kwargs) 14 | self.fields['course'].queryset = Course.objects.all() 15 | -------------------------------------------------------------------------------- /Chapter16/educa/students/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter16/educa/students/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter16/educa/students/models.py: -------------------------------------------------------------------------------- 1 | # Create your models here. 2 | -------------------------------------------------------------------------------- /Chapter16/educa/students/templates/students/student/registration.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Sign up 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

9 | Sign up 10 |

11 |
12 |

Enter your details to create an account:

13 |
14 | {{ form.as_p }} 15 | {% csrf_token %} 16 |

17 |
18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /Chapter16/educa/students/tests.py: -------------------------------------------------------------------------------- 1 | # Create your tests here. 2 | -------------------------------------------------------------------------------- /Chapter16/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.7.2 2 | Django~=5.0.4 3 | sqlparse==0.5.0 4 | Pillow==10.3.0 5 | django-braces==1.15.0 6 | django-embed-video==1.4.9 7 | pymemcache==4.0.0 8 | django-debug-toolbar==4.3.0 9 | redis==5.0.4 10 | django-redisboard==8.4.0 11 | djangorestframework==3.15.1 12 | requests==2.31.0 13 | channels[daphne]==4.1.0 14 | channels-redis==4.2.0 15 | -------------------------------------------------------------------------------- /Chapter17/Dockerfile: -------------------------------------------------------------------------------- 1 | # Pull official base Python Docker image 2 | FROM python:3.12.3 3 | 4 | # Set environment variables 5 | ENV PYTHONDONTWRITEBYTECODE=1 6 | ENV PYTHONUNBUFFERED=1 7 | 8 | # Set work directory 9 | WORKDIR /code 10 | 11 | # Install dependencies 12 | RUN pip install --upgrade pip 13 | COPY requirements.txt . 14 | RUN pip install -r requirements.txt 15 | 16 | # Copy the Django project 17 | COPY . . 18 | -------------------------------------------------------------------------------- /Chapter17/config/uwsgi/uwsgi.ini: -------------------------------------------------------------------------------- 1 | [uwsgi] 2 | socket=/code/educa/uwsgi_app.sock 3 | chdir = /code/educa/ 4 | module=educa.wsgi:application 5 | master=true 6 | chmod-socket=666 7 | uid=www-data 8 | gid=www-data 9 | vacuum=true 10 | -------------------------------------------------------------------------------- /Chapter17/educa/chat/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/chat/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/chat/admin.py: -------------------------------------------------------------------------------- 1 | from django.contrib import admin 2 | 3 | from chat.models import Message 4 | 5 | 6 | @admin.register(Message) 7 | class MessageAdmin(admin.ModelAdmin): 8 | list_display = ['sent_on', 'user', 'course', 'content'] 9 | list_filter = ['sent_on', 'course'] 10 | search_fields = ['content'] 11 | raw_id_fields = ['user', 'course'] 12 | -------------------------------------------------------------------------------- /Chapter17/educa/chat/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class ChatConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'chat' 7 | -------------------------------------------------------------------------------- /Chapter17/educa/chat/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/chat/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/chat/routing.py: -------------------------------------------------------------------------------- 1 | from django.urls import re_path 2 | 3 | from . import consumers 4 | 5 | 6 | websocket_urlpatterns = [ 7 | re_path( 8 | r'ws/chat/room/(?P\d+)/$', 9 | consumers.ChatConsumer.as_asgi(), 10 | ), 11 | ] 12 | -------------------------------------------------------------------------------- /Chapter17/educa/chat/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter17/educa/chat/urls.py: -------------------------------------------------------------------------------- 1 | from django.urls import path 2 | 3 | from . import views 4 | 5 | 6 | app_name = 'chat' 7 | 8 | urlpatterns = [ 9 | path( 10 | 'room//', 11 | views.course_chat_room, 12 | name='course_chat_room', 13 | ), 14 | ] 15 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/courses/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/courses/api/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/courses/api/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/courses/api/pagination.py: -------------------------------------------------------------------------------- 1 | from rest_framework.pagination import PageNumberPagination 2 | 3 | 4 | class StandardPagination(PageNumberPagination): 5 | page_size = 10 6 | page_size_query_param = 'page_size' 7 | max_page_size = 50 8 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/api/permissions.py: -------------------------------------------------------------------------------- 1 | from rest_framework.permissions import BasePermission 2 | 3 | 4 | class IsEnrolled(BasePermission): 5 | def has_object_permission(self, request, view, obj): 6 | return obj.students.filter(id=request.user.id).exists() 7 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class CoursesConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'courses' 7 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/forms.py: -------------------------------------------------------------------------------- 1 | from django.forms.models import inlineformset_factory 2 | 3 | from .models import Course, Module 4 | 5 | ModuleFormSet = inlineformset_factory( 6 | Course, 7 | Module, 8 | fields=['title', 'description'], 9 | extra=2, 10 | can_delete=True, 11 | ) 12 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/courses/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/courses/content/file.html: -------------------------------------------------------------------------------- 1 |

2 | Download file 3 |

4 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/courses/content/image.html: -------------------------------------------------------------------------------- 1 |

2 | {{ item.title }} 3 |

4 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/courses/content/text.html: -------------------------------------------------------------------------------- 1 | {{ item.content|linebreaks }} 2 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/courses/content/video.html: -------------------------------------------------------------------------------- 1 | {% load embed_video_tags %} 2 | {% video item.url "small" %} 3 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/courses/manage/course/delete.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Delete course{% endblock %} 4 | 5 | {% block content %} 6 |

Delete course "{{ object.title }}"

7 |
8 |
9 | {% csrf_token %} 10 |

Are you sure you want to delete "{{ object }}"?

11 | 12 |
13 |
14 | {% endblock %} 15 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templates/registration/logged_out.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %}Logged out{% endblock %} 4 | 5 | {% block content %} 6 |

Logged out

7 |
8 |

9 | You have been successfully logged out. 10 | You can log-in again. 11 |

12 |
13 | {% endblock %} 14 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/templatetags/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/courses/templatetags/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/courses/templatetags/course.py: -------------------------------------------------------------------------------- 1 | from django import template 2 | 3 | register = template.Library() 4 | 5 | 6 | @register.filter 7 | def model_name(obj): 8 | try: 9 | return obj._meta.model_name 10 | except AttributeError: 11 | return None 12 | -------------------------------------------------------------------------------- /Chapter17/educa/courses/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter17/educa/educa/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/educa/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/educa/settings/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/educa/settings/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/educa/settings/local.py: -------------------------------------------------------------------------------- 1 | from .base import * 2 | 3 | DEBUG = True 4 | 5 | DATABASES = { 6 | 'default': { 7 | 'ENGINE': 'django.db.backends.sqlite3', 8 | 'NAME': BASE_DIR / 'db.sqlite3', 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /Chapter17/educa/educa/wsgi.py: -------------------------------------------------------------------------------- 1 | """ 2 | WSGI config for educa project. 3 | 4 | It exposes the WSGI callable as a module-level variable named 5 | ``application``. 6 | 7 | For more information on this file, see 8 | https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/ 9 | """ 10 | 11 | import os 12 | 13 | from django.core.wsgi import get_wsgi_application 14 | 15 | os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'educa.settings') 16 | 17 | application = get_wsgi_application() 18 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/fonts/README.txt: -------------------------------------------------------------------------------- 1 | Roboto webfont source: https://www.google.com/fonts/specimen/Roboto 2 | WOFF files extracted using https://github.com/majodev/google-webfonts-helper 3 | Weights used in this project: Light (300), Regular (400), Bold (700) 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/fonts/Roboto-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/admin/fonts/Roboto-Bold-webfont.woff -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/fonts/Roboto-Light-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/admin/fonts/Roboto-Light-webfont.woff -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/fonts/Roboto-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/admin/fonts/Roboto-Regular-webfont.woff -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/README.txt: -------------------------------------------------------------------------------- 1 | All icons are taken from Font Awesome (http://fontawesome.io/) project. 2 | The Font Awesome font is licensed under the SIL OFL 1.1: 3 | - https://scripts.sil.org/OFL 4 | 5 | SVG icons source: https://github.com/encharm/Font-Awesome-SVG-PNG 6 | Font-Awesome-SVG-PNG is licensed under the MIT license (see file license 7 | in current folder). 8 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/icon-addlink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/icon-changelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/icon-deletelink.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/icon-yes.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/search.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/tooltag-add.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/img/tooltag-arrowright.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/admin/js/jquery.init.js: -------------------------------------------------------------------------------- 1 | /*global jQuery:false*/ 2 | 'use strict'; 3 | /* Puts the included jQuery into our own namespace using noConflict and passing 4 | * it 'true'. This ensures that the included jQuery doesn't pollute the global 5 | * namespace (i.e. this preserves pre-existing values for both window.$ and 6 | * window.jQuery). 7 | */ 8 | window.django = {jQuery: jQuery.noConflict(true)}; 9 | -------------------------------------------------------------------------------- /Chapter17/educa/static/debug_toolbar/css/print.css: -------------------------------------------------------------------------------- 1 | #djDebug { 2 | display: none !important; 3 | } 4 | -------------------------------------------------------------------------------- /Chapter17/educa/static/debug_toolbar/js/redirect.js: -------------------------------------------------------------------------------- 1 | document.getElementById("redirect_to").focus(); 2 | -------------------------------------------------------------------------------- /Chapter17/educa/static/redisboard/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/redisboard/favicon.ico -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/docs/img/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/docs/img/favicon.ico -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/docs/img/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/docs/img/grid.png -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.eot -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.ttf -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/fontawesome-webfont.woff -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/img/glyphicons-halflings-white.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/img/glyphicons-halflings-white.png -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/img/glyphicons-halflings.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/img/glyphicons-halflings.png -------------------------------------------------------------------------------- /Chapter17/educa/static/rest_framework/img/grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/static/rest_framework/img/grid.png -------------------------------------------------------------------------------- /Chapter17/educa/students/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/students/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/students/admin.py: -------------------------------------------------------------------------------- 1 | 2 | # Register your models here. 3 | -------------------------------------------------------------------------------- /Chapter17/educa/students/apps.py: -------------------------------------------------------------------------------- 1 | from django.apps import AppConfig 2 | 3 | 4 | class StudentsConfig(AppConfig): 5 | default_auto_field = 'django.db.models.BigAutoField' 6 | name = 'students' 7 | -------------------------------------------------------------------------------- /Chapter17/educa/students/forms.py: -------------------------------------------------------------------------------- 1 | from django import forms 2 | 3 | from courses.models import Course 4 | 5 | 6 | class CourseEnrollForm(forms.Form): 7 | course = forms.ModelChoiceField( 8 | queryset=Course.objects.none(), 9 | widget=forms.HiddenInput 10 | ) 11 | 12 | def __init__(self, *args, **kwargs): 13 | super(CourseEnrollForm, self).__init__(*args, **kwargs) 14 | self.fields['course'].queryset = Course.objects.all() 15 | -------------------------------------------------------------------------------- /Chapter17/educa/students/management/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/students/management/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/students/management/commands/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/students/management/commands/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/students/migrations/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PacktPublishing/Django-5-By-Example/a4c1e4e917c7f68472bf575ef7bf3cf096e7e8e1/Chapter17/educa/students/migrations/__init__.py -------------------------------------------------------------------------------- /Chapter17/educa/students/models.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your models here. 3 | -------------------------------------------------------------------------------- /Chapter17/educa/students/templates/students/student/registration.html: -------------------------------------------------------------------------------- 1 | {% extends "base.html" %} 2 | 3 | {% block title %} 4 | Sign up 5 | {% endblock %} 6 | 7 | {% block content %} 8 |

9 | Sign up 10 |

11 |
12 |

Enter your details to create an account:

13 |
14 | {{ form.as_p }} 15 | {% csrf_token %} 16 |

17 |
18 |
19 | {% endblock %} 20 | -------------------------------------------------------------------------------- /Chapter17/educa/students/tests.py: -------------------------------------------------------------------------------- 1 | 2 | # Create your tests here. 3 | -------------------------------------------------------------------------------- /Chapter17/requirements.txt: -------------------------------------------------------------------------------- 1 | asgiref==3.8.1 2 | Django~=5.0.4 3 | Pillow==10.3.0 4 | sqlparse==0.5.0 5 | django-braces==1.15.0 6 | django-embed-video==1.4.9 7 | pymemcache==4.0.0 8 | django-debug-toolbar==4.3.0 9 | redis==5.0.4 10 | django-redisboard==8.4.0 11 | djangorestframework==3.15.1 12 | requests==2.31.0 13 | channels[daphne]==4.1.0 14 | channels-redis==4.2.0 15 | psycopg==3.1.18 16 | uwsgi==2.0.25.1 17 | python-decouple==3.8 18 | --------------------------------------------------------------------------------