Как стать автором
Обновить

Комментарии 15

представление redirect можно и нужно сделать через views.generic.RedirectView добавив SingleObjectMixin.

переопределять save модели - такое себе решение. Не запрещено, конечно, но чисткой данных (генерацией short) дожен бы заниматься serializer/форма.

blank=True # поле short_url может быть пустым, предполагается, что наш сервис будет сам генерить короткие ссылки.

не понял, как связано то, что в формах поле ввода будет не обязательное (required=False) с генерацией ссылок.

Для надежности я бы использовал Token.pk как короткую ссылку. Его всегда можно в символы превратить. Кстати, название модели, рекомендуется сделать Token, единственное число.

Круто! Спасибо.

по "blank=True" я имел в виду, что мы можем как генерить короткую ссылку на стороне приложения, так и установить ее самостоятельно в случае если такая ссылка свободна.

Неа))

Фидбэк дали? Что не понравилось?

Нет, сначала сказали что дадут фидбек, но потом просто написали, что изучили тестовое задание и поняли, что знаний у меня пока маловато.

Это на джуна тестовое?

token.requests_count += 1  # добавляем 1 к счетчику в случае удачного извлечения токена
token.save() # сохраняем изменный экземпляр токена в БД 

Я не особо хорош в django, но в нашем тесте про url shortener это было сигналом того, что человек не знает что бывают race conditions. Попробуйте сделать 1000 запросов с concurrency 5 с помощью siege и посмотреть результат. Что-то мне подсказывает, что это будет не 1000

Race conditions? В этом синхронном коде?

А кто сказал что app server запустит только один поток?

Привет!

Пару советов для дальнейшего успешного поиска работы:

  1. Используй сразу python poetry + Dockerfile + docker-compose. Сейчас это такие же стандарты, как знание git. Дадут тебе +15 очков на собеседовании.

  2. class Tokens(models.Model) -> class Token(models.Model)

  3. settings.CHARACTERS = string.ascii_letters + string.ascii_digits +5 очков

  4. Вместо цикла while True с filter() query надо использовать try: Model.objects.create() / except IntegrityError - так будет в 99.9% случаев только один запрос. +30 очков

  5. token.requests_count += 1 -> Models.objects.filter().update(requests_count=F("requests_count")+1) +20 очков

  6. Вынести код из save() в отдельный модуль services.create_token . +15 очков

  7. Можно вместо рандомайзера использовать hash от pk, но это так уже, когда совсем делать нечего :) Нашел в одном из своих старых проектов:
    hashlib.shake_128(user_id.encode("utf-8")).hexdigest(3).upper()

ну, если говорим про django тогда уж:

  1. Очень субъективно. Я, как наниматель, а я наниматель, скорее поморщусь, чем порадуюсь появлению доп зависимостей в проекте.

  1. settings.CHARACTERS = django.utils.baseconv.BASE62_ALPHABET

    или

    settings.CHARACTERS = django.utils.crypto.RANDOM_STRING_CHARS

    4.-5. Вместо этого всего использовать метод Data Manager, точнее порожденной им производной класса queryset.

    1. Services и прочие заблуждения гексагональной архитектуры. Очень спорно для Django. По мне - см п. 4-5

Ох, я был в обоих лагерях "services vs managers". :)

Для больших проектов 100+ моделей обычно выбираю services последнее время. На практике поддерживать service, где и python логика и ORM в одном месте - легче. Да и распиливать потом - одно удовольствие. Но для маленьких проектов, как у автора - согласен, managers предпочтительнее и чище.

В любом случае вердикт один - нужно выносить из save().

Круто! Большое спасибо!
Да, перед отправкой на проверку я все закатал в Dockerfile + docker-compose и развернул в Я.Облаке чтобы сервис работал.

А вот это не до конца понял. Мы же по сути делаем тоже самое, только код становится более громоздским и хуже читается.
token.requests_count += 1 -> Models.objects.filter().update(requests_count=F("requests_count")+1)

Инкремент счетчика происходит на уровне базы данных.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Истории