Oleksandr Rehush,
python developer
А ви ще не знали про ці зручні інструменти для рішення ваших задач? В цій темі ми обговоримо стандартні пакети та підходи для рішення типових задач засобами Python.
Тема буде цікавою для початківців та впевнених розробників.
NumPy є основним пакетом для наукових обчислень в Python. Пакет містить:
import numpy as np
arr = np.array([1,2,3,4,5])
print(arr.ndim) # 1
print(arr.size) # 5
print(arr.shape) # (5,)
arr2 = np.array([[1,2,3,4,5], [2,4,6,8,10]])
print(arr2.ndim) # 2
print(arr2.size) # 10
print(arr2.shape) # (2, 5)
import numpy as np
arr = np.array([1,2,3,4,5])
arr2 = np.array([[1,2,3,4,5], [2,4,6,8,10]])
print(arr + arr2)
# array([[ 2, 4, 6, 8, 10],
# [ 3, 6, 9, 12, 15]])
a = np.zeros((2,2))
print(a)
# [[ 0. 0.]
# [ 0. 0.]]"
b = np.ones((1,2))
print(b)
# [[ 1. 1.]]
c = np.full((2,2), 7)
print(c)
# [[ 7. 7.]
# [ 7. 7.]]
d = np.eye(2)
print(d)
# [[ 1. 0.]
# [ 0. 1.]]
e = np.random.random((2,2))
print(e)
# [[ 0.91940167 0.08143941]
# [ 0.68744134 0.87236687]]import numpy as np
def distance_L2(a, b):
"""
:param a - np.ndarray
:param b - np.ndarray
:return float
"""
return ((a-b)**2).sum()
a = np.random.random(4)
print(a)
# array([ 0.62118135, 0.9600108 , 0.84022489, 0.55372924])
b = np.random.random(4)
print(b)
# array([ 0.45873813, 0.12493711, 0.80636291, 0.93912522])
print(distance_L2(a, b))
# 0.87341256692496827import numpy as np
def reshape_to_vector(a):
"""
:param a - np.ndarray
:return np.ndarray
"""
return np.array(a.reshape((a.shape[0]**2, 1)), dtype=np.int16)
a = np.random.random((4,4))
print(a)
# array([[ 0.55206853, 0.30658551, 0.84145866, 0.37926292],
# [ 0.88968549, 0.42673438, 0.47431736, 0.74421548],
# [ 0.0800564 , 0.919614 , 0.46828862, 0.97317616],
# [ 0.28684353, 0.67264068, 0.26134366, 0.41890796]])
print(reshape_to_vector(a))
# array([[ 0.55206853],
# [ 0.30658551],
# [ 0.84145866],
# [ 0.37926292],
# [ 0.88968549],
# [ 0.42673438],
# [ 0.47431736],
# [ 0.74421548],
# [ 0.0800564 ],
# [ 0.919614 ],
# [ 0.46828862],
# [ 0.97317616],
# [ 0.28684353],
# [ 0.67264068],
# [ 0.26134366],
# [ 0.41890796]])import numpy as np
def merge_with_ones_vector(a: np.ndarray) -> np.ndarray:
"""
:param a - np.ndarray
:return np.ndarray
"""
ones_vector = np.ones(a.shape, dtype=np.int16)
return np.concatenate((ones_vector, a), axis=1)
b = np.array([[5],[2],[24]])
c = merge_with_ones_vector(b)
print(c)
# array([[ 1, 5],
# [ 1, 2],
# [ 1, 24]])
import numpy as np
def ols(A, b):
"""
Y = AX + b
:param A - np.ndarray - square block
:param b - np.ndarray - vector
:return np.ndarray, float - coeficients of ols, error
"""
X = np.dot(np.linalg.inv(A.T.dot(A)), A.T.dot(b))
return X, distance_L2(A.dot(X), b)
A = np.array([[4,2,5], [-1,3,-2], [5,-2,4]])
b = np.array([[1],[2],[3]])
X, error = ols(A, b)
print(X)
# array([[ 1.88888889],
# [ 0.33333333],
# [-1.44444444]])
print(error)
# 4.6542793408039697e-29pandas - надає високопродуктивні, прості у використанні структури даних та інструменти аналізу даних в Python.
Основними структурами в pandas є DataFrame i Series.
DataFrame в Python - двовимірна структура даних з колонками потенційно різних типів, які дуже подібні до датафреймів в мові R.
Загалом, можна сказати, що Pandas DataFrame складається з трьох основних компонентів: даних, індексу та стовпців.
DataFrame складається із об'єктів типу Series: одновимірний маркований масив, здатний утримувати будь-який тип даних з мітками осей або індексом.
import pandas as pd
df = pd.DataFrame({
'a': [1,2,3,4],
'b': [True, False, False, True],
'c': ['Ala', 'ma', 'kota', 'Markiza']
})

