Skip to content

Instantly share code, notes, and snippets.

View mark-mishyn's full-sized avatar

Mark Mishyn mark-mishyn

View GitHub Profile
def get_phones_from_text(text: str) -> Set[str]:
phone_matches_iterator = re.finditer(r'(\+\d{1,2}\s)?\(?\d{3}\)?[\s.-]?\d{3}[\s.-]?\d{4}', text)
return set((r.group(0) for r in phone_matches_iterator))
def get_emails_from_text(text: str) -> Set[str]:
email_matches_iterator = re.finditer(r'[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+', text)
return set((r.group(0) for r in email_matches_iterator))
class FormatDict(dict):
def __missing__(self, key):
return '{{{}}}'.format(key)
def format_string(string, context: dict) -> str:
"""
Format string without KeyError if key is not present in dict.
>>> format_string('Oh, hi {first_name} {last_name}', {'first_name': 'Mark'})
@mark-mishyn
mark-mishyn / filter_by_birthdays.py
Created March 8, 2019 17:41
Filter Django queryset by birthdays in date range
def filter_by_birthdays(qs, from_date, to_date):
# Build the list of month/day tuples.
dates = []
while from_date < to_date:
dates.append((from_date.month, from_date.day))
from_date += timedelta(days=1)
# Transform each into queryset keyword args.
dates = (dict(
@mark-mishyn
mark-mishyn / order_by_upcoming_birthdays.py
Created March 8, 2019 17:35
Order Django queryset by upcoming birthdays
def order_by_upcoming_birthdays(qs, from_date=None, birthday_field_name='date_of_birth'):
from_date = from_date or now().date()
qs = users_qs.annotate(
month=Extract(birthday_field_name, 'month'),
day=Extract(birthday_field_name, 'day'))
whens = []
for i in range(12):
whens.append(When(month=(from_date + relativedelta(months=i)).month, then=i))
@mark-mishyn
mark-mishyn / generate_strong_password.py
Created March 8, 2019 17:31
generate strong password in Django
import string
from django.utils.crypto import get_random_string
def generate_strong_password(length=12):
allowed_chars = string.digits + string.ascii_letters + '+=~|*_-#'
while True:
password = get_random_string(length=length, allowed_chars=allowed_chars)
if (set(password) & set(string.ascii_lowercase) and
@mark-mishyn
mark-mishyn / django_ORM_append.py
Last active June 13, 2021 15:22
Append value to DB column with Django ORM with 1 QB query
from django.db.models import F, Value
from django.db.models.functions import Concat
# only one SQL query
User.objects.filter(id=user.id).update(description=Concat(F('description'), Value('some note to append')))
@mark-mishyn
mark-mishyn / history_mixin.py
Last active December 13, 2018 15:05
History mixin for Django REST Framework and django-reversions
from django.core.exceptions import FieldDoesNotExist
from django_extensions.db.fields import json
from rest_framework.decorators import list_route, detail_route
from reversion.models import Version
from common.pagination import SmallPagination, HistoryDiffPagination
from history.serializers import HistoryUserSerializer
from history.views import get_serialized_history
@mark-mishyn
mark-mishyn / Django ORM full-text search.py
Last active December 31, 2024 17:57
allows use trigram similarity search with Django and PostgreSQL
from django.contrib.postgres.search import TrigramSimilarity
from django.db.models import Case, When, Q, IntegerField
def filter_by_trigram_similarity(qs, field_name, search_term, similarity=0.15):
if not search_term:
return qs
similarity_name = field_name + '_similarity'
strict_matching_name = field_name + '_strict_matching'
@mark-mishyn
mark-mishyn / Django form errors to messages.py
Last active July 18, 2018 09:50
Simple way to put form errors to django messages
def put_forms_errors_to_messages(request, form, only_first=False):
for field_name, error_msg in form.errors.items():
if field_name == '__all__':
error_msg = error_msg[0]
else:
field = form.fields[field_name]
error_msg = '{}: {}'.format(field.label if field.label else field_name,
error_msg[0].lower())
messages.error(request, error_msg)
if only_first:
@mark-mishyn
mark-mishyn / flat_errors_response.py
Last active June 20, 2017 18:04
DRF Flat Errors Response
"""
Monkey patch for Response class in Django REST Framework.
Original response's data will be accessible by key "data"
and errors have flat format, so it is easier to handle
errors on client side.
"""
from django.utils import six
from rest_framework.response import Response