SlideShare a Scribd company logo
1 of 62
Сергей Бурма
#kranonit e20
Обо мне
● использую Python в своих корыстных и не
очень целях уже пятый год;
● поучаствовал в нескольких больших
незапустившихся проектах;
● приложил руку к сайтам wokifood.ru,
dewote.com, biz-translate.com;
● изредка пишу на хабр (ник batment).
О чем вы сегодня узнаете
● немного о Python;
● много о фреймворке Django;
● о том как сделать очень простой
интернет-магазин с админкой.
Особенности Python
● приоритет на читаемость;
● данные бывают изменяемые и
неизменяемые (mutable, immutable)
● жесткие стандарты оформления кода;
● любая сущность - это объект;
● очень своеобразное ООП;
● магические методы.
Дисклеймер
● мы используем Python 3;
● код представлен максимально наглядно,
но в нем скорее всего есть неувязки и
ошибки, будьте осторожны.
Почему Django?
● очень популярен, активно развивается;
● покрывает большинство нужд веб-
разработчиков;
● минимизирует рутину;
● достаточно приятен в обращении.
Составляющие Django-приложения
● основная парадигма - Models Views
Templates;
● модели;
● формы;
● представления;
● шаблоны;
● маршрутизаторы.
Недостатки Django
● однопоточный и как следствие тормозной;
● нестандартные вещи делать сложно (но
зато более-менее красиво);
● имеет жесткую структуру и идеологию,
что в редких случаях может помешать
разработке.
Что понадобится
● настроенная машина с Linux (лучше всего
Ubuntu, подойдет виртуальная) или
MacOS;
● редактор Python и HTML. Для начала
рекомендую PyCharm Professional Edition.
● или вместо всего этого онлайн-среда,
например c9.io
Подготовка системы
sudo apt-get install build-essential python3-dev python3 python3-virtualenv python3-
pip zlib1g-dev libpng12-dev libjpeg-dev git
virtualenv -p /usr/bin/python3 venv
source venv/bin/activate
git clone https://github.com/batment/kranonit-shop
cd kranonit-shop
pip install -r requirements.txt
Инициализация проекта
cd ..
django-admin startproject shop
cd shop
python manage.py startapp catalog
python manage.py startapp cart
python manage.py migrate
python manage.py syncdb
python manage.py runserver
Структура интернет-магазина
Настройки Django-проекта
● параметры подключения к базам данных;
● расположение директорий со
статическими файлами (JS, CSS, etc.) и
загружаемыми файлами;
● локализация, интернационализация и т.д.;
● подключенные приложения;
● параметры безопасности.
Настройки проекта ч.1
import dj_database_url
DEFAULT_DB = 'sqlite:///' + BASE_DIR + '/db.sqlite3'
DATABASES = {
'default': dj_database_url.config(default=DEFAULT_DB)
}
STATIC_URL = '/static/'
MEDIA_URL = '/media/'
TEMPLATE_DIRS = (
os.path.join(BASE_DIR, 'templates'),
)
STATICFILES_DIRS = (
os.path.join(BASE_DIR, ‘static’),
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
Настройки проекта ч.2
INSTALLED_APPS = (
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'catalog',
'cart',
)
SECRET_KEY = '0!+6_x3g49_do4d5)e=)07ke%wza^1)&@*=@!aw1x&%&kv24j3'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
TEMPLATE_DEBUG = True
ALLOWED_HOSTS = []
ROOT_URLCONF = 'shop.urls'
WSGI_APPLICATION = 'shop.wsgi.application'
Описание модели в Django
● класс, наследуемый от models.Model;
● нужные поля с данными описываются как
поля класса;
● класс Meta, объявленный внутри модели
содержит ее настройки;
● методы __str__ или __unicode__ упростят
текстовый вывод модели.
Модель ProductCategory
class ProductCategory(models.Model):
name = models.CharField(max_length=128)
class Meta:
verbose_name = 'Category'
verbose_name_plural = 'Categories'
def __str__(self):
return self.name
Базовые типы полей
● CharField - простое текстовое поле
ограниченной длинны;
● IntegerField - для хранения целых чисел;
● BooleanField - для хранения логических
данных (True, False)
● ForeignKey - для связи с другой моделью;
● ManyToManyField - для связи со многими
моделями.
Загружаемые файлы
● в базовой поставке FileField и
ImageFileField;
● в базе хранится только имя файла;
● файл хранится в MEDIA_ROOT;
● файлы нужно удалять вручную;
● в поле нужно указать upload_to;
● для картинок рекомендую easy_thumbnails
Модель Product
class Product(models.Model):
name = models.CharField(max_length=128)
description = models.TextField(max_length=10000, blank=True, null=True)
price = models.DecimalField(max_digits=8, decimal_places=2)
category = models.ForeignKey('catalog.ProductCategory')
image = models.ImageField(upload_to='products')
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def __str__(self):
return self.name
Модель Order
class Order(models.Model):
created_at = models.DateTimeField(auto_now_add=True, verbose_name='Opened at')
closed_at = models.DateTimeField(verbose_name='Closed at', blank=True, null=True)
is_closed = models.BooleanField(default=False, verbose_name='Is closed')
is_processed = models.BooleanField(default=False, verbose_name='Is processed')
phone = models.CharField(max_length=32, null=True)
address = models.CharField(max_length=256, null=True)
name = models.CharField(max_length=64, verbose_name='Contact name', null=True)
class Meta:
verbose_name = 'Order'
verbose_name_plural = 'Orders'
def price(self):
total_price = 0
for p in self.positions.all():
total_price += p.price()
return total_price
Модель OrderPosition
class OrderPosition(models.Model):
order = models.ForeignKey('cart.Order', related_name='positions')
product = models.ForeignKey('catalog.Product')
count = models.PositiveIntegerField(default=0)
class Meta:
verbose_name = 'Order position'
verbose_name_plural = 'Order positions'
ordering = ['-count']
def price(self):
return self.product.price * self.count
Формы в Django
● класс, наследуемый от forms.Form;
● описывается аналогично моделям;
● в описании полей можно указать
необходимый контрол (widget);
● могут генерировать готовый HTML-код.
Формы для моделей (ModelForm)
● в параметрах нужно только указать
модель, форма сгенерируется
автоматически;
● можно также указать включенные поля и
их порядок вывода;
● вместо этого можно указать исключенные
поля.
Набор форм (FormSet)
● предназначен для ситуаций, когда нужно
редактировать сразу много однотипных
данных;
● генерируется при помощи специальных
функций-фабрик;
● формы-составляющие являются
обычными формами.
Форма для добавления в корзину
class AddToCartForm(forms.Form):
product = forms.ModelChoiceField(
Product.objects.all(),
widget=forms.HiddenInput
)
Форма для оформления заказа
class OrderForm(forms.ModelForm):
class Meta:
model = Order
fields = ['name', 'address', 'phone']
Форма для позиций заказа
class OrderPositionForm(forms.ModelForm):
class Meta:
model = OrderPosition
fields = ['product', 'count']
OrderPositionFormset = forms.inlineformset_factory(
Order,
OrderPosition,
OrderPositionForm,
extra=0,
)
Представления в Django
● берут данные из GET или POST-массива,
моделей и форм, передают в шаблон;
● могут быть функцией - минимум
параметров и полная свобода в
функционале или классом на основе
базовых представлений, с настройкой
готового кода.
● get_context_data - формирует данные для
вывода в шаблон, можно добавить туда
свои;
● get_queryset - отправляет запрос в базу,
можно изменить любым образом;
● get_template_name - определяет шаблон,
можно подставлять другой при, например,
ajax-запросе.
Функционал Class Based Views
ListView
● служит для вывода списка моделей;
● поддерживает разбитие на страницы
(pagination).
DetailView
● служит для вывода одной модели.
Список товаров ч.1
class ProductList(ShopMixin, ListView):
model = Product
template_name = 'product_list.html'
context_object_name = 'products'
def __init__(self, *args, **kwargs):
self.category = None
super().__init__(*args, **kwargs)
Список товаров ч.2
def get_category(self):
category_id = self.kwargs.get('category_id')
category = None
if category_id:
category = get_object_or_404(
ProductCategory,
id=category_id,
)
self.category = category
return category
def get_queryset(self):
queryset = super().get_queryset()
if self.category:
queryset = queryset.filter(
category=self.category,
)
return queryset
Просмотр товара
class ProductDetailed(ShopMixin, DetailView):
model = Product
template_name = 'product.html'
context_object_name = 'product'
Примесь ShopMixin
class ShopMixin(object):
"""Adds categories and current order to render context"""
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
categories = ProductCategory.objects.all()
data['categories'] = categories
data['order'] = get_order(self.request)
return data
Представление на базе функции
● принимает объект запроса и параметры
URL;
● нужно все делать вручную;
● позволяет вызывать любые побочные
эффекты;
● более явный и понятный код.
Представление add_to_cart
def add_to_cart(request):
order = get_order(request)
if not order:
order = Order.objects.create()
request.session['order_id'] = order.id
form = AddToCartForm(request.POST)
if form.is_valid():
product = form.cleaned_data['product']
order_position, created = OrderPosition.objects.get_or_create(
product=product,
order=order,
)
order_position.count += 1
order_position.save()
return redirect('cart')
● обычный словарь в request.session;
● у каждого пользователя свой на основе
cookie session_id;
● может хранится в базе, в redis или в
cookies (не рекомендуется);
● может быть в Pickles или JSON;
● хранить лучше не модели, а их id.
Сессии в Django
Функция get_order
def get_order(request):
order_id = request.session.get('order_id')
order = None
if order_id:
try:
order = Order.objects.get(id=order_id)
except Order.DoesNotExist:
pass
return order
CreateView
UpdateView
● для редактирования моделей;
● обязательно принимает pk или slug.
● для создания моделей;
● может сам генерировать форму;
● содержит функции form_valid, form_invalid.
Редактирование заказа ч.1
class OrderDetails(UpdateView):
model = Order
template_name = 'cart.html'
form_class = OrderForm
success_url = '/finish'
def get_object(self, queryset=None):
return get_order(self.request)
def get_formset(self):
return OrderPositionFormset(**self.get_form_kwargs())
Редактирование заказа ч.2
def get_context_data(self, **kwargs):
data = super().get_context_data(**kwargs)
data['formset'] = self.get_formset()
return data
def form_valid(self, form):
formset = self.get_formset()
if formset.is_valid():
for position_form in formset:
position_form.save()
return super().form_valid(form)
else:
return self.form_invalid(form)
Завершение заказа
def close_order(request):
if request.POST:
order = get_order(request)
order.is_closed = True
order.closed_at = datetime.datetime.now()
order.save()
return render(request, 'close_order.html', {
'order': order,
})
else:
return redirect('order')
TemplateView
class AboutUs(TemplateView):
template_name = 'about_us.html'
Страница About us
● для вывода статичной или частично статичной страницы без моделей.
Админ-сайт в Django
● небольшая встроенная CMS, которой вам
скорее всего хватит;
● позволяет настроить очень многое, но не
все;
● настраивается для каждой модели
отдельно, плюс можно по связям сделать
встроенную админку.
Настройка админки каталога
from django.contrib import admin
from catalog.models import Product, ProductCategory
admin.site.register(Product)
admin.site.register(ProductCategory)
Настройка админки заказов
class OrderPositionInline(admin.TabularInline):
model = OrderPosition
class OrderAdmin(admin.ModelAdmin):
inlines = [
OrderPositionInline,
]
readonly_fields = ['created_at', 'closed_at']
admin.site.register(Order, OrderAdmin)
Маршрутизация в Django
● ROOT_URLCONF со списком url_patterns;
● каждый элемент - это regexp с
соответствующим представлением.
● CBV должны вызвать метод as_view для
вставки в список;
● для представлений-функций достаточно
указать ссылку ‘app.views.view’;
● можно включать другие файлы c
маршрутами через include
Маршруты приложения ч.1
from django.conf.urls import patterns, include, url
from django.contrib import admin
from django.conf import settings
from django.conf.urls.static import static
from catalog.views import ProductDetailed, ProductList, AboutUs
from cart.views import OrderDetails
urlpatterns = patterns(
'',
url(r'^(?P<category_id>d+)?$', ProductList.as_view(), name='products'),
url(r'^product/(?P<pk>d+)/$', ProductDetailed.as_view(), name='product'),
url(r'^add/$', 'cart.views.add_to_cart', name='add_to_cart'),
url(r'^cart/$', OrderDetails.as_view(), name='cart'),
url(r'^finish/$', 'cart.views.close_order', name='finish'),
url(r'^about/$', AboutUs.as_view(), name='about'),
url(r'^admin/', include(admin.site.urls)),
)
Маршруты приложения ч.2
urlpatterns += [static(
settings.STATIC_URL
) + static(
settings.MEDIA_URL,
document_root=settings.MEDIA_ROOT
)]
Язык шаблонов в Django
● очень простой;
● состоит из тегов и фильтров;
● теги нужны для вывода контента;
● фильтры нужны для обработки
переменных или результатов работы
других фильтров;
● исключения по возможности
подавляются.
Главный шаблон
● в основе лежит скелет getskeleton.com
● для встраивания используется тег
{% include ‘filename’ %}
● для наследования используется тег
{% extends ‘filename’ %}
● тег extends должен быть на первой
строке файла.
Код главного шаблона
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{% block title %}{% endblock %}</title>
<link rel="stylesheet" href="/static/css/normalize.css">
<link rel="stylesheet" href="/static/css/skeleton.css">
</head>
<body>
<div class="container">
{% include ’header.html’ %}
{% block body %}
<div class="row">
<div class="twelve columns">
{% block content %}{% endblock %}
</div>
</div>
{% endblock %}
</div>
</body>
</html>
Используемые теги
● url для вставки ссылок;
● csrf_token - нужен для POST-форм;
● if ... else … endif - условный тег
● for … in … endfor - цикл;
● forloop - объект с описанием текущей
итерации цикла, работает только внутри
for … endfor
Шаблон-заголовок
<div class="row">
<a href="{% url 'about' %}">About us</a>
Cart: {% if order %}
<a href="{% url 'cart' %}">{{ order.price }}$</a>
{% else %}empty{% endif %}
</div>
Страница списка товаров ч.1
{% extends 'base.html' %}
{% block title %}Shop{% endblock %}
{% block body %}
<div class="row">
{% for category in categories %}
<a href="{% url 'products' category.id %}>{{ category }}</a>
{% endfor %}
</div>
{% for product in products %}
{% if not forloop.counter|divisibleby:"2" %}
<div class="row">
{% endif %}
Страница списка товаров ч.2
<div class="six columns">
<div>
<img src="{{ product.image.url }}" alt="{{ product }}">
</div>
<div>
<a href="{% url 'product' product.id %}"><h4>{{ product }}</h4></a>
</div>
<div>
{{ product.price }}$
</div>
<form action="{% url 'add_to_cart' %}" method="post">
{% csrf_token %}
<input type="hidden" value="{{ product.id }}">
<input type="submit" value="Add to cart">
</form>
</div>
{% if forloop.counter|divisibleby:"2" %}
</div>
{% endif %}
{% endfor %}
{% endblock %}
Страница товара
{% extends 'base.html' %}
{% block title %}{{ product }}{% endblock %}
{% block content %}
<div><img src="{{ product.image.url }}" alt="{{ product }}"></div>
<div>
<h3>{{ product }}</h3>
</div>
<div>{{ product.price }}$</div>
<div>{{ product.description }}</div>
<form action="{% url 'add_to_cart' %}" method="post">
{% csrf_token %}
<input type="hidden" value="{{ product.id }}">
<input type="submit" value="Add to cart">
</form>
{% endblock %}
Корзина ч.1
{% extends 'base.html' %}
{% block title %}Cart{% endblock %}
{% block body %}
<form action="{% url 'cart' %}" method="post">
{% csrf_token %}
<div class="row">
{{ form.as_ul }}
<input type="submit" value="Update order">
</div>
Корзина ч.2
<div class="row">
{% for position_form in formset %}
{{ position_form.as_ul }}
{% endfor %}
</div>
<input type="submit" value="Update order">
</form>
<div class="row">
<form action="{% url 'finish' %}">
{% csrf_token %}
<input type="submit" value="Finish order">
</form>
</div>
{% endblock %}
Страница завершения заказа
{% extends 'base.html' %}
{% block title %}Thank you!{% endblock %}
{% block content %}
Thank you! Your order is {{ order.id }}. You will not be called soon.
{% endblock %}
Страница About us
{% extends 'base.html' %}
{% block title %}About us{% endblock %}
{% block content %}
Glad to see you here!
{% endblock %}
Вопросы?
Ссылки
● https://github.com/SergeyBurma/kranonit-
shop
● https://www.djangoproject.com/
● http://djbook.ru/
● https://pypi.python.org/pypi?%3Aaction=sear
ch&term=django&submit=search
● http://habrahabr.ru/post/159575/
● https://www.jetbrains.com/pycharm/
Спасибо!

More Related Content

What's hot

credit card fraud analysis using predictive modeling python project abstract
credit card fraud analysis using predictive modeling python project abstractcredit card fraud analysis using predictive modeling python project abstract
credit card fraud analysis using predictive modeling python project abstract
Venkat Projects
 

What's hot (20)

Text mining
Text miningText mining
Text mining
 
Intrusion Detection Systems (IDS)
Intrusion Detection Systems (IDS)Intrusion Detection Systems (IDS)
Intrusion Detection Systems (IDS)
 
credit card fraud analysis using predictive modeling python project abstract
credit card fraud analysis using predictive modeling python project abstractcredit card fraud analysis using predictive modeling python project abstract
credit card fraud analysis using predictive modeling python project abstract
 
Bioinformatics, application by kk sahu sir
Bioinformatics, application by kk sahu sirBioinformatics, application by kk sahu sir
Bioinformatics, application by kk sahu sir
 
Ethics in biotechnology
Ethics in biotechnologyEthics in biotechnology
Ethics in biotechnology
 
Deep learning for genomics: Present and future
Deep learning for genomics: Present and futureDeep learning for genomics: Present and future
Deep learning for genomics: Present and future
 
Cyber security and its advantages
Cyber security and its advantagesCyber security and its advantages
Cyber security and its advantages
 
Data Mining & Applications
Data Mining & ApplicationsData Mining & Applications
Data Mining & Applications
 
Data Privacy: What you need to know about privacy, from compliance to ethics
Data Privacy: What you need to know about privacy, from compliance to ethicsData Privacy: What you need to know about privacy, from compliance to ethics
Data Privacy: What you need to know about privacy, from compliance to ethics
 
cyber security.pdf
cyber security.pdfcyber security.pdf
cyber security.pdf
 
Applications of bioinformatics
Applications of bioinformaticsApplications of bioinformatics
Applications of bioinformatics
 
Cyber crimes presentation
Cyber crimes presentationCyber crimes presentation
Cyber crimes presentation
 
National bioethics-committee-guidelines
National bioethics-committee-guidelinesNational bioethics-committee-guidelines
National bioethics-committee-guidelines
 
Big Data Ecosystem
Big Data EcosystemBig Data Ecosystem
Big Data Ecosystem
 
OS Fingerprinting
OS FingerprintingOS Fingerprinting
OS Fingerprinting
 
Bioinformatics in present and its future
Bioinformatics in present and its futureBioinformatics in present and its future
Bioinformatics in present and its future
 
Data mining
Data mining Data mining
Data mining
 
An introduction to cyber forensics and open source tools in cyber forensics
An introduction to cyber forensics and open source tools in cyber forensicsAn introduction to cyber forensics and open source tools in cyber forensics
An introduction to cyber forensics and open source tools in cyber forensics
 
Data Mining : Concepts and Techniques
Data Mining : Concepts and TechniquesData Mining : Concepts and Techniques
Data Mining : Concepts and Techniques
 
Dark Web Forensics
Dark Web Forensics Dark Web Forensics
Dark Web Forensics
 

Viewers also liked

Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
Krivoy Rog IT Community
 
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDDkranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
Krivoy Rog IT Community
 
Работа с платежными системами в Django (Paypal, WebMoney)
Работа с платежными системами в Django (Paypal, WebMoney)Работа с платежными системами в Django (Paypal, WebMoney)
Работа с платежными системами в Django (Paypal, WebMoney)
proft
 

Viewers also liked (20)

Kranonit S18 Lobova Elena
Kranonit S18 Lobova ElenaKranonit S18 Lobova Elena
Kranonit S18 Lobova Elena
 
Kranonit S18 Pavlov Evgeniy
Kranonit S18 Pavlov Evgeniy Kranonit S18 Pavlov Evgeniy
Kranonit S18 Pavlov Evgeniy
 
Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
Kranonit S18 Chernomorov Vasiliy "Как создать игру и не сойти с ума "
 
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDDkranonit S15 Vladimir Melnik - Ruby on Rails, BDD
kranonit S15 Vladimir Melnik - Ruby on Rails, BDD
 
Python и Django – платформа для фрилансера
Python и Django – платформа для фрилансераPython и Django – платформа для фрилансера
Python и Django – платформа для фрилансера
 
Работа с платежными системами в Django (Paypal, WebMoney)
Работа с платежными системами в Django (Paypal, WebMoney)Работа с платежными системами в Django (Paypal, WebMoney)
Работа с платежными системами в Django (Paypal, WebMoney)
 
Refactoring
RefactoringRefactoring
Refactoring
 
Kranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenkoKranonit s16 (python). dmitry furzenko
Kranonit s16 (python). dmitry furzenko
 
Kranonit s16 (python). sergey burma
Kranonit s16 (python). sergey burmaKranonit s16 (python). sergey burma
Kranonit s16 (python). sergey burma
 
Codefest 2016 - Go в Openprovider
Codefest 2016 - Go в OpenproviderCodefest 2016 - Go в Openprovider
Codefest 2016 - Go в Openprovider
 
Go в автобусе
Go в автобусеGo в автобусе
Go в автобусе
 
Обзорная экскурсия по runit
Обзорная экскурсия по runitОбзорная экскурсия по runit
Обзорная экскурсия по runit
 
РИФ+КИБ 2016: как потратить почти 2 миллиона рублей и так и не сделать бизнес
РИФ+КИБ 2016: как потратить почти 2 миллиона рублей и так и не сделать бизнесРИФ+КИБ 2016: как потратить почти 2 миллиона рублей и так и не сделать бизнес
РИФ+КИБ 2016: как потратить почти 2 миллиона рублей и так и не сделать бизнес
 
Golang
GolangGolang
Golang
 
Как ВКонтакте использует Go
Как ВКонтакте использует GoКак ВКонтакте использует Go
Как ВКонтакте использует Go
 
Dynamic Ruby. Lesson #1: Object model
Dynamic Ruby. Lesson #1: Object modelDynamic Ruby. Lesson #1: Object model
Dynamic Ruby. Lesson #1: Object model
 
Ruby строки
Ruby строкиRuby строки
Ruby строки
 
OOP в Go
OOP в GoOOP в Go
OOP в Go
 
BeeGo для веб приложений, API и демонов
BeeGo для веб приложений, API и демоновBeeGo для веб приложений, API и демонов
BeeGo для веб приложений, API и демонов
 
Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015Go meetup smotri+ 23.04.2015
Go meetup smotri+ 23.04.2015
 

Similar to kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно

Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
Technopark
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11
dva
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
it-people
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7
Technopark
 
Web осень 2013 лекция 8
Web осень 2013 лекция 8Web осень 2013 лекция 8
Web осень 2013 лекция 8
Technopark
 
Web весна 2013 лекция 4
Web весна 2013 лекция 4Web весна 2013 лекция 4
Web весна 2013 лекция 4
Technopark
 
Django South. Миграция баз данных.
Django South. Миграция баз данных.  Django South. Миграция баз данных.
Django South. Миграция баз данных.
MoscowDjango
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
Yehor Nazarkin
 

Similar to kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно (20)

Web осень 2013 лекция 6
Web осень 2013 лекция 6Web осень 2013 лекция 6
Web осень 2013 лекция 6
 
django cheBit'11
django cheBit'11django cheBit'11
django cheBit'11
 
Js fuckworks
Js fuckworksJs fuckworks
Js fuckworks
 
Yii2
Yii2Yii2
Yii2
 
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
View как чистая функция от состояния базы данных  - Илья Беда, bro.agencyView как чистая функция от состояния базы данных  - Илья Беда, bro.agency
View как чистая функция от состояния базы данных - Илья Беда, bro.agency
 
Web весна 2012 лекция 7
Web весна 2012 лекция 7Web весна 2012 лекция 7
Web весна 2012 лекция 7
 
Введение в Django
Введение в DjangoВведение в Django
Введение в Django
 
Zend Framework и Doctrine
Zend Framework и DoctrineZend Framework и Doctrine
Zend Framework и Doctrine
 
Django
DjangoDjango
Django
 
Web осень 2013 лекция 8
Web осень 2013 лекция 8Web осень 2013 лекция 8
Web осень 2013 лекция 8
 
Вёрстка WordPress тем - WP Kharkiv Meetup #1
Вёрстка WordPress тем - WP Kharkiv Meetup #1Вёрстка WordPress тем - WP Kharkiv Meetup #1
Вёрстка WordPress тем - WP Kharkiv Meetup #1
 
Выжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим ГопейВыжить с помощью ООП. Максим Гопей
Выжить с помощью ООП. Максим Гопей
 
Что нового в Django 1.4
Что нового в Django 1.4Что нового в Django 1.4
Что нового в Django 1.4
 
Web весна 2013 лекция 4
Web весна 2013 лекция 4Web весна 2013 лекция 4
Web весна 2013 лекция 4
 
Python Meetup
Python Meetup Python Meetup
Python Meetup
 
10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)10 - Web-технологии. MVC фреймворки (продолжение)
10 - Web-технологии. MVC фреймворки (продолжение)
 