print(type(df))
# pandas.core.frame.DataFrame

print(type(df.a))
# pandas.core.series.Series
print(df.index)
# RangeIndex(start=0, stop=4, step=1)
print(df)
# a b c
# 0 1 True Ala
# 1 2 False ma
# 2 3 False kota
# 3 4 True Markiza
import pandas as pd
print(df)
# a b c
# 0 1 True Ala
# 1 2 False ma
# 2 3 False kota
# 3 4 True Markiza
print(df[df.b == True])
# a b c
# 0 1 True Ala
# 3 4 True Markiza

print(df[df.c.str.len() >= 3])
# a b c
# 0 1 True Ala
# 2 3 False kota
# 3 4 True Markiza
import pandas as pd
print(df)
# a b c
# 0 1 True Ala
# 1 2 False ma
# 2 3 False kota
# 3 4 True Markiza

c = df.c.str.len() > 3
b = df.b == True
print(c & b)
# 0 False
# 1 False
# 2 False
# 3 True
# dtype: bool

print(df[c & b])
# a b c
# 3 4 True Markiza

print(df.sort_values(by='c'))
# a b c
# 0 1 True Ala
# 3 4 True Markiza
# 2 3 False kota
# 1 2 False ma
import pandas as pd
df = pd.DataFrame({
'a': [1,2,3,None],
'b': [True, False, None, True],
'c': ['Ala', None, 'kota', 'Markiza']
})

print(df)
# a b c
# 0 1.0 True Ala
# 1 2.0 False None
# 2 3.0 None kota
# 3 NaN True Markiza