Survive with OOP
Survive with OOPSurvive with OOP
Survive with OOP
 
12 - Web-технологии. Django модели
12 - Web-технологии. Django модели12 - Web-технологии. Django модели
12 - Web-технологии. Django модели
 
Django South. Миграция баз данных.
Django South. Миграция баз данных.  Django South. Миграция баз данных.
Django South. Миграция баз данных.
 
GAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камниGAE - плюсы/минусы/подводные камни
GAE - плюсы/минусы/подводные камни
 

More from Krivoy Rog IT Community

kranonit S12E02 Артур Титов: Юзабилити форм
kranonit S12E02 Артур Титов: Юзабилити формkranonit S12E02 Артур Титов: Юзабилити форм
kranonit S12E02 Артур Титов: Юзабилити форм
Krivoy Rog IT Community
 
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Javakranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
Krivoy Rog IT Community
 
kranonit S10E01 Андрей Бабак- Запускаем стартап
kranonit S10E01 Андрей Бабак- Запускаем стартапkranonit S10E01 Андрей Бабак- Запускаем стартап
kranonit S10E01 Андрей Бабак- Запускаем стартап
Krivoy Rog IT Community
 
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информацииkranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
Krivoy Rog IT Community
 
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушекkranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
Krivoy Rog IT Community
 
kranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High loadkranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High load
Krivoy Rog IT Community
 
kranonit S05E01 Sergey Burma: Welcome to cloud!
kranonit S05E01 Sergey Burma: Welcome to cloud!kranonit S05E01 Sergey Burma: Welcome to cloud!
kranonit S05E01 Sergey Burma: Welcome to cloud!
Krivoy Rog IT Community
 
kranonit S04E02 Кирил Jstor: Hacking .NET applications
kranonit S04E02 Кирил Jstor: Hacking .NET applicationskranonit S04E02 Кирил Jstor: Hacking .NET applications
kranonit S04E02 Кирил Jstor: Hacking .NET applications
Krivoy Rog IT Community
 
kranonit S04E01 Антон: Защита от Master Boot Record Locker
kranonit S04E01 Антон: Защита от Master Boot Record Lockerkranonit S04E01 Антон: Защита от Master Boot Record Locker
kranonit S04E01 Антон: Защита от Master Boot Record Locker
Krivoy Rog IT Community
 
kranonit S03E01 Эдуард Лобас: Freelance
kranonit S03E01 Эдуард Лобас: Freelancekranonit S03E01 Эдуард Лобас: Freelance
kranonit S03E01 Эдуард Лобас: Freelance
Krivoy Rog IT Community
 