df2 = df[~pd.isnull(df.a) & ~pd.isnull(df.b)]
print(df2)
# a b c
# 0 1.0 True Ala
# 1 2.0 False None
import pandas as pd
df1 = pd.DataFrame({'a': [1,2], 'b': [0, 6]})
df2 = pd.DataFrame({'a': [7,8], 'b': [1.5, 3]})
df3 = df1.append(df2)
print(df3)
# a b
# 0 1 0.0
# 1 2 6.0
# 0 7 1.5
# 1 8 3.0
print(df3.reset_index(drop=True))
# a b
# 0 1 0.0
# 1 2 6.0
# 2 7 1.5
# 3 8 3.0
"""
Rule to extract partner info to separate table
Example:
input df:
---|-----------------------------------------------------------------------|---
...| p1_deeplink | p1_price | p1_attr1 | p2_deeplink | p2_price | p2_attr2 |...
---|-----------------------------------------------------------------------|---
...| deeplink1.1 | 5.0 | value1.1 | deeplink2.1 | 1.0 | val2.1 |...
---|-----------------------------------------------------------------------|---
...| deeplink1.2 | 7.0 | value1.2 | deeplink2.2 | 4.0 | val2.2 |...
---|-----------------------------------------------------------------------|---
output df:
partner1 has id 1
partner2 has id 2
|---------------------------------------------------------------------|
| product_id | partner_id | deeplink | price | attributes |
|---------------------------------------------------------------------|
| 1 | 1 | deeplink1.1 | 5.0 | {"attr1": value1.1} |
|---------------------------------------------------------------------|
| 2 | 1 | deeplink1.2 | 7.0 | {"attr1": value1.2} |
|---------------------------------------------------------------------|
| 1 | 2 | deeplink2.1 | 1.0 | {"attr2": val2.1} |
|---------------------------------------------------------------------|
| 2 | 2 | deeplink2.2 | 4.0 | {"attr2": val2.2} |
|---------------------------------------------------------------------|
"""import pandas as pd
def apply(self):
result_df = pd.DataFrame()
for partner in Partner.objects.all():
cols = self.columns(partner.name)
if not cols:
continue
result_df = result_df.append(
self.perform_one_partner(partner, cols)
)
return result_df
def perform_one_partner(self, partner, columns):
df = pd.DataFrame({
self.product_id: self.products_pks,
self.partner_id: partner.id
})
for col, attr in columns:
df[attr] = self.df[col]
# keeps all rows with at least 3 non-na cols:
# (partner_id, product_id and one more)
df.dropna(thresh=3, inplace=True)
return self.extract_extra_attrs(df)import pandas as pd
def extract_extra_attrs(self, df: pd.DataFrame):
extra_df = pd.DataFrame()
for col in df.columns:
if col not in self.partner_columns:
extra_df[col] = df[col]
df.drop(col, axis=1, inplace=True)
if extra_df.any().any():
df['attributes'] = json.loads(extra_df.to_json(orient='records'))
return dfMatplotlib - це бібліотека Python для побудови 2D графіків, яка вміє працювати з різноманітними форматами та в інтерактивних середовищах на різних платформах.
import numpy as np
import matplotlib.pyplot as plt
# Fixing random state for reproducibility
np.random.seed(19680801)
mu, sigma = 100, 15
x = mu + sigma * np.random.randn(10000)
# the histogram of the data
n, bins, patches = plt.hist(x, 50, density=True, facecolor='g', alpha=0.75)
plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title('Histogram of IQ')
plt.text(60, .025, r'$\mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)
plt.show()Бібліотека PIL (Python Imaging Library) надає можливості для обробки зображень.
Ця бібліотека надає велику підтримку різноманітних форматів файлів, ефективне внутрішнє представлення та досить потужні можливості обробки зображень.
Основа бібліотеки призначена для швидкого доступу до даних. Вона слугує міцною основою для загального інструменту обробки зображень.
from PIL import Image
im = Image.open("bird.png")
print(im.format, im.size, im.mode)
# PNG (512, 512) RGBA
im.show()from PIL import Image
size = (64, 64)
try:
im = Image.open('bird.png')
im.thumbnail(size)
im.save('bird-thumb.png')
except IOError as e:
print("cannot create thumbnail", e)from PIL import Image
im = Image.open("bird.png")
box = (100, 100, 400, 400)
region = im.crop(box)
region.save('cropped.png')
from PIL import Image
im = Image.open("bird.png")
box = (100, 100, 400, 400)
region = im.crop(box)
region = region.transpose(Image.ROTATE_180)
im.paste(region, box)
im.save('transposed.png')from PIL import ImageFilter
im = Image.open("bird.png")
out = im.filter(ImageFilter.BLUR)
out.save('blured.png')
from PIL import ImageFilter
im = Image.open("bird.png")
r, g, b, a = im.split()
im1 = Image.merge("RGB", (r, g, b))
im1.save('without-a.jpg')import numpy as np
from PIL import ImageFilter
def noise_filter(im):
arr = np.array(im)
noise = np.random.random(arr.shape)
result = np.array(np.round(arr + noise), dtype=np.int8)
return Image.fromarray(result, 'RGBA')
im2 = noise_filter(im)
im2.save('with-noise.png')HTTP for humans
Requests allows you to send organic, grass-fed HTTP/1.1 requests, without the need for manual labor. There’s no need to manually add query strings to your URLs, or to form-encode your POST data. Keep-alive and HTTP connection pooling are 100% automatic, thanks to urllib3.
import requests
response = requests.get('https://api.github.com')
print(response.status_code)
# 200
print(response.headers)
# {
# 'Server': 'GitHub.com',
# 'Date': 'Tue, 14 May 2019 16:36:53 GMT',
# 'Content-Type': 'application/json; charset=utf-8',
# 'X-GitHub-Request-Id': '8E86:5BA4:23FB888:4D8A680:5CDAEEA5',
# ...
# }
print(response.json())
# {
# 'current_user_url': 'https://api.github.com/user',
# 'current_user_authorizations_html_url': 'https://github.com/settings/connections/applications{/client_id}',
# 'authorizations_url': 'https://api.github.com/authorizations',
# ...
# }
import requests
from getpass import getpass
with requests.Session() as session:
session.auth = ('orehush', getpass())
response = session.get('https://api.github.com/user')
print(response.json())
# {
# 'login': 'orehush',
# 'id': 22370432, 'node_id': 'MDQ6VXNlcjIyMzcwNDMy',
# 'avatar_url': 'https://avatars1.githubusercontent.com/u/22370432?v=4',
# 'public_repos': 11,
# 'public_gists': 3,
# 'created_at': '2016-09-22T12:15:26Z',
# 'updated_at': '2019-05-13T13:49:17Z',
# ...
# }
>>> requests.post('https://httpbin.org/post', data={'key':'value'})
>>> requests.put('https://httpbin.org/put', data={'key':'value'})
>>> requests.delete('https://httpbin.org/delete')
>>> requests.head('https://httpbin.org/get')
>>> requests.patch('https://httpbin.org/patch', data={'key':'value'})
>>> requests.options('https://httpbin.org/get')import requests
response = requests.post('https://httpbin.org/post', data={'key':'value'})
print(response.status_code)
# 200
print(response.json())
# {
# 'args': {}, 'data': '', 'files': {}, 'form': {'key': 'value'},
# 'headers': {
# 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Content-Length': '9',
# 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'httpbin.org',
# 'User-Agent': 'python-requests/2.21.0'
# },
# 'json': None,
# 'origin': '93.175.204.45, 93.175.204.45',
# 'url': 'https://httpbin.org/post'
# }
Flask - це легкий веб-додаток WSGI. Він призначений для того, щоб розпочати роботу швидко і легко, з можливістю масштабування до складних додатків. Flask почанався як проста обгортка навколо Werkzeug і Jinja і став одним з найпопулярніших фреймворків веб-додатків Python.
Flask надає пропозиції, як створювати додаток, але не застосовує ніяких залежностей або макет проекту. Розробник самостійно обирає інструменти та бібліотеки, які вони хочуть використовувати. Спільнота надає багато розширень, що полегшує додавання нових функцій.
# hello.py
from flask import Flask
app = Flask(__name__)
@app.route("/")
def hello():
return "Hello World!"$ FLASK_APP=hello.py flask run
* Serving Flask app "hello.py"
* Environment: production
WARNING: Do not use the development server in a production environment.
Use a production WSGI server instead.
* Debug mode: off
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
127.0.0.1 - - [14/May/2019 20:15:40] "GET / HTTP/1.1" 200 -
127.0.0.1 - - [14/May/2019 20:15:40] "GET /favicon.ico HTTP/1.1" 404 -
import telebot
import os
from flask import Flask, request
bot = telebot.TeleBot('{TOKEN}')
server = Flask(__name__)
@bot.message_handler(commands=['start'])
def start(message):
bot.reply_to(message, 'Hello, ' + message.from_user.first_name)
@bot.message_handler(func=lambda message: True, content_types=['text'])
def echo_message(message):
bot.reply_to(message, message.text)
@server.route("/{TOKEN}", methods=['POST'])
def getMessage():
bot.process_new_updates([
telebot.types.Update.de_json(request.stream.read().decode("utf-8"))
])
return "!", 200
@server.route("/")
def webhook():
bot.remove_webhook()
bot.set_webhook(url="https://{DOMAIN}/{TOKEN}")
return "!", 200
server.run(host="0.0.0.0", port=os.environ.get('PORT', 5000))
Sanic - веб-сервер і веб-платформа, написаний щоб бути швидким. Він дозволяє використовувати синтаксис async / await, доданий у Python 3.5, що робить код неблокуючим і швидким.
Мета проекту полягає в тому, щоб забезпечити простий спосіб створення і роботи високопродуктивного HTTP-сервера, який можна легко створювати, розширювати і в кінцевому підсумку масштабувати.
from sanic import Sanic
from sanic.response import json
app = Sanic()
@app.route('/')
async def test(request):
return json({'hello': 'world'})
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000)$ python hello.py
[2019-05-14 21:26:41 +0300] [18182] [INFO] Goin' Fast @ http://0.0.0.0:8000
[2019-05-14 21:26:41 +0300] [18182] [INFO] Starting worker [18182]$ curl -i http://0.0.0.0:8000
HTTP/1.1 200 OK
Connection: keep-alive
Keep-Alive: 5
Content-Length: 17
Content-Type: application/json
{"hello":"world"}from sanic import Sanic
from sanic.response import file
app = Sanic(__name__)
@app.route('/')
async def index(request):
return await file('websocket.html')
@app.websocket('/feed')
async def feed(request, ws):
while True:
data = 'hello!'
print('Server sending: ' + data)
await ws.send(data)
data = await ws.recv()
print('Server received: ' + data)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=8000, debug=True)var ws = new WebSocket('ws://'+document.domain+':'+location.port+'/feed'),
messages = document.createElement('ul');
ws.onmessage = function (event) {
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode('Client received: ' + event.data);
message.appendChild(content);
messages.appendChild(message);
};
document.body.appendChild(messages);
window.setInterval(function() {
data = 'bye!'
ws.send(data);
var messages = document.getElementsByTagName('ul')[0],
message = document.createElement('li'),
content = document.createTextNode('Client sent: ' + data);
message.appendChild(content);
messages.appendChild(message);
}, 1000);$ python ws.py
[2019-05-14 21:40:08 +0300] [19020] [DEBUG]
Sanic
Build Fast. Run Fast.
[2019-05-14 21:40:08 +0300] [19020] [INFO] Goin' Fast @ http://0.0.0.0:8000
[2019-05-14 21:40:09 +0300] [19024] [INFO] Starting worker [19024]
[2019-05-14 21:41:11 +0300] - (sanic.access)[INFO][127.0.0.1:43104]:
GET http://0.0.0.0:8000/ 200 1155
Server sending: hello!
Server received: bye!
Server sending: hello!
Server received: bye!
Server sending: hello!
Server received: bye!
Server sending: hello!
Server received: bye!
Server sending: hello!
[2019-05-14 21:41:16 +0300] [19024] [DEBUG] KeepAlive Timeout.
Closing connection.
Django - це високорівнева веб-платформа Python, яка заохочує до швидкого розвитоку, чистого та прагматичного дизайну. Побудований досвідченими розробниками, він піклується про більшу частину проблем веб-розробки, тому розробник може зосередитися на написанні додатку без необхідності винаходити колесо.
Смішно швидкий.
Django був розроблений, щоб допомогти розробникам створювати додатки від концепції до завершення якнайшвидше.
Заспокійливо безпечний.
Django серйозно ставиться до безпеки і допомагає розробникам уникнути багатьох поширених помилок безпеки.
Надзвичайно масштабований.
Деякі з найбільш завантажених веб-сайтів використовують здатність Django швидко і гнучко масштабувати.
$ mkdir helloworld
$ cd helloworld
$ pip install django==2.2.0
$ django-admin startproject helloworld_project
$ tree
.
├── helloworld_project
│ ├── __init__.py
│ ├── settings.py
│ ├── urls.py
│ └── wsgi.py
└── manage.py
$ python manage.py runserverfrom django.db import models
class Person(models.Model):
name = models.CharField(max_length=128)
def __str__(self):
return self.name
class Group(models.Model):
name = models.CharField(max_length=128)
members = models.ManyToManyField(Person, through='Membership')
def __str__(self):
return self.name
class Membership(models.Model):
person = models.ForeignKey(Person, on_delete=models.CASCADE)
group = models.ForeignKey(Group, on_delete=models.CASCADE)
date_joined = models.DateField()
invite_reason = models.CharField(max_length=64)>>> ringo = Person.objects.create(name="Ringo Starr")
>>> paul = Person.objects.create(name="Paul McCartney")
>>> beatles = Group.objects.create(name="The Beatles")
>>> m1 = Membership(person=ringo, group=beatles,
... date_joined=date(1962, 8, 16),
... invite_reason="Needed a new drummer.")
>>> m1.save()
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>]>
>>> ringo.group_set.all()
<QuerySet [<Group: The Beatles>]>
>>> m2 = Membership.objects.create(person=paul, group=beatles,
... date_joined=date(1960, 8, 1),
... invite_reason="Wanted to form a band.")
>>> beatles.members.all()
<QuerySet [<Person: Ringo Starr>, <Person: Paul McCartney>]>
# Find all the groups with a member whose name starts with 'Paul'
>>> Group.objects.filter(members__name__startswith='Paul')
<QuerySet [<Group: The Beatles>]>
>>> Person.objects.filter(
... group__name='The Beatles',
... membership__date_joined__gt=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>
>>> Person.objects.filter(
... group__name='The Beatles')
... .exclude(
... membership__date_joined__lte=date(1961,1,1))
<QuerySet [<Person: Ringo Starr]>
>>> ringos_membership = Membership.objects.get(group=beatles, person=ringo)
>>> ringos_membership.date_joined
datetime.date(1962, 8, 16)
>>> ringos_membership.invite_reason
'Needed a new drummer.'from django.conf.urls import url, include
from django.contrib.auth.models import User
from rest_framework import serializers, viewsets, routers
# Serializers define the API representation.
class UserSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = User
fields = ('url', 'username', 'email', 'is_staff')
# ViewSets define the view behavior.
class UserViewSet(viewsets.ModelViewSet):
queryset = User.objects.all()
serializer_class = UserSerializer
# Routers provide a way of automatically determining the URL conf.
router = routers.DefaultRouter()
router.register(r'users', UserViewSet)
# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
url(r'^', include(router.urls)),
url(r'^api-auth/', include('rest_framework.urls', namespace='rest_framework'))
]GET /users/
GET /users/{pk}/
POST /users/
PUT /users/{pk}/
PATCH /users/{pk}/
DELETE /users/{pk}/
$ curl -H 'Accept: application/json' -u admin:password http://127.0.0.1:8000/users/
[
{
"url": "http://127.0.0.1:8000/users/1/",
"username": "admin",
"email": "admin@example.com",
"is_staff": true,
}
]Trusted Posts
$ tree api/
api/
├── migrations
│ ├── 0001_initial.py
│ └── __init__.py
├── __init__.py
├── admin.py
├── apps.py
├── filters.py
├── helpers.py
├── models.py
├── permissions.py
├── serializers.py
├── urls.py
└── views.py
from django.contrib.auth.models import User
from django.db import models
from django_extensions.db.models import TimeStampedModel
from api.helpers import get_sub_obj
class InheritanceMixin:
@property
def child(self):
return get_sub_obj(self)
class Author(InheritanceMixin, User):
rating = models.FloatField(default=0)
class Reviewer(InheritanceMixin, User):
level = models.PositiveIntegerField(default=0)
class Tag(models.Model):
name = models.CharField(max_length=100)
def __str__(self):
return self.name
class Post(TimeStampedModel):
class Meta:
ordering = ('-updated', )
title = models.CharField(max_length=255)
body = models.TextField()
tags = models.ManyToManyField(Tag, related_name='posts')
author = models.ForeignKey(Author, models.CASCADE, related_name='posts')
reviewed_by = models.ManyToManyField(Reviewer)
def __str__(self):
return self.title
from django.contrib.auth.models import User
from rest_framework import serializers
from api.models import Tag, Author, Reviewer, Post
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ('id', 'first_name', 'last_name', 'email', )
class AuthorSerializer(UserSerializer):
class Meta:
model = Author
fields = UserSerializer.Meta.fields + ('rating', )
class ReviewerSerializer(UserSerializer):
class Meta:
model = Reviewer
fields = UserSerializer.Meta.fields + ('level', )
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
fields = '__all__'class PostSerializer(serializers.ModelSerializer):
class Meta:
model = Post
fields = '__all__'
read_only_fields = ('reviewed_by', 'updated', 'created', )
author = PresentablePrimaryKeyRelatedField(
presentation_serializer=AuthorSerializer,
default=serializers.CreateOnlyDefault(CurrentChildUserDefault())
)
tags = PresentablePrimaryKeyRelatedField(
presentation_serializer=TagSerializer, many=True
)
reviewed_by = ReviewerSerializer(many=True, read_only=True)
from rest_framework.permissions import IsAuthenticatedOrReadOnly, IsAuthenticated
from api.models import Post
class IsAuthorOrReadOnly(IsAuthenticatedOrReadOnly):
def has_permission(self, request, view):
if request.method == 'post':
return hasattr(request.user, 'author')
return super(IsAuthorOrReadOnly, self).has_permission(request, view)
def has_object_permission(self, request, view, obj: Post):
return (
super(IsAuthorOrReadOnly, self).has_object_permission(request, view, obj) and
hasattr(request.user, 'author') and
obj.author == request.user.author
)
class IsReviewer(IsAuthenticated):
def has_permission(self, request, view):
return (
super(IsReviewer, self).has_permission(request, view) and
hasattr(request.user, 'reviewer')
)
from django_filters import FilterSet
from api.models import Post
class PostFilterSet(FilterSet):
class Meta:
model = Post
fields = ('tags', 'author', 'reviewed_by', )
from rest_framework import viewsets
from rest_framework.decorators import action
from rest_framework.permissions import AllowAny
from rest_framework.response import Response
from api.filters import PostFilterSet
from api.permissions import IsAuthorOrReadOnly, IsReviewer
from api.serializers import *
class TagViewSet(viewsets.ReadOnlyModelViewSet):
"""
List/retrieve tags
"""
queryset = Tag.objects.all()
serializer_class = TagSerializer
permission_classes = (AllowAny, )
class AuthorViewSet(viewsets.ReadOnlyModelViewSet):
"""
List/retrieve authors
"""
queryset = Author.objects.filter(is_active=True)
serializer_class = AuthorSerializer
permission_classes = (AllowAny, )
class ReviewerViewSet(viewsets.ReadOnlyModelViewSet):
"""
List/retrieve experienced reviewers
"""
queryset = Reviewer.objects.filter(is_active=True, level__gte=1)
serializer_class = ReviewerSerializer
permission_classes = (AllowAny, )class PostViewSet(viewsets.ModelViewSet):
"""
CRUD posts
"""
queryset = Post.objects.exclude(is_deleted=True)
serializer_class = PostSerializer
permission_classes = (IsAuthorOrReadOnly, )
filterset_class = PostFilterSet
def perform_destroy(self, instance):
instance.is_deleted = True
instance.save()
@action(detail=True, methods=['put'],
permission_classes=[IsReviewer],
serializer_class=serializers.Serializer)
def approve(self, request, **kwargs):
"""
Endpoint to approve post by reviewer
"""
post = self.get_object()
post.reviewed_by.add(request.user.reviewer)
serializer = PostSerializer(post)
return Response(serializer.data)
from rest_framework.routers import DefaultRouter
from api import views
router = DefaultRouter(trailing_slash='')
router.register('authors', views.AuthorViewSet)
router.register('reviewers', views.ReviewerViewSet)
router.register('tags', views.TagViewSet)
router.register('posts', views.PostViewSet)
urlpatterns = router.urls
from django.contrib import admin
from django.urls import path, include
from rest_framework import permissions
from drf_yasg.views import get_schema_view
from drf_yasg import openapi
schema_view = get_schema_view(
openapi.Info(
title="Posts API",
default_version='v1',
),
public=True,
permission_classes=(permissions.AllowAny,),
)
urlpatterns = [
path('admin/', admin.site.urls),
path('api-auth/', include('rest_framework.urls')),
path('api/', include('api.urls')),
path('swagger/', schema_view.with_ui('swagger', cache_timeout=0), name='swagger-ui'),
path('redoc/', schema_view.with_ui('redoc', cache_timeout=0), name='redoc'),
]
# Install
$ pip install django-allauth
# settings.py
AUTHENTICATION_BACKENDS = (
...
# Needed to login by username in Django admin, regardless of `allauth`
'django.contrib.auth.backends.ModelBackend',
# `allauth` specific authentication methods, such as login by e-mail
'allauth.account.auth_backends.AuthenticationBackend',
...
)
INSTALLED_APPS = (
...
# The following apps are required:
'django.contrib.auth',
'django.contrib.messages',
'django.contrib.sites',
'allauth',
'allauth.account',
'allauth.socialaccount',
# ... include the providers you want to enable:
'allauth.socialaccount.providers.facebook',
)
SITE_ID = 1
# urls.py:
urlpatterns = [
...
url(r'^accounts/', include('allauth.urls')),
...
]
agave
amazon
angellist
asana
auth0
authentiq
azure
baidu
basecamp
battlenet
bitbucket
bitbucket_oauth2
bitly
box
cern
coinbase
dataporten
daum
digitalocean
discord
disqus
douban
doximity
draugiem
dropbox
dwolla
edmodo
eventbrite
eveonline
evernote
facebook
feedly
fivehundredpx
flickr
foursquare
fxa
github
gitlab
globus
google
hubic
instagram
jupyterhub
kakao
line
linkedin
linkedin_oauth2
mailchimp
mailru
meetup
microsoft
naver
nextcloud
odnoklassniki
openid
orcid
patreon
paypal
...
Celery - це асинхронна черга завдань, заснована на передачі розподілених повідомлень. Він орієнтований на операцію в реальному часі, але також підтримує планування (періодичні таски).
Виконавчі блоки, звані завданнями, виконуються одночасно на одному або декількох робочих серверах, використовуючи мультипроцесорність, Eventlet або gevent. Завдання можуть виконуватися асинхронно (у фоновому режимі) або синхронно (очікуючи на виконання).
Celery використовується в продакшині для обробки мільйонів завдань на день.
# celery.py
import os
from celery import Celery
# set the default Django settings module for the 'celery' program.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'project.settings')
app = Celery('project')
# Using a string here means the worker doesn't have to serialize
# the configuration object to child processes.
# - namespace='CELERY' means all celery-related configuration keys
# should have a `CELERY_` prefix.
app.config_from_object('django.conf:settings', namespace='CELERY')
# Load task modules from all registered Django app configs.
app.autodiscover_tasks()
@app.task(bind=True)
def debug_task(self):
print('Request: {0!r}'.format(self.request))# tasks.py
@app.task()
def process_outlook_notifications(calendar_id, event_id, status):
try:
calendar = ExternalCalendar.objects.get(id=calendar_id)
except ExternalCalendar.DoesNotExist:
logger.error('External calendar {} does not exists'.format(calendar_id))
return
try:
calendar.processing_data(
event_id, status, **OutlookAdapter.retrieve(event_id)
)
except Exception as e:
logger.error(e)
# views.py
def calendar_web_hook(request):
sz = HookSerializer(data=request.data)
sz.is_valid(raise_exceptions=True)
process_outlook_notifications.delay(**sz.validated_data)
return HttpResponse('Ok')
Kivy - Бібліотека з відкритим вихідним кодом Python призначена для швидкої розробки додатків, які використовують інноваційні інтерфейси користувача, такі як мультисенсорні програми.
# Install
$ pip install kivy
# app.py
from kivy.app import App
from kivy.uix.button import Button
class TestApp(App):
def build(self):
return Button(text='Hello World')
TestApp().run()Scikit-learn
Scipy
Tensorflow
Keras
Theano
nltk