kranonit S07E02 nixoid: Будущее электронных денег
kranonit S07E02 nixoid: Будущее электронных денегkranonit S07E02 nixoid: Будущее электронных денег
kranonit S07E02 nixoid: Будущее электронных денег
Krivoy Rog IT Community
 
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игрkranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
Krivoy Rog IT Community
 
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальностиkranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
Krivoy Rog IT Community
 
kranonit S01E02 Игорь Цинько: Как искать работу
kranonit S01E02 Игорь Цинько: Как искать работуkranonit S01E02 Игорь Цинько: Как искать работу
kranonit S01E02 Игорь Цинько: Как искать работу
Krivoy Rog IT Community
 
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
Krivoy Rog IT Community
 

More from Krivoy Rog IT Community (18)

Kranonit sponsorskoe predlozhenie
Kranonit sponsorskoe predlozhenieKranonit sponsorskoe predlozhenie
Kranonit sponsorskoe predlozhenie
 
kranonit S14E02 Серёжа Пономарёв: kranonit’у уже год. Полёт нормальный?
kranonit S14E02 Серёжа Пономарёв: kranonit’у уже год. Полёт нормальный?kranonit S14E02 Серёжа Пономарёв: kranonit’у уже год. Полёт нормальный?
kranonit S14E02 Серёжа Пономарёв: kranonit’у уже год. Полёт нормальный?
 
kranonit S14E01 Эдуард Лобас Management & IT Industry
kranonit S14E01 Эдуард Лобас Management & IT Industrykranonit S14E01 Эдуард Лобас Management & IT Industry
kranonit S14E01 Эдуард Лобас Management & IT Industry
 
kranonit S12E02 Артур Титов: Юзабилити форм
kranonit S12E02 Артур Титов: Юзабилити формkranonit S12E02 Артур Титов: Юзабилити форм
kranonit S12E02 Артур Титов: Юзабилити форм
 
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Javakranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
kranonit S11E01 Андрей Пономарёв: Тренинг по TDD в Java
 
kranonit S10E01 Андрей Бабак- Запускаем стартап
kranonit S10E01 Андрей Бабак- Запускаем стартапkranonit S10E01 Андрей Бабак- Запускаем стартап
kranonit S10E01 Андрей Бабак- Запускаем стартап
 
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информацииkranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
kranonit S07E01 Евгений Василенко: Методы криптографической защиты информации
 
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушекkranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
kranonit S06E02 Артём Юрков: Как все успеть и не слететь с катушек
 
kranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High loadkranonit S06E01 Игорь Цинько: High load
kranonit S06E01 Игорь Цинько: High load
 
kranonit S05E01 Sergey Burma: Welcome to cloud!
kranonit S05E01 Sergey Burma: Welcome to cloud!kranonit S05E01 Sergey Burma: Welcome to cloud!
kranonit S05E01 Sergey Burma: Welcome to cloud!
 
kranonit S04E02 Кирил Jstor: Hacking .NET applications
kranonit S04E02 Кирил Jstor: Hacking .NET applicationskranonit S04E02 Кирил Jstor: Hacking .NET applications
kranonit S04E02 Кирил Jstor: Hacking .NET applications
 
kranonit S04E01 Антон: Защита от Master Boot Record Locker
kranonit S04E01 Антон: Защита от Master Boot Record Lockerkranonit S04E01 Антон: Защита от Master Boot Record Locker
kranonit S04E01 Антон: Защита от Master Boot Record Locker
 
kranonit S03E01 Эдуард Лобас: Freelance
kranonit S03E01 Эдуард Лобас: Freelancekranonit S03E01 Эдуард Лобас: Freelance
kranonit S03E01 Эдуард Лобас: Freelance
 
kranonit S07E02 nixoid: Будущее электронных денег
kranonit S07E02 nixoid: Будущее электронных денегkranonit S07E02 nixoid: Будущее электронных денег
kranonit S07E02 nixoid: Будущее электронных денег
 
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игрkranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
kranonit S02E02 Стас Чирва: Unity3D Разработка казуальных и социальных игр
 
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальностиkranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
kranonit S02E01 Дмитрий Свириденко- HTML5: Поздравляю, ты в новой реальности
 
kranonit S01E02 Игорь Цинько: Как искать работу
kranonit S01E02 Игорь Цинько: Как искать работуkranonit S01E02 Игорь Цинько: Как искать работу
kranonit S01E02 Игорь Цинько: Как искать работу
 
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
kranonit S01E01 Серёжа Пономарёв: Современный программист 2.1
 

kranonitS20 Сергей Бурма. Django - легко, быстро, эффективно

  • 2. Обо мне ● использую Python в своих корыстных и не очень целях уже пятый год; ● поучаствовал в нескольких больших незапустившихся проектах; ● приложил руку к сайтам wokifood.ru, dewote.com, biz-translate.com; ● изредка пишу на хабр (ник batment).
  • 3. О чем вы сегодня узнаете ● немного о Python; ● много о фреймворке Django; ● о том как сделать очень простой интернет-магазин с админкой.
  • 4. Особенности Python ● приоритет на читаемость; ● данные бывают изменяемые и неизменяемые (mutable, immutable) ● жесткие стандарты оформления кода; ● любая сущность - это объект; ● очень своеобразное ООП; ● магические методы.
  • 5. Дисклеймер ● мы используем Python 3; ● код представлен максимально наглядно, но в нем скорее всего есть неувязки и ошибки, будьте осторожны.
  • 6. Почему Django? ● очень популярен, активно развивается; ● покрывает большинство нужд веб- разработчиков; ● минимизирует рутину; ● достаточно приятен в обращении.
  • 7. Составляющие Django-приложения ● основная парадигма - Models Views Templates; ● модели; ● формы; ● представления; ● шаблоны; ● маршрутизаторы.
  • 8. Недостатки Django ● однопоточный и как следствие тормозной; ● нестандартные вещи делать сложно (но зато более-менее красиво); ● имеет жесткую структуру и идеологию, что в редких случаях может помешать разработке.
  • 9. Что понадобится ● настроенная машина с Linux (лучше всего Ubuntu, подойдет виртуальная) или MacOS; ● редактор Python и HTML. Для начала рекомендую PyCharm Professional Edition. ● или вместо всего этого онлайн-среда, например c9.io
  • 10. Подготовка системы sudo apt-get install build-essential python3-dev python3 python3-virtualenv python3- pip zlib1g-dev libpng12-dev libjpeg-dev git virtualenv -p /usr/bin/python3 venv source venv/bin/activate git clone https://github.com/batment/kranonit-shop cd kranonit-shop pip install -r requirements.txt
  • 11. Инициализация проекта cd .. django-admin startproject shop cd shop python manage.py startapp catalog python manage.py startapp cart python manage.py migrate python manage.py syncdb python manage.py runserver
  • 13. Настройки Django-проекта ● параметры подключения к базам данных; ● расположение директорий со статическими файлами (JS, CSS, etc.) и загружаемыми файлами; ● локализация, интернационализация и т.д.; ● подключенные приложения; ● параметры безопасности.
  • 14. Настройки проекта ч.1 import dj_database_url DEFAULT_DB = 'sqlite:///' + BASE_DIR + '/db.sqlite3' DATABASES = { 'default': dj_database_url.config(default=DEFAULT_DB) } STATIC_URL = '/static/' MEDIA_URL = '/media/' TEMPLATE_DIRS = ( os.path.join(BASE_DIR, 'templates'), ) STATICFILES_DIRS = ( os.path.join(BASE_DIR, ‘static’), ) MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
  • 15. Настройки проекта ч.2 INSTALLED_APPS = ( 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'catalog', 'cart', ) SECRET_KEY = '0!+6_x3g49_do4d5)e=)07ke%wza^1)&@*=@!aw1x&%&kv24j3' # SECURITY WARNING: don't run with debug turned on in production! DEBUG = True TEMPLATE_DEBUG = True ALLOWED_HOSTS = [] ROOT_URLCONF = 'shop.urls' WSGI_APPLICATION = 'shop.wsgi.application'
  • 16. Описание модели в Django ● класс, наследуемый от models.Model; ● нужные поля с данными описываются как поля класса; ● класс Meta, объявленный внутри модели содержит ее настройки; ● методы __str__ или __unicode__ упростят текстовый вывод модели.
  • 17. Модель ProductCategory class ProductCategory(models.Model): name = models.CharField(max_length=128) class Meta: verbose_name = 'Category' verbose_name_plural = 'Categories' def __str__(self): return self.name
  • 18. Базовые типы полей ● CharField - простое текстовое поле ограниченной длинны; ● IntegerField - для хранения целых чисел; ● BooleanField - для хранения логических данных (True, False) ● ForeignKey - для связи с другой моделью; ● ManyToManyField - для связи со многими моделями.
  • 19. Загружаемые файлы ● в базовой поставке FileField и ImageFileField; ● в базе хранится только имя файла; ● файл хранится в MEDIA_ROOT; ● файлы нужно удалять вручную; ● в поле нужно указать upload_to; ● для картинок рекомендую easy_thumbnails
  • 20. Модель Product class Product(models.Model): name = models.CharField(max_length=128) description = models.TextField(max_length=10000, blank=True, null=True) price = models.DecimalField(max_digits=8, decimal_places=2) category = models.ForeignKey('catalog.ProductCategory') image = models.ImageField(upload_to='products') class Meta: verbose_name = 'Product' verbose_name_plural = 'Products' def __str__(self): return self.name
  • 21. Модель Order class Order(models.Model): created_at = models.DateTimeField(auto_now_add=True, verbose_name='Opened at') closed_at = models.DateTimeField(verbose_name='Closed at', blank=True, null=True) is_closed = models.BooleanField(default=False, verbose_name='Is closed') is_processed = models.BooleanField(default=False, verbose_name='Is processed') phone = models.CharField(max_length=32, null=True) address = models.CharField(max_length=256, null=True) name = models.CharField(max_length=64, verbose_name='Contact name', null=True) class Meta: verbose_name = 'Order' verbose_name_plural = 'Orders' def price(self): total_price = 0 for p in self.positions.all(): total_price += p.price() return total_price
  • 22. Модель OrderPosition class OrderPosition(models.Model): order = models.ForeignKey('cart.Order', related_name='positions') product = models.ForeignKey('catalog.Product') count = models.PositiveIntegerField(default=0) class Meta: verbose_name = 'Order position' verbose_name_plural = 'Order positions' ordering = ['-count'] def price(self): return self.product.price * self.count
  • 23. Формы в Django ● класс, наследуемый от forms.Form; ● описывается аналогично моделям; ● в описании полей можно указать необходимый контрол (widget); ● могут генерировать готовый HTML-код.
  • 24. Формы для моделей (ModelForm) ● в параметрах нужно только указать модель, форма сгенерируется автоматически; ● можно также указать включенные поля и их порядок вывода; ● вместо этого можно указать исключенные поля.
  • 25. Набор форм (FormSet) ● предназначен для ситуаций, когда нужно редактировать сразу много однотипных данных; ● генерируется при помощи специальных функций-фабрик; ● формы-составляющие являются обычными формами.
  • 26. Форма для добавления в корзину class AddToCartForm(forms.Form): product = forms.ModelChoiceField( Product.objects.all(), widget=forms.HiddenInput ) Форма для оформления заказа class OrderForm(forms.ModelForm): class Meta: model = Order fields = ['name', 'address', 'phone']
  • 27. Форма для позиций заказа class OrderPositionForm(forms.ModelForm): class Meta: model = OrderPosition fields = ['product', 'count'] OrderPositionFormset = forms.inlineformset_factory( Order, OrderPosition, OrderPositionForm, extra=0, )
  • 28. Представления в Django ● берут данные из GET или POST-массива, моделей и форм, передают в шаблон; ● могут быть функцией - минимум параметров и полная свобода в функционале или классом на основе базовых представлений, с настройкой готового кода.
  • 29. ● get_context_data - формирует данные для вывода в шаблон, можно добавить туда свои; ● get_queryset - отправляет запрос в базу, можно изменить любым образом; ● get_template_name - определяет шаблон, можно подставлять другой при, например, ajax-запросе. Функционал Class Based Views
  • 30. ListView ● служит для вывода списка моделей; ● поддерживает разбитие на страницы (pagination). DetailView ● служит для вывода одной модели.
  • 31. Список товаров ч.1 class ProductList(ShopMixin, ListView): model = Product template_name = 'product_list.html' context_object_name = 'products' def __init__(self, *args, **kwargs): self.category = None super().__init__(*args, **kwargs)
  • 32. Список товаров ч.2 def get_category(self): category_id = self.kwargs.get('category_id') category = None if category_id: category = get_object_or_404( ProductCategory, id=category_id, ) self.category = category return category def get_queryset(self): queryset = super().get_queryset() if self.category: queryset = queryset.filter( category=self.category, ) return queryset
  • 33. Просмотр товара class ProductDetailed(ShopMixin, DetailView): model = Product template_name = 'product.html' context_object_name = 'product' Примесь ShopMixin class ShopMixin(object): """Adds categories and current order to render context""" def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) categories = ProductCategory.objects.all() data['categories'] = categories data['order'] = get_order(self.request) return data
  • 34. Представление на базе функции ● принимает объект запроса и параметры URL; ● нужно все делать вручную; ● позволяет вызывать любые побочные эффекты; ● более явный и понятный код.
  • 35. Представление add_to_cart def add_to_cart(request): order = get_order(request) if not order: order = Order.objects.create() request.session['order_id'] = order.id form = AddToCartForm(request.POST) if form.is_valid(): product = form.cleaned_data['product'] order_position, created = OrderPosition.objects.get_or_create( product=product, order=order, ) order_position.count += 1 order_position.save() return redirect('cart')
  • 36. ● обычный словарь в request.session; ● у каждого пользователя свой на основе cookie session_id; ● может хранится в базе, в redis или в cookies (не рекомендуется); ● может быть в Pickles или JSON; ● хранить лучше не модели, а их id. Сессии в Django
  • 37. Функция get_order def get_order(request): order_id = request.session.get('order_id') order = None if order_id: try: order = Order.objects.get(id=order_id) except Order.DoesNotExist: pass return order
  • 38. CreateView UpdateView ● для редактирования моделей; ● обязательно принимает pk или slug. ● для создания моделей; ● может сам генерировать форму; ● содержит функции form_valid, form_invalid.
  • 39. Редактирование заказа ч.1 class OrderDetails(UpdateView): model = Order template_name = 'cart.html' form_class = OrderForm success_url = '/finish' def get_object(self, queryset=None): return get_order(self.request) def get_formset(self): return OrderPositionFormset(**self.get_form_kwargs())
  • 40. Редактирование заказа ч.2 def get_context_data(self, **kwargs): data = super().get_context_data(**kwargs) data['formset'] = self.get_formset() return data def form_valid(self, form): formset = self.get_formset() if formset.is_valid(): for position_form in formset: position_form.save() return super().form_valid(form) else: return self.form_invalid(form)
  • 41. Завершение заказа def close_order(request): if request.POST: order = get_order(request) order.is_closed = True order.closed_at = datetime.datetime.now() order.save() return render(request, 'close_order.html', { 'order': order, }) else: return redirect('order')
  • 42. TemplateView class AboutUs(TemplateView): template_name = 'about_us.html' Страница About us ● для вывода статичной или частично статичной страницы без моделей.
  • 43. Админ-сайт в Django ● небольшая встроенная CMS, которой вам скорее всего хватит; ● позволяет настроить очень многое, но не все; ● настраивается для каждой модели отдельно, плюс можно по связям сделать встроенную админку.
  • 44. Настройка админки каталога from django.contrib import admin from catalog.models import Product, ProductCategory admin.site.register(Product) admin.site.register(ProductCategory)
  • 45. Настройка админки заказов class OrderPositionInline(admin.TabularInline): model = OrderPosition class OrderAdmin(admin.ModelAdmin): inlines = [ OrderPositionInline, ] readonly_fields = ['created_at', 'closed_at'] admin.site.register(Order, OrderAdmin)
  • 46. Маршрутизация в Django ● ROOT_URLCONF со списком url_patterns; ● каждый элемент - это regexp с соответствующим представлением. ● CBV должны вызвать метод as_view для вставки в список; ● для представлений-функций достаточно указать ссылку ‘app.views.view’; ● можно включать другие файлы c маршрутами через include
  • 47. Маршруты приложения ч.1 from django.conf.urls import patterns, include, url from django.contrib import admin from django.conf import settings from django.conf.urls.static import static from catalog.views import ProductDetailed, ProductList, AboutUs from cart.views import OrderDetails urlpatterns = patterns( '', url(r'^(?P<category_id>d+)?$', ProductList.as_view(), name='products'), url(r'^product/(?P<pk>d+)/$', ProductDetailed.as_view(), name='product'), url(r'^add/$', 'cart.views.add_to_cart', name='add_to_cart'), url(r'^cart/$', OrderDetails.as_view(), name='cart'), url(r'^finish/$', 'cart.views.close_order', name='finish'), url(r'^about/$', AboutUs.as_view(), name='about'), url(r'^admin/', include(admin.site.urls)), )
  • 48. Маршруты приложения ч.2 urlpatterns += [static( settings.STATIC_URL ) + static( settings.MEDIA_URL, document_root=settings.MEDIA_ROOT )]
  • 49. Язык шаблонов в Django ● очень простой; ● состоит из тегов и фильтров; ● теги нужны для вывода контента; ● фильтры нужны для обработки переменных или результатов работы других фильтров; ● исключения по возможности подавляются.
  • 50. Главный шаблон ● в основе лежит скелет getskeleton.com ● для встраивания используется тег {% include ‘filename’ %} ● для наследования используется тег {% extends ‘filename’ %} ● тег extends должен быть на первой строке файла.
  • 51. Код главного шаблона <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>{% block title %}{% endblock %}</title> <link rel="stylesheet" href="/static/css/normalize.css"> <link rel="stylesheet" href="/static/css/skeleton.css"> </head> <body> <div class="container"> {% include ’header.html’ %} {% block body %} <div class="row"> <div class="twelve columns"> {% block content %}{% endblock %} </div> </div> {% endblock %} </div> </body> </html>
  • 52. Используемые теги ● url для вставки ссылок; ● csrf_token - нужен для POST-форм; ● if ... else … endif - условный тег ● for … in … endfor - цикл; ● forloop - объект с описанием текущей итерации цикла, работает только внутри for … endfor
  • 53. Шаблон-заголовок <div class="row"> <a href="{% url 'about' %}">About us</a> Cart: {% if order %} <a href="{% url 'cart' %}">{{ order.price }}$</a> {% else %}empty{% endif %} </div>
  • 54. Страница списка товаров ч.1 {% extends 'base.html' %} {% block title %}Shop{% endblock %} {% block body %} <div class="row"> {% for category in categories %} <a href="{% url 'products' category.id %}>{{ category }}</a> {% endfor %} </div> {% for product in products %} {% if not forloop.counter|divisibleby:"2" %} <div class="row"> {% endif %}
  • 55. Страница списка товаров ч.2 <div class="six columns"> <div> <img src="{{ product.image.url }}" alt="{{ product }}"> </div> <div> <a href="{% url 'product' product.id %}"><h4>{{ product }}</h4></a> </div> <div> {{ product.price }}$ </div> <form action="{% url 'add_to_cart' %}" method="post"> {% csrf_token %} <input type="hidden" value="{{ product.id }}"> <input type="submit" value="Add to cart"> </form> </div> {% if forloop.counter|divisibleby:"2" %} </div> {% endif %} {% endfor %} {% endblock %}
  • 56. Страница товара {% extends 'base.html' %} {% block title %}{{ product }}{% endblock %} {% block content %} <div><img src="{{ product.image.url }}" alt="{{ product }}"></div> <div> <h3>{{ product }}</h3> </div> <div>{{ product.price }}$</div> <div>{{ product.description }}</div> <form action="{% url 'add_to_cart' %}" method="post"> {% csrf_token %} <input type="hidden" value="{{ product.id }}"> <input type="submit" value="Add to cart"> </form> {% endblock %}
  • 57. Корзина ч.1 {% extends 'base.html' %} {% block title %}Cart{% endblock %} {% block body %} <form action="{% url 'cart' %}" method="post"> {% csrf_token %} <div class="row"> {{ form.as_ul }} <input type="submit" value="Update order"> </div>
  • 58. Корзина ч.2 <div class="row"> {% for position_form in formset %} {{ position_form.as_ul }} {% endfor %} </div> <input type="submit" value="Update order"> </form> <div class="row"> <form action="{% url 'finish' %}"> {% csrf_token %} <input type="submit" value="Finish order"> </form> </div> {% endblock %}
  • 59. Страница завершения заказа {% extends 'base.html' %} {% block title %}Thank you!{% endblock %} {% block content %} Thank you! Your order is {{ order.id }}. You will not be called soon. {% endblock %} Страница About us {% extends 'base.html' %} {% block title %}About us{% endblock %} {% block content %} Glad to see you here! {% endblock %}
  • 61. Ссылки ● https://github.com/SergeyBurma/kranonit- shop ● https://www.djangoproject.com/ ● http://djbook.ru/ ● https://pypi.python.org/pypi?%3Aaction=sear ch&term=django&submit=search ● http://habrahabr.ru/post/159575/ ● https://www.jetbrains.com/pycharm/