From c3307c968a1d78469a0c97a5ca5b27f0a959ee49 Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Wed, 20 Nov 2024 13:49:57 +0500
Subject: [PATCH 1/9] configure postgresql search system
---
apps/blog/filters.py | 14 +
apps/blog/utils.py | 34 +-
apps/users/api_endpoints/users/User/tests.py | 3 +
.../api_endpoints/users/UserProfile/tests.py | 22 +
search_system.md | 489 ++++++++++++++++++
templates/blog/home.html | 2 +-
6 files changed, 554 insertions(+), 10 deletions(-)
create mode 100644 apps/blog/filters.py
create mode 100644 search_system.md
diff --git a/apps/blog/filters.py b/apps/blog/filters.py
new file mode 100644
index 0000000..92a246d
--- /dev/null
+++ b/apps/blog/filters.py
@@ -0,0 +1,14 @@
+import django_filters
+
+from .models import Post
+
+
+class PostFilter(django_filters.FilterSet):
+ title = django_filters.CharFilter(lookup_expr="icontains")
+ description = django_filters.CharFilter(lookup_expr="icontains")
+ content = django_filters.CharFilter(lookup_expr="icontains")
+ created_at = django_filters.DateFromToRangeFilter()
+
+ class Meta:
+ model = Post
+ fields = ['title', 'description', 'content', 'created_at']
diff --git a/apps/blog/utils.py b/apps/blog/utils.py
index 40c3a10..069bf08 100644
--- a/apps/blog/utils.py
+++ b/apps/blog/utils.py
@@ -1,23 +1,36 @@
from django.db.models import QuerySet
from django.db.models import Q
-from django.core.paginator import Paginator, Page, EmptyPage, PageNotAnInteger
+from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
+from django.core.paginator import Paginator, Page, EmptyPage, PageNotAnInteger, InvalidPage
+from django.conf import settings
from .models import PostLike, PostDislike, Post, PostComment
def get_search_model_queryset(
- model_queryset: QuerySet, search_query: str = None
+ model_queryset: QuerySet, query: str = None
) -> QuerySet:
- if not search_query:
+ if not query:
return model_queryset
- search_query = model_queryset.filter(
- Q(title__icontains=search_query)
- | Q(description__icontains=search_query)
- | Q(content__icontains=search_query)
- )
+ search_vector = SearchVector("title", "description", "content")
+ search_query = SearchQuery(query)
- return search_query
+ if settings.DATABASES['default']['ENGINE'] == 'django.db.backends.postgresql':
+ # PostgreSQL search
+ queryset = model_queryset.annotate(
+ search=search_vector,
+ rank=SearchRank(search_vector, search_query),
+ ).filter(search=search_query).order_by('-rank')
+ else:
+ # SQLite3 search
+ queryset = model_queryset.filter(
+ Q(title__icontains=query)
+ | Q(description__icontains=query)
+ | Q(content__icontains=query)
+ )
+
+ return queryset
def get_pagination_obj(model_queryset: QuerySet, page: int = 1, size: int = 4) -> Page:
@@ -29,6 +42,9 @@ def get_pagination_obj(model_queryset: QuerySet, page: int = 1, size: int = 4) -
except PageNotAnInteger:
page_obj = paginator.page(1)
+ except InvalidPage:
+ page_obj = paginator.page(1)
+
except EmptyPage:
page_obj = paginator.page(paginator.num_pages)
diff --git a/apps/users/api_endpoints/users/User/tests.py b/apps/users/api_endpoints/users/User/tests.py
index d8c4c7c..3c3639f 100644
--- a/apps/users/api_endpoints/users/User/tests.py
+++ b/apps/users/api_endpoints/users/User/tests.py
@@ -102,3 +102,6 @@ def _create_user():
_check_user_error_field()
_check_user_passwords_field()
_create_user()
+
+ def test_api_user_update(self):
+ pass
\ No newline at end of file
diff --git a/apps/users/api_endpoints/users/UserProfile/tests.py b/apps/users/api_endpoints/users/UserProfile/tests.py
index e69de29..899736f 100644
--- a/apps/users/api_endpoints/users/UserProfile/tests.py
+++ b/apps/users/api_endpoints/users/UserProfile/tests.py
@@ -0,0 +1,22 @@
+from rest_framework.test import APITestCase
+from rest_framework_simplejwt.tokens import RefreshToken
+from apps.users.models import UserProfile, User
+
+
+class UserProfileApiTestCase(APITestCase):
+ def setUp(self) -> None:
+ self.username = "Admin"
+ self.email = "admin@gmail.com"
+ self.password = "password"
+ user = User.objects.create(
+ username=self.username,
+ email=self.email,
+ )
+ user.set_password(self.password)
+ user.save()
+ self.user = user
+ refresh = RefreshToken.for_user(self.user)
+ self.token = str(refresh.access_token)
+ return super().setUp()
+
+
\ No newline at end of file
diff --git a/search_system.md b/search_system.md
new file mode 100644
index 0000000..303e55e
--- /dev/null
+++ b/search_system.md
@@ -0,0 +1,489 @@
+Для создания продвинутой поисковой системы в Django есть несколько возможностей, начиная с базового поиска с использованием фильтрации по полям и заканчивая интеграцией с мощными поисковыми движками, такими как Elasticsearch или Solr. Вот несколько основных методов и подходов для разных уровней сложности:
+
+### 1. **Базовый поиск с использованием `icontains` в `filter`**
+ Это самый простой способ поиска, где вы можете использовать `QuerySet` для фильтрации объектов по полям:
+
+ ```python
+ # models.py
+ from django.db import models
+
+ class Post(models.Model):
+ title = models.CharField(max_length=200)
+ content = models.TextField()
+ created_at = models.DateTimeField(auto_now_add=True)
+
+ # views.py
+ from django.shortcuts import render
+ from .models import Post
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = Post.objects.filter(title__icontains=query) | Post.objects.filter(content__icontains=query)
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+ Здесь `icontains` позволяет осуществлять поиск по подстроке без учета регистра.
+
+### 2. **Поиск с использованием библиотеки Django ORM для полнотекстового поиска**
+
+ Django поддерживает встроенный полнотекстовый поиск для баз данных PostgreSQL, начиная с Django 1.10. Этот метод позволяет вам находить документы по релевантности.
+
+ ```python
+ # views.py
+ from django.contrib.postgres.search import SearchQuery, SearchRank, SearchVector
+ from .models import Post
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ vector = SearchVector('title', 'content')
+ search_query = SearchQuery(query)
+ posts = Post.objects.annotate(rank=SearchRank(vector, search_query)).filter(rank__gte=0.3).order_by('-rank')
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+### 3. **Использование Django `django-filter` для фильтрации**
+ `django-filter` помогает создать форму поиска и фильтрации с использованием Django ORM, включая фильтрацию по дате и другим полям.
+
+ ```python
+ # filters.py
+ import django_filters
+ from .models import Post
+
+ class PostFilter(django_filters.FilterSet):
+ title = django_filters.CharFilter(lookup_expr='icontains')
+ content = django_filters.CharFilter(lookup_expr='icontains')
+ created_at = django_filters.DateFromToRangeFilter()
+
+ class Meta:
+ model = Post
+ fields = ['title', 'content', 'created_at']
+ ```
+
+ В views:
+
+ ```python
+ # views.py
+ from django.shortcuts import render
+ from .models import Post
+ from .filters import PostFilter
+
+ def search_posts(request):
+ post_filter = PostFilter(request.GET, queryset=Post.objects.all())
+ return render(request, 'search_results.html', {'filter': post_filter})
+ ```
+
+### 4. **Расширенный поиск с использованием Elasticsearch**
+ Если вам нужно поддерживать масштабируемый и быстрый поиск по сложным запросам, то стоит использовать Elasticsearch. Для интеграции можно воспользоваться библиотекой `django-elasticsearch-dsl`.
+
+ 1. Установите Elasticsearch и `django-elasticsearch-dsl`:
+
+ ```bash
+ pip install django-elasticsearch-dsl
+ ```
+
+ 2. Настройте индекс для модели `Post`.
+
+ ```python
+ # documents.py
+ from django_elasticsearch_dsl import Document
+ from django_elasticsearch_dsl.registries import registry
+ from .models import Post
+
+ @registry.register_document
+ class PostDocument(Document):
+ class Index:
+ name = 'posts'
+
+ class Django:
+ model = Post
+ fields = [
+ 'title',
+ 'content',
+ 'created_at',
+ ]
+ ```
+
+ 3. В views можно использовать `PostDocument` для поиска:
+
+ ```python
+ # views.py
+ from django.shortcuts import render
+ from .documents import PostDocument
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = PostDocument.search().query("multi_match", query=query, fields=['title', 'content'])
+ else:
+ posts = PostDocument.search()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+### 5. **Фильтрация с использованием Django Haystack**
+ Haystack – это еще один инструмент для создания поисковых систем, который поддерживает несколько движков, включая Elasticsearch, Solr и Whoosh.
+
+ 1. Установите Django Haystack и поисковый движок (например, Whoosh):
+
+ ```bash
+ pip install django-haystack whoosh
+ ```
+
+ 2. Настройте индекс в `search_indexes.py`:
+
+ ```python
+ # search_indexes.py
+ from haystack import indexes
+ from .models import Post
+
+ class PostIndex(indexes.SearchIndex, indexes.Indexable):
+ text = indexes.CharField(document=True, use_template=True)
+ title = indexes.CharField(model_attr='title')
+ content = indexes.CharField(model_attr='content')
+
+ def get_model(self):
+ return Post
+ ```
+
+ 3. Создайте шаблон для индексации данных (`templates/search/indexes/yourapp/post_text.txt`):
+
+ ```jinja
+ {{ object.title }}
+ {{ object.content }}
+ ```
+
+ 4. Настройте поиск в views:
+
+ ```python
+ from haystack.query import SearchQuerySet
+ from django.shortcuts import render
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = SearchQuerySet().filter(content=query)
+ else:
+ posts = SearchQuerySet().all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+### Заключение
+Выбор подхода зависит от ваших требований и масштабов проекта:
+
+- Для небольших и средних проектов базовый поиск и фильтрация через `icontains` или `django-filter` может быть достаточным.
+- Для продвинутого полнотекстового поиска стоит использовать PostgreSQL или Elasticsearch.
+- Для комплексных решений с поддержкой различных движков лучше использовать Haystack.
+
+---
+Если вы хотите использовать Elasticsearch или PostgreSQL для продвинутого поиска, вам нужно учитывать следующие моменты:
+
+1. **PostgreSQL полнотекстовый поиск** будет работать только с PostgreSQL. Если вы поменяете базу данных на SQLite, MySQL или другую, этот метод перестанет работать, так как полнотекстовый поиск на уровне базы данных — это функция, специфичная для PostgreSQL.
+
+2. **Elasticsearch** же работает независимо от базы данных, потому что это отдельный поисковый движок, а не часть вашей основной базы данных. Это значит, что вы можете использовать любую базу данных (включая SQLite) вместе с Elasticsearch, так как данные для поиска хранятся в индексе Elasticsearch и не зависят от структуры самой базы данных.
+
+### Как это настроить, чтобы работало с любой базой данных
+
+#### 1. **Использование Elasticsearch как основного поискового инструмента**
+ Вы можете использовать любую базу данных для хранения основной информации, а для поиска по этой информации полагаться на Elasticsearch. Процесс будет выглядеть так:
+
+ 1. **Подключение и настройка Elasticsearch.** Убедитесь, что Elasticsearch установлен и настроен. После этого нужно создать документ, который будет индексировать вашу модель Django.
+
+ ```python
+ # documents.py
+ from django_elasticsearch_dsl import Document
+ from django_elasticsearch_dsl.registries import registry
+ from .models import Post
+
+ @registry.register_document
+ class PostDocument(Document):
+ class Index:
+ name = 'posts'
+
+ class Django:
+ model = Post
+ fields = [
+ 'title',
+ 'content',
+ 'created_at',
+ ]
+ ```
+
+ 2. **Настройка views для поиска с Elasticsearch.** После того, как документ настроен, создайте представление (`view`), которое будет отправлять поисковый запрос в Elasticsearch.
+
+ ```python
+ # views.py
+ from django.shortcuts import render
+ from .documents import PostDocument
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = PostDocument.search().query("multi_match", query=query, fields=['title', 'content'])
+ else:
+ posts = PostDocument.search()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+ 3. **Автоматическое обновление индексов Elasticsearch при изменении данных.** Если данные в базе данных изменяются, необходимо синхронизировать их с Elasticsearch, чтобы индексы всегда были актуальны. Для этого используйте сигналы (`signals`) или настройте пакет `django-elasticsearch-dsl` для автоматической синхронизации.
+
+#### 2. **Fallback для баз данных без полнотекстового поиска**
+ Если Elasticsearch по какой-то причине недоступен, вы можете использовать базовую фильтрацию с помощью `icontains` для других баз данных, например:
+
+ ```python
+ # views.py
+ from django.shortcuts import render
+ from django.conf import settings
+ from .documents import PostDocument
+ from .models import Post
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ if settings.USE_ELASTICSEARCH: # Используем Elasticsearch
+ posts = PostDocument.search().query("multi_match", query=query, fields=['title', 'content'])
+ else: # Используем базовую фильтрацию с icontains
+ posts = Post.objects.filter(title__icontains=query) | Post.objects.filter(content__icontains=query)
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+### Преимущества и недостатки подхода
+
+| Подход | Преимущества | Недостатки |
+|------------------------------|--------------------------------------------------------|-----------------------------------------------------|
+| **Elasticsearch** | Независимость от базы данных, мощный и гибкий поиск | Требуется отдельная установка и поддержка сервера |
+| **PostgreSQL полнотекстовый**| Удобная интеграция с Django ORM, нет доп. зависимостей | Поддерживается только PostgreSQL |
+| **SQLite / MySQL + icontains** | Легко настраивается, работает с любой БД | Ограниченный поиск, менее точные и гибкие результаты|
+
+Таким образом, оптимально использовать Elasticsearch как независимый поисковый движок для обеспечения максимальной гибкости и совместимости с любой базой данных.
+
+---
+Да, вы правы — для использования Elasticsearch требуется либо установка его на компьютер, либо поднятие контейнера Docker. Если хотите обойтись без установки Elasticsearch, но всё равно нужен продвинутый поиск, вот несколько вариантов:
+
+### Варианты для обхода Elasticsearch
+
+1. **Использование PostgreSQL для полнотекстового поиска (только PostgreSQL)**:
+ Если ваша база данных — PostgreSQL, его встроенные инструменты для полнотекстового поиска предоставляют хорошие возможности, хотя и менее мощные, чем у Elasticsearch.
+
+ ```python
+ # views.py
+ from django.contrib.postgres.search import SearchVector
+ from .models import Post
+
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = Post.objects.annotate(search=SearchVector('title', 'content')).filter(search=query)
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+ Этот подход работает на уровне базы данных и не требует установки дополнительных сервисов, но он совместим только с PostgreSQL.
+
+2. **Использование Django ORM с `__icontains` для упрощённого поиска**:
+ Это самый простой способ и не требует использования каких-либо специфичных баз данных. Этот метод не столь мощный, как Elasticsearch, но позволит осуществить базовый поиск по текстовым полям.
+
+ ```python
+ def search_posts(request):
+ query = request.GET.get('q', '')
+ if query:
+ posts = Post.objects.filter(title__icontains=query) | Post.objects.filter(content__icontains=query)
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+ ```
+
+ Этот метод работает с любой базой данных (SQLite, MySQL, PostgreSQL и др.) и позволяет организовать простой поиск, но без ранжирования или сложных запросов.
+
+3. **Использование Django-Haystack (совместим с SQLite)**:
+ Библиотека Django Haystack поддерживает несколько поисковых движков, включая базовые текстовые индексы. Это позволит реализовать простой индексный поиск, совместимый с SQLite и другими базами.
+
+ ```bash
+ pip install django-haystack
+ ```
+
+ Пример настройки Haystack с SQLite:
+
+ ```python
+ # settings.py
+ INSTALLED_APPS = [
+ # ...,
+ 'haystack',
+ ]
+
+ HAYSTACK_CONNECTIONS = {
+ 'default': {
+ 'ENGINE': 'haystack.backends.simple_backend.SimpleEngine',
+ },
+ }
+ ```
+
+ После этого можно создать индекс для модели и использовать Haystack для поиска. Этот метод подходит для базового поиска, но с ограниченной функциональностью.
+
+### Какой вариант лучше выбрать
+
+- Если у вас **PostgreSQL**, лучше всего использовать его встроенные средства полнотекстового поиска.
+- Если ваша база данных **SQLite** или другая, и вам нужен продвинутый поиск, **Django-Haystack с SimpleEngine** будет наилучшим выбором для базового поиска без установки дополнительных сервисов.
+- Если достаточно простого поиска и у вас ограниченные требования к функциональности, используйте **`icontains`** — это самый простой и универсальный метод.
+
+Каждый из этих методов позволит вам обойтись без установки Elasticsearch, обеспечивая подходящий уровень поиска для вашего проекта.
+---
+В Django тоже можно реализовать полнотекстовый поиск с PostgreSQL, используя его встроенные возможности и интеграцию с `django.contrib.postgres.search`. Это приложение добавляет поддержку полнотекстового поиска для полей в PostgreSQL и обеспечивает удобные классы и функции, чтобы интегрировать поисковые запросы на уровне ORM. Вот полное объяснение того, как это сделать.
+
+### 1. Установка PostgreSQL в качестве основной базы данных
+
+Прежде чем использовать полнотекстовый поиск, нужно убедиться, что Django настроен на использование PostgreSQL:
+
+```python
+# settings.py
+DATABASES = {
+ 'default': {
+ 'ENGINE': 'django.db.backends.postgresql',
+ 'NAME': 'your_db_name',
+ 'USER': 'your_db_user',
+ 'PASSWORD': 'your_password',
+ 'HOST': 'localhost',
+ 'PORT': '5432',
+ }
+}
+```
+
+### 2. Основные классы и функции для полнотекстового поиска
+
+Django предоставляет несколько ключевых классов и функций для работы с полнотекстовым поиском в PostgreSQL:
+
+- `SearchVector`: позволяет выбрать, какие поля модели использовать для поиска.
+- `SearchQuery`: создает поисковый запрос.
+- `SearchRank`: обеспечивает ранжирование результатов поиска.
+- `SearchHeadline`: выделяет поисковые термины в результатах.
+
+### 3. Пример модели и конфигурации полнотекстового поиска
+
+Допустим, у нас есть модель `Post` с полями `title` и `content`, и мы хотим выполнить полнотекстовый поиск по этим полям.
+
+```python
+# models.py
+from django.db import models
+
+class Post(models.Model):
+ title = models.CharField(max_length=255)
+ content = models.TextField()
+
+ def __str__(self):
+ return self.title
+```
+
+### 4. Настройка простого поиска с `SearchVector` и `SearchQuery`
+
+Теперь можно создать представление, которое будет искать по полям `title` и `content` с использованием `SearchVector` и `SearchQuery`.
+
+```python
+# views.py
+from django.contrib.postgres.search import SearchVector, SearchQuery
+from django.shortcuts import render
+from .models import Post
+
+def search_posts(request):
+ query = request.GET.get('q')
+ if query:
+ search_vector = SearchVector('title', 'content')
+ search_query = SearchQuery(query)
+ posts = Post.objects.annotate(search=search_vector).filter(search=search_query)
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+```
+
+- `SearchVector('title', 'content')` объединяет оба поля в один вектор для поиска.
+- `SearchQuery(query)`: принимает поисковый запрос, который мы будем сравнивать с вектором.
+
+### 5. Ранжирование результатов поиска с `SearchRank`
+
+Для сортировки результатов по релевантности используем `SearchRank`.
+
+```python
+from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank
+
+def search_posts(request):
+ query = request.GET.get('q')
+ if query:
+ search_vector = SearchVector('title', 'content')
+ search_query = SearchQuery(query)
+ posts = Post.objects.annotate(
+ rank=SearchRank(search_vector, search_query)
+ ).filter(search=search_query).order_by('-rank')
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+```
+
+Теперь результаты будут отсортированы по релевантности (от более релевантных к менее релевантным).
+
+### 6. Выделение ключевых слов в результатах с `SearchHeadline`
+
+`SearchHeadline` можно использовать для выделения поисковых терминов в тексте. Это может быть полезно для подсветки ключевых слов в результатах поиска.
+
+```python
+from django.contrib.postgres.search import SearchVector, SearchQuery, SearchRank, SearchHeadline
+
+def search_posts(request):
+ query = request.GET.get('q')
+ if query:
+ search_vector = SearchVector('title', 'content')
+ search_query = SearchQuery(query)
+ posts = Post.objects.annotate(
+ rank=SearchRank(search_vector, search_query),
+ headline=SearchHeadline('content', search_query) # Добавляем выделение слов
+ ).filter(search=search_query).order_by('-rank')
+ else:
+ posts = Post.objects.all()
+ return render(request, 'search_results.html', {'posts': posts, 'query': query})
+```
+
+Теперь в каждом объекте `Post` будет атрибут `headline`, в котором выделены найденные слова.
+
+### 7. Использование разных языков и конфигураций поиска
+
+По умолчанию используется английская конфигурация. Чтобы изменить это, можно передать дополнительный аргумент:
+
+```python
+search_vector = SearchVector('title', 'content', config='russian')
+search_query = SearchQuery(query, config='russian')
+```
+
+### Полный пример шаблона
+
+```html
+
+
Search Results for "{{ query }}"
+{% for post in posts %}
+
+
{{ post.title }}
+
{{ post.headline|safe }}
+
+{% empty %}
+ No results found.
+{% endfor %}
+```
+
+### Преимущества и ограничения
+
+#### Преимущества:
+- **Глубокая интеграция** с ORM Django.
+- Поддержка **ранжирования и выделения** ключевых слов.
+- **Настройка языка** для корректной обработки разных языков.
+
+#### Ограничения:
+- Поддерживается только **PostgreSQL**.
+- Полнотекстовый поиск требует **GIN-индексации** для оптимизации скорости.
+
+### Заключение
+
+Используя `django.contrib.postgres.search`, можно организовать мощную систему полнотекстового поиска прямо на уровне ORM Django, включая ранжирование, подсветку ключевых слов и настройку языков.
\ No newline at end of file
diff --git a/templates/blog/home.html b/templates/blog/home.html
index 05b72dc..72db7ba 100644
--- a/templates/blog/home.html
+++ b/templates/blog/home.html
@@ -1,4 +1,4 @@
-
+{% load blog_tags %}
From 27ff867dad3d0a29080ac0e3f10364b1eda35f2d Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 12:49:21 +0500
Subject: [PATCH 2/9] change simple jwt config
---
core/config/jwt.py | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/core/config/jwt.py b/core/config/jwt.py
index dba6029..bf6f3aa 100644
--- a/core/config/jwt.py
+++ b/core/config/jwt.py
@@ -16,8 +16,8 @@
SIMPLE_JWT = {
- "ACCESS_TOKEN_LIFETIME": timedelta(days=7),
- "REFRESH_TOKEN_LIFETIME": timedelta(days=31),
+ "ACCESS_TOKEN_LIFETIME": timedelta(days=1),
+ "REFRESH_TOKEN_LIFETIME": timedelta(days=7),
"ROTATE_REFRESH_TOKENS": True,
"BLACKLIST_AFTER_ROTATION": True,
"UPDATE_LAST_LOGIN": False,
@@ -35,8 +35,15 @@
"USER_AUTHENTICATION_RULE": "rest_framework_simplejwt.authentication.default_user_authentication_rule",
"AUTH_TOKEN_CLASSES": ("rest_framework_simplejwt.tokens.AccessToken",),
"TOKEN_TYPE_CLAIM": "token_type",
+ "TOKEN_USER_CLASS": "rest_framework_simplejwt.models.TokenUser",
"JTI_CLAIM": "jti",
"SLIDING_TOKEN_REFRESH_EXP_CLAIM": "refresh_exp",
- "SLIDING_TOKEN_LIFETIME": timedelta(days=7),
- "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=31),
+ "SLIDING_TOKEN_LIFETIME": timedelta(days=60),
+ "SLIDING_TOKEN_REFRESH_LIFETIME": timedelta(days=1),
+ "TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainPairSerializer",
+ "TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSerializer",
+ "TOKEN_VERIFY_SERIALIZER": "rest_framework_simplejwt.serializers.TokenVerifySerializer",
+ "TOKEN_BLACKLIST_SERIALIZER": "rest_framework_simplejwt.serializers.TokenBlacklistSerializer",
+ "SLIDING_TOKEN_OBTAIN_SERIALIZER": "rest_framework_simplejwt.serializers.TokenObtainSlidingSerializer",
+ "SLIDING_TOKEN_REFRESH_SERIALIZER": "rest_framework_simplejwt.serializers.TokenRefreshSlidingSerializer",
}
From 5d30d52d5d3872656bede41754c0a183feffe9e0 Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 12:59:16 +0500
Subject: [PATCH 3/9] add unfold, modeltranslation
---
core/config/apps.py | 9 +++++++++
core/config/unfold.py | 0
core/config/unfold_navigation.py | 0
requirements.txt | 4 ++++
4 files changed, 13 insertions(+)
create mode 100644 core/config/unfold.py
create mode 100644 core/config/unfold_navigation.py
diff --git a/core/config/apps.py b/core/config/apps.py
index 83de4a9..6f92d27 100644
--- a/core/config/apps.py
+++ b/core/config/apps.py
@@ -17,6 +17,15 @@
]
THIRD_PARTY_APPS = [
+ "unfold",
+ "unfold.contrib.filters",
+ "unfold.contrib.forms",
+ "unfold.contrib.import_export",
+ "unfold.contrib.guardian",
+ "unfold.contrib.simple_history",
+ "modeltranslation",
+ "drf_spectacular",
+ "drf_spectacular_sidecar",
"rest_framework",
"rest_framework_simplejwt",
"rest_framework_simplejwt.token_blacklist",
diff --git a/core/config/unfold.py b/core/config/unfold.py
new file mode 100644
index 0000000..e69de29
diff --git a/core/config/unfold_navigation.py b/core/config/unfold_navigation.py
new file mode 100644
index 0000000..e69de29
diff --git a/requirements.txt b/requirements.txt
index 73ed40d..19e3539 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -9,3 +9,7 @@ markdown2==2.5.1
pillow==10.4.0
psycopg2-binary==2.9.10
python-dotenv==1.0.1
+django-unfold
+django-modeltranslation==0.18.11
+drf-spectacular==0.27.1
+drf-spectacular-sidecar==2024.3.4
\ No newline at end of file
From 883370a31f42e6408b0fa5fb0900425ea356bee7 Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 13:23:40 +0500
Subject: [PATCH 4/9] add rosetta
---
apps/users/middleware.py | 1 +
core/config/apps.py | 7 +++++++
core/settings/base.py | 15 +++++++++++++--
core/urls.py | 7 ++++---
manage.py | 5 +----
requirements.txt | 3 ++-
6 files changed, 28 insertions(+), 10 deletions(-)
diff --git a/apps/users/middleware.py b/apps/users/middleware.py
index 656cb40..6d457c2 100644
--- a/apps/users/middleware.py
+++ b/apps/users/middleware.py
@@ -10,6 +10,7 @@
class JWTAuthMiddleware(MiddlewareMixin):
def process_request(self, request):
+ # If admin auth for session
if request.path.startswith("/admin"):
return
diff --git a/core/config/apps.py b/core/config/apps.py
index 6f92d27..ccdf6be 100644
--- a/core/config/apps.py
+++ b/core/config/apps.py
@@ -17,16 +17,23 @@
]
THIRD_PARTY_APPS = [
+ # Admin panel
"unfold",
"unfold.contrib.filters",
"unfold.contrib.forms",
"unfold.contrib.import_export",
"unfold.contrib.guardian",
"unfold.contrib.simple_history",
+ # Translation
"modeltranslation",
+ # Translation pannel
+ "rosetta",
+ # DRF Swaggers
"drf_spectacular",
"drf_spectacular_sidecar",
+ # Rest Framework
"rest_framework",
+ # Rest Framework JWT (Json web token)s
"rest_framework_simplejwt",
"rest_framework_simplejwt.token_blacklist",
]
diff --git a/core/settings/base.py b/core/settings/base.py
index 82bd896..a3b406e 100644
--- a/core/settings/base.py
+++ b/core/settings/base.py
@@ -2,6 +2,8 @@
from pathlib import Path
+from django.utils.translation import gettext_lazy
+
from core.config import * # noqa
from dotenv import load_dotenv
@@ -28,7 +30,7 @@
"django.contrib.auth.middleware.AuthenticationMiddleware",
"django.contrib.messages.middleware.MessageMiddleware",
"django.middleware.clickjacking.XFrameOptionsMiddleware",
- "apps.users.middleware.JWTAuthMiddleware",
+ "apps.users.middleware.JWTAuthMiddleware", # My Jwt Auth Middleware
]
ROOT_URLCONF = "core.urls"
@@ -81,10 +83,19 @@
TIME_ZONE = "Asia/Tashkent"
USE_I18N = True
-# USE_L10N = True
USE_TZ = True
+gettext = lambda s: gettext_lazy(s)
+
+LANGUAGES = (
+ ("ru", gettext("Russia")),
+ ("en", gettext("English")),
+ ("uz", gettext("Uzbek")),
+)
+
+LOCALE_PATHS = [os.path.join(BASE_DIR, "locale")]
+
LOGIN_URL = "/users/login/"
LOGIN_REDIRECT_URL = "/"
diff --git a/core/urls.py b/core/urls.py
index 2eb33a0..cbb25fa 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -1,4 +1,5 @@
from django.conf.urls import handler400, handler403, handler404, handler500 # noqa
+from django.conf.urls.i18n import i18n_patterns # noqa: F401
from django.conf.urls.static import static
from django.conf import settings
@@ -24,6 +25,7 @@
# URLs
urlpatterns = [
path("admin/", admin.site.urls),
+ path("i18n", include("django.conf.urls.i18n")),
path("", include("apps.blog.urls", namespace="blog")),
path("users/", include("apps.users.urls", namespace="users")),
path("robots.txt", TemplateView.as_view(template_name="bunin/robots.txt")),
@@ -43,9 +45,8 @@
path("api/v1/blogs/", include(blog_api_router.urls)),
]
-if settings.DEBUG:
- urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
- urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
+urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
handler400 = "apps.shared.views.bad_request_view" # noqa
diff --git a/manage.py b/manage.py
index b67adc1..a2ee85e 100644
--- a/manage.py
+++ b/manage.py
@@ -1,5 +1,3 @@
-#!/usr/bin/env python
-"""Django's command-line utility for administrative tasks."""
import os
import sys
@@ -9,8 +7,7 @@
def main():
- """Run administrative tasks."""
-
+
os.environ.setdefault(
"DJANGO_SETTINGS_MODULE",
os.getenv("DJANGO_SETTINGS_MODULE", "core.settings.development"),
diff --git a/requirements.txt b/requirements.txt
index 19e3539..4b121cf 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -12,4 +12,5 @@ python-dotenv==1.0.1
django-unfold
django-modeltranslation==0.18.11
drf-spectacular==0.27.1
-drf-spectacular-sidecar==2024.3.4
\ No newline at end of file
+drf-spectacular-sidecar==2024.3.4
+django-rosetta==0.10.0
From 7590af246f5906636ed073eabd33c376db8daa4a Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 13:25:18 +0500
Subject: [PATCH 5/9] makemessage ru uz
---
locale/ru/LC_MESSAGES/django.po | 1329 +++++++++++++++++++++++++++++++
locale/uz/LC_MESSAGES/django.po | 1327 ++++++++++++++++++++++++++++++
2 files changed, 2656 insertions(+)
create mode 100644 locale/ru/LC_MESSAGES/django.po
create mode 100644 locale/uz/LC_MESSAGES/django.po
diff --git a/locale/ru/LC_MESSAGES/django.po b/locale/ru/LC_MESSAGES/django.po
new file mode 100644
index 0000000..8aebbcc
--- /dev/null
+++ b/locale/ru/LC_MESSAGES/django.po
@@ -0,0 +1,1329 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR
, YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-11-21 13:24+0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=4; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && "
+"n%10<=4 && (n%100<12 || n%100>14) ? 1 : n%10==0 || (n%10>=5 && n%10<=9) || "
+"(n%100>=11 && n%100<=14)? 2 : 3);\n"
+
+#: .\apps\blog\models.py:14
+msgid "title"
+msgstr ""
+
+#: .\apps\blog\models.py:15
+msgid "slug"
+msgstr ""
+
+#: .\apps\blog\models.py:17
+msgid "status"
+msgstr ""
+
+#: .\apps\blog\models.py:23
+msgid "description"
+msgstr ""
+
+#: .\apps\blog\models.py:25
+msgid "content"
+msgstr ""
+
+#: .\apps\blog\models.py:26
+msgid "publisher at"
+msgstr ""
+
+#: .\apps\blog\models.py:27
+msgid "active"
+msgstr ""
+
+#: .\apps\blog\models.py:29
+msgid "watching"
+msgstr ""
+
+#: .\apps\blog\models.py:40
+msgid "Post"
+msgstr ""
+
+#: .\apps\blog\models.py:41
+msgid "Posts"
+msgstr ""
+
+#: .\apps\blog\models.py:94
+msgid "message"
+msgstr ""
+
+#: .\apps\users\models.py:9
+msgid "email address"
+msgstr ""
+
+#: .\apps\users\models.py:26
+msgid "User"
+msgstr ""
+
+#: .\apps\users\models.py:27
+msgid "Users"
+msgstr ""
+
+#: .\apps\users\models.py:40
+msgid "avatar"
+msgstr ""
+
+#: .\apps\users\models.py:47
+msgid "bio"
+msgstr ""
+
+#: .\apps\users\models.py:51
+msgid "User Profile"
+msgstr ""
+
+#: .\apps\users\models.py:52
+msgid "User Profiles"
+msgstr ""
+
+#: .\core\settings\base.py:92
+msgid "Russia"
+msgstr ""
+
+#: .\core\settings\base.py:93
+msgid "English"
+msgstr ""
+
+#: .\core\settings\base.py:94
+msgid "Uzbek"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\messages\apps.py:16
+msgid "Messages"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\sitemaps\apps.py:8
+msgid "Site Maps"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\staticfiles\apps.py:9
+msgid "Static Files"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\syndication\apps.py:7
+msgid "Syndication"
+msgstr ""
+
+#. Translators: String used to replace omitted page numbers in elided page
+#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10].
+#: .\venv\Lib\site-packages\django\core\paginator.py:30
+msgid "…"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:32
+msgid "That page number is not an integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:33
+msgid "That page number is less than 1"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:34
+msgid "That page contains no results"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:22
+msgid "Enter a valid value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:70
+msgid "Enter a valid domain name."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:155
+#: .\venv\Lib\site-packages\django\forms\fields.py:768
+msgid "Enter a valid URL."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:216
+msgid "Enter a valid integer."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:227
+msgid "Enter a valid email address."
+msgstr ""
+
+#. Translators: "letters" means latin letters: a-z and A-Z.
+#: .\venv\Lib\site-packages\django\core\validators.py:310
+msgid ""
+"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:318
+msgid ""
+"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or "
+"hyphens."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:330
+#: .\venv\Lib\site-packages\django\core\validators.py:339
+#: .\venv\Lib\site-packages\django\core\validators.py:353
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2215
+#, python-format
+msgid "Enter a valid %(protocol)s address."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:332
+msgid "IPv4"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:341
+#: .\venv\Lib\site-packages\django\utils\ipv6.py:30
+msgid "IPv6"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:355
+msgid "IPv4 or IPv6"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:396
+msgid "Enter only digits separated by commas."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:402
+#, python-format
+msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:437
+#, python-format
+msgid "Ensure this value is less than or equal to %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:446
+#, python-format
+msgid "Ensure this value is greater than or equal to %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:455
+#, python-format
+msgid "Ensure this value is a multiple of step size %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:462
+#, python-format
+msgid ""
+"Ensure this value is a multiple of step size %(limit_value)s, starting from "
+"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:494
+#, python-format
+msgid ""
+"Ensure this value has at least %(limit_value)d character (it has "
+"%(show_value)d)."
+msgid_plural ""
+"Ensure this value has at least %(limit_value)d characters (it has "
+"%(show_value)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:512
+#, python-format
+msgid ""
+"Ensure this value has at most %(limit_value)d character (it has "
+"%(show_value)d)."
+msgid_plural ""
+"Ensure this value has at most %(limit_value)d characters (it has "
+"%(show_value)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:535
+#: .\venv\Lib\site-packages\django\forms\fields.py:359
+#: .\venv\Lib\site-packages\django\forms\fields.py:398
+msgid "Enter a number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:537
+#, python-format
+msgid "Ensure that there are no more than %(max)s digit in total."
+msgid_plural "Ensure that there are no more than %(max)s digits in total."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:542
+#, python-format
+msgid "Ensure that there are no more than %(max)s decimal place."
+msgid_plural "Ensure that there are no more than %(max)s decimal places."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:547
+#, python-format
+msgid ""
+"Ensure that there are no more than %(max)s digit before the decimal point."
+msgid_plural ""
+"Ensure that there are no more than %(max)s digits before the decimal point."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:618
+#, python-format
+msgid ""
+"File extension “%(extension)s” is not allowed. Allowed extensions are: "
+"%(allowed_extensions)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:680
+msgid "Null characters are not allowed."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\base.py:1571
+#: .\venv\Lib\site-packages\django\forms\models.py:908
+msgid "and"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\base.py:1573
+#, python-format
+msgid "%(model_name)s with this %(field_labels)s already exists."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\constraints.py:22
+#, python-format
+msgid "Constraint “%(name)s” is violated."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:134
+#, python-format
+msgid "Value %(value)r is not a valid choice."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:135
+msgid "This field cannot be null."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:136
+msgid "This field cannot be blank."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:137
+#, python-format
+msgid "%(model_name)s with this %(field_label)s already exists."
+msgstr ""
+
+#. Translators: The 'lookup_type' is one of 'date', 'year' or
+#. 'month'. Eg: "Title must be unique for pub_date year"
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:141
+#, python-format
+msgid ""
+"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:180
+#, python-format
+msgid "Field of type: %(field_type)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1156
+#, python-format
+msgid "“%(value)s” value must be either True or False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1157
+#, python-format
+msgid "“%(value)s” value must be either True, False, or None."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1159
+msgid "Boolean (Either True or False)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1209
+#, python-format
+msgid "String (up to %(max_length)s)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1211
+msgid "String (unlimited)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1320
+msgid "Comma-separated integers"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1421
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD "
+"format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1425
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1560
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid "
+"date."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1429
+msgid "Date (without time)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1556
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[."
+"uuuuuu]][TZ] format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1564
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]"
+"[TZ]) but it is an invalid date/time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1569
+msgid "Date (with time)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1696
+#, python-format
+msgid "“%(value)s” value must be a decimal number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1698
+msgid "Decimal number"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1859
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[."
+"uuuuuu] format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1863
+msgid "Duration"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1915
+msgid "Email address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1940
+msgid "File path"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2018
+#, python-format
+msgid "“%(value)s” value must be a float."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2020
+msgid "Floating point number"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2060
+#, python-format
+msgid "“%(value)s” value must be an integer."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2062
+msgid "Integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2158
+msgid "Big (8 byte) integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2175
+msgid "Small integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2183
+msgid "IPv4 address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2214
+msgid "IP address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2305
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2306
+#, python-format
+msgid "“%(value)s” value must be either None, True or False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2308
+msgid "Boolean (Either True, False or None)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2359
+msgid "Positive big integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2374
+msgid "Positive integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2389
+msgid "Positive small integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2405
+#, python-format
+msgid "Slug (up to %(max_length)s)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2441
+msgid "Text"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2521
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] "
+"format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2525
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an "
+"invalid time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2529
+msgid "Time"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2637
+msgid "URL"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2661
+msgid "Raw binary data"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2726
+#, python-format
+msgid "“%(value)s” is not a valid UUID."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2728
+msgid "Universally unique identifier"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\files.py:244
+msgid "File"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\files.py:420
+msgid "Image"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\json.py:24
+msgid "A JSON object"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\json.py:26
+msgid "Value must be valid JSON."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:932
+#, python-format
+msgid "%(model)s instance with %(field)s %(value)r does not exist."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:934
+msgid "Foreign Key (type determined by related field)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1228
+msgid "One-to-one relationship"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1285
+#, python-format
+msgid "%(from)s-%(to)s relationship"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1287
+#, python-format
+msgid "%(from)s-%(to)s relationships"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1335
+msgid "Many-to-many relationship"
+msgstr ""
+
+#. Translators: If found as last label character, these punctuation
+#. characters will prevent the default label_suffix to be appended to the label
+#: .\venv\Lib\site-packages\django\forms\boundfield.py:185
+msgid ":?.!"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:95
+msgid "This field is required."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:308
+msgid "Enter a whole number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:479
+#: .\venv\Lib\site-packages\django\forms\fields.py:1260
+msgid "Enter a valid date."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:502
+#: .\venv\Lib\site-packages\django\forms\fields.py:1261
+msgid "Enter a valid time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:529
+msgid "Enter a valid date/time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:563
+msgid "Enter a valid duration."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:564
+#, python-brace-format
+msgid "The number of days must be between {min_days} and {max_days}."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:633
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:634
+msgid "No file was submitted."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:635
+msgid "The submitted file is empty."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:637
+#, python-format
+msgid "Ensure this filename has at most %(max)d character (it has %(length)d)."
+msgid_plural ""
+"Ensure this filename has at most %(max)d characters (it has %(length)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:642
+msgid "Please either submit a file or check the clear checkbox, not both."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:710
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:882
+#: .\venv\Lib\site-packages\django\forms\fields.py:968
+#: .\venv\Lib\site-packages\django\forms\models.py:1592
+#, python-format
+msgid "Select a valid choice. %(value)s is not one of the available choices."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:970
+#: .\venv\Lib\site-packages\django\forms\fields.py:1089
+#: .\venv\Lib\site-packages\django\forms\models.py:1590
+msgid "Enter a list of values."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1090
+msgid "Enter a complete value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1329
+msgid "Enter a valid UUID."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1359
+msgid "Enter a valid JSON."
+msgstr ""
+
+#. Translators: This is the default suffix added to form field labels
+#: .\venv\Lib\site-packages\django\forms\forms.py:94
+msgid ":"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\forms.py:230
+#, python-format
+msgid "(Hidden field %(name)s) %(error)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:61
+#, python-format
+msgid ""
+"ManagementForm data is missing or has been tampered with. Missing fields: "
+"%(field_names)s. You may need to file a bug report if the issue persists."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:65
+#, python-format
+msgid "Please submit at most %(num)d form."
+msgid_plural "Please submit at most %(num)d forms."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:70
+#, python-format
+msgid "Please submit at least %(num)d form."
+msgid_plural "Please submit at least %(num)d forms."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:484
+#: .\venv\Lib\site-packages\django\forms\formsets.py:491
+msgid "Order"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:499
+msgid "Delete"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:901
+#, python-format
+msgid "Please correct the duplicate data for %(field)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:906
+#, python-format
+msgid "Please correct the duplicate data for %(field)s, which must be unique."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:913
+#, python-format
+msgid ""
+"Please correct the duplicate data for %(field_name)s which must be unique "
+"for the %(lookup)s in %(date_field)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:922
+msgid "Please correct the duplicate values below."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1359
+msgid "The inline value did not match the parent instance."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1450
+msgid "Select a valid choice. That choice is not one of the available choices."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1594
+#, python-format
+msgid "“%(pk)s” is not a valid value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\utils.py:227
+#, python-format
+msgid ""
+"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it "
+"may be ambiguous or it may not exist."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:461
+msgid "Clear"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:462
+msgid "Currently"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:463
+msgid "Change"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:800
+msgid "Unknown"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:801
+msgid "Yes"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:802
+msgid "No"
+msgstr ""
+
+#. Translators: Please do not add spaces around commas.
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:873
+msgid "yes,no,maybe"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:903
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:920
+#, python-format
+msgid "%(size)d byte"
+msgid_plural "%(size)d bytes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:922
+#, python-format
+msgid "%s KB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:924
+#, python-format
+msgid "%s MB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:926
+#, python-format
+msgid "%s GB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:928
+#, python-format
+msgid "%s TB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:930
+#, python-format
+msgid "%s PB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:74
+msgid "p.m."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:75
+msgid "a.m."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:80
+msgid "PM"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:81
+msgid "AM"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:153
+msgid "midnight"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:155
+msgid "noon"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:7
+msgid "Monday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:8
+msgid "Tuesday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:9
+msgid "Wednesday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:10
+msgid "Thursday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:11
+msgid "Friday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:12
+msgid "Saturday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:13
+msgid "Sunday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:16
+msgid "Mon"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:17
+msgid "Tue"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:18
+msgid "Wed"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:19
+msgid "Thu"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:20
+msgid "Fri"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:21
+msgid "Sat"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:22
+msgid "Sun"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:25
+msgid "January"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:26
+msgid "February"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:27
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:28
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:29
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:30
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:31
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:32
+msgid "August"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:33
+msgid "September"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:34
+msgid "October"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:35
+msgid "November"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:36
+msgid "December"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:39
+msgid "jan"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:40
+msgid "feb"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:41
+msgid "mar"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:42
+msgid "apr"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:43
+msgid "may"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:44
+msgid "jun"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:45
+msgid "jul"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:46
+msgid "aug"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:47
+msgid "sep"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:48
+msgid "oct"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:49
+msgid "nov"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:50
+msgid "dec"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:53
+msgctxt "abbrev. month"
+msgid "Jan."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:54
+msgctxt "abbrev. month"
+msgid "Feb."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:55
+msgctxt "abbrev. month"
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:56
+msgctxt "abbrev. month"
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:57
+msgctxt "abbrev. month"
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:58
+msgctxt "abbrev. month"
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:59
+msgctxt "abbrev. month"
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:60
+msgctxt "abbrev. month"
+msgid "Aug."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:61
+msgctxt "abbrev. month"
+msgid "Sept."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:62
+msgctxt "abbrev. month"
+msgid "Oct."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:63
+msgctxt "abbrev. month"
+msgid "Nov."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:64
+msgctxt "abbrev. month"
+msgid "Dec."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:67
+msgctxt "alt. month"
+msgid "January"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:68
+msgctxt "alt. month"
+msgid "February"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:69
+msgctxt "alt. month"
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:70
+msgctxt "alt. month"
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:71
+msgctxt "alt. month"
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:72
+msgctxt "alt. month"
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:73
+msgctxt "alt. month"
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:74
+msgctxt "alt. month"
+msgid "August"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:75
+msgctxt "alt. month"
+msgid "September"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:76
+msgctxt "alt. month"
+msgid "October"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:77
+msgctxt "alt. month"
+msgid "November"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:78
+msgctxt "alt. month"
+msgid "December"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\ipv6.py:8
+msgid "This is not a valid IPv6 address."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\text.py:75
+#, python-format
+msgctxt "String to return when truncating text"
+msgid "%(truncated_text)s…"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\text.py:286
+msgid "or"
+msgstr ""
+
+#. Translators: This string is used as a separator between list elements
+#: .\venv\Lib\site-packages\django\utils\text.py:305
+#: .\venv\Lib\site-packages\django\utils\timesince.py:135
+msgid ", "
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:8
+#, python-format
+msgid "%(num)d year"
+msgid_plural "%(num)d years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:9
+#, python-format
+msgid "%(num)d month"
+msgid_plural "%(num)d months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:10
+#, python-format
+msgid "%(num)d week"
+msgid_plural "%(num)d weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:11
+#, python-format
+msgid "%(num)d day"
+msgid_plural "%(num)d days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:12
+#, python-format
+msgid "%(num)d hour"
+msgid_plural "%(num)d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:13
+#, python-format
+msgid "%(num)d minute"
+msgid_plural "%(num)d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:29
+msgid "Forbidden"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:30
+msgid "CSRF verification failed. Request aborted."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:34
+msgid ""
+"You are seeing this message because this HTTPS site requires a “Referer "
+"header” to be sent by your web browser, but none was sent. This header is "
+"required for security reasons, to ensure that your browser is not being "
+"hijacked by third parties."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:40
+msgid ""
+"If you have configured your browser to disable “Referer” headers, please re-"
+"enable them, at least for this site, or for HTTPS connections, or for “same-"
+"origin” requests."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:45
+msgid ""
+"If you are using the tag or "
+"including the “Referrer-Policy: no-referrer” header, please remove them. The "
+"CSRF protection requires the “Referer” header to do strict referer checking. "
+"If you’re concerned about privacy, use alternatives like for links to third-party sites."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:54
+msgid ""
+"You are seeing this message because this site requires a CSRF cookie when "
+"submitting forms. This cookie is required for security reasons, to ensure "
+"that your browser is not being hijacked by third parties."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:60
+msgid ""
+"If you have configured your browser to disable cookies, please re-enable "
+"them, at least for this site, or for “same-origin” requests."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:66
+msgid "More information is available with DEBUG=True."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:44
+msgid "No year specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:64
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:115
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:214
+msgid "Date out of range"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:94
+msgid "No month specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:147
+msgid "No day specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:194
+msgid "No week specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:349
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:380
+#, python-format
+msgid "No %(verbose_name_plural)s available"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:652
+#, python-format
+msgid ""
+"Future %(verbose_name_plural)s not available because %(class_name)s."
+"allow_future is False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:692
+#, python-format
+msgid "Invalid date string “%(datestr)s” given format “%(format)s”"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\detail.py:56
+#, python-format
+msgid "No %(verbose_name)s found matching the query"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:70
+msgid "Page is not “last”, nor can it be converted to an int."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:77
+#, python-format
+msgid "Invalid page (%(page_number)s): %(message)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:169
+#, python-format
+msgid "Empty list and “%(class_name)s.allow_empty” is False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:49
+msgid "Directory indexes are not allowed here."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:51
+#, python-format
+msgid "“%(path)s” does not exist"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:68
+#: .\venv\Lib\site-packages\django\views\templates\directory_index.html:8
+#: .\venv\Lib\site-packages\django\views\templates\directory_index.html:11
+#, python-format
+msgid "Index of %(directory)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:7
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:204
+msgid "The install worked successfully! Congratulations!"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:206
+#, python-format
+msgid ""
+"View release notes for Django %(version)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:208
+#, python-format
+msgid ""
+"You are seeing this page because DEBUG=True is in your settings file and you have not configured any "
+"URLs."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:217
+msgid "Django Documentation"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:218
+msgid "Topics, references, & how-to’s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:226
+msgid "Tutorial: A Polling App"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:227
+msgid "Get started with Django"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:235
+msgid "Django Community"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:236
+msgid "Connect, get help, or contribute"
+msgstr ""
diff --git a/locale/uz/LC_MESSAGES/django.po b/locale/uz/LC_MESSAGES/django.po
new file mode 100644
index 0000000..94afbbe
--- /dev/null
+++ b/locale/uz/LC_MESSAGES/django.po
@@ -0,0 +1,1327 @@
+# SOME DESCRIPTIVE TITLE.
+# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
+# This file is distributed under the same license as the PACKAGE package.
+# FIRST AUTHOR , YEAR.
+#
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: PACKAGE VERSION\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2024-11-21 13:24+0500\n"
+"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"Last-Translator: FULL NAME \n"
+"Language-Team: LANGUAGE \n"
+"Language: \n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=1; plural=0;\n"
+
+#: .\apps\blog\models.py:14
+msgid "title"
+msgstr ""
+
+#: .\apps\blog\models.py:15
+msgid "slug"
+msgstr ""
+
+#: .\apps\blog\models.py:17
+msgid "status"
+msgstr ""
+
+#: .\apps\blog\models.py:23
+msgid "description"
+msgstr ""
+
+#: .\apps\blog\models.py:25
+msgid "content"
+msgstr ""
+
+#: .\apps\blog\models.py:26
+msgid "publisher at"
+msgstr ""
+
+#: .\apps\blog\models.py:27
+msgid "active"
+msgstr ""
+
+#: .\apps\blog\models.py:29
+msgid "watching"
+msgstr ""
+
+#: .\apps\blog\models.py:40
+msgid "Post"
+msgstr ""
+
+#: .\apps\blog\models.py:41
+msgid "Posts"
+msgstr ""
+
+#: .\apps\blog\models.py:94
+msgid "message"
+msgstr ""
+
+#: .\apps\users\models.py:9
+msgid "email address"
+msgstr ""
+
+#: .\apps\users\models.py:26
+msgid "User"
+msgstr ""
+
+#: .\apps\users\models.py:27
+msgid "Users"
+msgstr ""
+
+#: .\apps\users\models.py:40
+msgid "avatar"
+msgstr ""
+
+#: .\apps\users\models.py:47
+msgid "bio"
+msgstr ""
+
+#: .\apps\users\models.py:51
+msgid "User Profile"
+msgstr ""
+
+#: .\apps\users\models.py:52
+msgid "User Profiles"
+msgstr ""
+
+#: .\core\settings\base.py:92
+msgid "Russia"
+msgstr ""
+
+#: .\core\settings\base.py:93
+msgid "English"
+msgstr ""
+
+#: .\core\settings\base.py:94
+msgid "Uzbek"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\messages\apps.py:16
+msgid "Messages"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\sitemaps\apps.py:8
+msgid "Site Maps"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\staticfiles\apps.py:9
+msgid "Static Files"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\contrib\syndication\apps.py:7
+msgid "Syndication"
+msgstr ""
+
+#. Translators: String used to replace omitted page numbers in elided page
+#. range generated by paginators, e.g. [1, 2, '…', 5, 6, 7, '…', 9, 10].
+#: .\venv\Lib\site-packages\django\core\paginator.py:30
+msgid "…"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:32
+msgid "That page number is not an integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:33
+msgid "That page number is less than 1"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\paginator.py:34
+msgid "That page contains no results"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:22
+msgid "Enter a valid value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:70
+msgid "Enter a valid domain name."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:155
+#: .\venv\Lib\site-packages\django\forms\fields.py:768
+msgid "Enter a valid URL."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:216
+msgid "Enter a valid integer."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:227
+msgid "Enter a valid email address."
+msgstr ""
+
+#. Translators: "letters" means latin letters: a-z and A-Z.
+#: .\venv\Lib\site-packages\django\core\validators.py:310
+msgid ""
+"Enter a valid “slug” consisting of letters, numbers, underscores or hyphens."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:318
+msgid ""
+"Enter a valid “slug” consisting of Unicode letters, numbers, underscores, or "
+"hyphens."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:330
+#: .\venv\Lib\site-packages\django\core\validators.py:339
+#: .\venv\Lib\site-packages\django\core\validators.py:353
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2215
+#, python-format
+msgid "Enter a valid %(protocol)s address."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:332
+msgid "IPv4"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:341
+#: .\venv\Lib\site-packages\django\utils\ipv6.py:30
+msgid "IPv6"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:355
+msgid "IPv4 or IPv6"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:396
+msgid "Enter only digits separated by commas."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:402
+#, python-format
+msgid "Ensure this value is %(limit_value)s (it is %(show_value)s)."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:437
+#, python-format
+msgid "Ensure this value is less than or equal to %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:446
+#, python-format
+msgid "Ensure this value is greater than or equal to %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:455
+#, python-format
+msgid "Ensure this value is a multiple of step size %(limit_value)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:462
+#, python-format
+msgid ""
+"Ensure this value is a multiple of step size %(limit_value)s, starting from "
+"%(offset)s, e.g. %(offset)s, %(valid_value1)s, %(valid_value2)s, and so on."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:494
+#, python-format
+msgid ""
+"Ensure this value has at least %(limit_value)d character (it has "
+"%(show_value)d)."
+msgid_plural ""
+"Ensure this value has at least %(limit_value)d characters (it has "
+"%(show_value)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:512
+#, python-format
+msgid ""
+"Ensure this value has at most %(limit_value)d character (it has "
+"%(show_value)d)."
+msgid_plural ""
+"Ensure this value has at most %(limit_value)d characters (it has "
+"%(show_value)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:535
+#: .\venv\Lib\site-packages\django\forms\fields.py:359
+#: .\venv\Lib\site-packages\django\forms\fields.py:398
+msgid "Enter a number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:537
+#, python-format
+msgid "Ensure that there are no more than %(max)s digit in total."
+msgid_plural "Ensure that there are no more than %(max)s digits in total."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:542
+#, python-format
+msgid "Ensure that there are no more than %(max)s decimal place."
+msgid_plural "Ensure that there are no more than %(max)s decimal places."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:547
+#, python-format
+msgid ""
+"Ensure that there are no more than %(max)s digit before the decimal point."
+msgid_plural ""
+"Ensure that there are no more than %(max)s digits before the decimal point."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:618
+#, python-format
+msgid ""
+"File extension “%(extension)s” is not allowed. Allowed extensions are: "
+"%(allowed_extensions)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\core\validators.py:680
+msgid "Null characters are not allowed."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\base.py:1571
+#: .\venv\Lib\site-packages\django\forms\models.py:908
+msgid "and"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\base.py:1573
+#, python-format
+msgid "%(model_name)s with this %(field_labels)s already exists."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\constraints.py:22
+#, python-format
+msgid "Constraint “%(name)s” is violated."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:134
+#, python-format
+msgid "Value %(value)r is not a valid choice."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:135
+msgid "This field cannot be null."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:136
+msgid "This field cannot be blank."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:137
+#, python-format
+msgid "%(model_name)s with this %(field_label)s already exists."
+msgstr ""
+
+#. Translators: The 'lookup_type' is one of 'date', 'year' or
+#. 'month'. Eg: "Title must be unique for pub_date year"
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:141
+#, python-format
+msgid ""
+"%(field_label)s must be unique for %(date_field_label)s %(lookup_type)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:180
+#, python-format
+msgid "Field of type: %(field_type)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1156
+#, python-format
+msgid "“%(value)s” value must be either True or False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1157
+#, python-format
+msgid "“%(value)s” value must be either True, False, or None."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1159
+msgid "Boolean (Either True or False)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1209
+#, python-format
+msgid "String (up to %(max_length)s)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1211
+msgid "String (unlimited)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1320
+msgid "Comma-separated integers"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1421
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid date format. It must be in YYYY-MM-DD "
+"format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1425
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1560
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (YYYY-MM-DD) but it is an invalid "
+"date."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1429
+msgid "Date (without time)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1556
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in YYYY-MM-DD HH:MM[:ss[."
+"uuuuuu]][TZ] format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1564
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (YYYY-MM-DD HH:MM[:ss[.uuuuuu]]"
+"[TZ]) but it is an invalid date/time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1569
+msgid "Date (with time)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1696
+#, python-format
+msgid "“%(value)s” value must be a decimal number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1698
+msgid "Decimal number"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1859
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in [DD] [[HH:]MM:]ss[."
+"uuuuuu] format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1863
+msgid "Duration"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1915
+msgid "Email address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:1940
+msgid "File path"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2018
+#, python-format
+msgid "“%(value)s” value must be a float."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2020
+msgid "Floating point number"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2060
+#, python-format
+msgid "“%(value)s” value must be an integer."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2062
+msgid "Integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2158
+msgid "Big (8 byte) integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2175
+msgid "Small integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2183
+msgid "IPv4 address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2214
+msgid "IP address"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2305
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2306
+#, python-format
+msgid "“%(value)s” value must be either None, True or False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2308
+msgid "Boolean (Either True, False or None)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2359
+msgid "Positive big integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2374
+msgid "Positive integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2389
+msgid "Positive small integer"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2405
+#, python-format
+msgid "Slug (up to %(max_length)s)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2441
+msgid "Text"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2521
+#, python-format
+msgid ""
+"“%(value)s” value has an invalid format. It must be in HH:MM[:ss[.uuuuuu]] "
+"format."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2525
+#, python-format
+msgid ""
+"“%(value)s” value has the correct format (HH:MM[:ss[.uuuuuu]]) but it is an "
+"invalid time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2529
+msgid "Time"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2637
+msgid "URL"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2661
+msgid "Raw binary data"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2726
+#, python-format
+msgid "“%(value)s” is not a valid UUID."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\__init__.py:2728
+msgid "Universally unique identifier"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\files.py:244
+msgid "File"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\files.py:420
+msgid "Image"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\json.py:24
+msgid "A JSON object"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\json.py:26
+msgid "Value must be valid JSON."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:932
+#, python-format
+msgid "%(model)s instance with %(field)s %(value)r does not exist."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:934
+msgid "Foreign Key (type determined by related field)"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1228
+msgid "One-to-one relationship"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1285
+#, python-format
+msgid "%(from)s-%(to)s relationship"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1287
+#, python-format
+msgid "%(from)s-%(to)s relationships"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\db\models\fields\related.py:1335
+msgid "Many-to-many relationship"
+msgstr ""
+
+#. Translators: If found as last label character, these punctuation
+#. characters will prevent the default label_suffix to be appended to the label
+#: .\venv\Lib\site-packages\django\forms\boundfield.py:185
+msgid ":?.!"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:95
+msgid "This field is required."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:308
+msgid "Enter a whole number."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:479
+#: .\venv\Lib\site-packages\django\forms\fields.py:1260
+msgid "Enter a valid date."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:502
+#: .\venv\Lib\site-packages\django\forms\fields.py:1261
+msgid "Enter a valid time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:529
+msgid "Enter a valid date/time."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:563
+msgid "Enter a valid duration."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:564
+#, python-brace-format
+msgid "The number of days must be between {min_days} and {max_days}."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:633
+msgid "No file was submitted. Check the encoding type on the form."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:634
+msgid "No file was submitted."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:635
+msgid "The submitted file is empty."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:637
+#, python-format
+msgid "Ensure this filename has at most %(max)d character (it has %(length)d)."
+msgid_plural ""
+"Ensure this filename has at most %(max)d characters (it has %(length)d)."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:642
+msgid "Please either submit a file or check the clear checkbox, not both."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:710
+msgid ""
+"Upload a valid image. The file you uploaded was either not an image or a "
+"corrupted image."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:882
+#: .\venv\Lib\site-packages\django\forms\fields.py:968
+#: .\venv\Lib\site-packages\django\forms\models.py:1592
+#, python-format
+msgid "Select a valid choice. %(value)s is not one of the available choices."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:970
+#: .\venv\Lib\site-packages\django\forms\fields.py:1089
+#: .\venv\Lib\site-packages\django\forms\models.py:1590
+msgid "Enter a list of values."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1090
+msgid "Enter a complete value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1329
+msgid "Enter a valid UUID."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\fields.py:1359
+msgid "Enter a valid JSON."
+msgstr ""
+
+#. Translators: This is the default suffix added to form field labels
+#: .\venv\Lib\site-packages\django\forms\forms.py:94
+msgid ":"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\forms.py:230
+#, python-format
+msgid "(Hidden field %(name)s) %(error)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:61
+#, python-format
+msgid ""
+"ManagementForm data is missing or has been tampered with. Missing fields: "
+"%(field_names)s. You may need to file a bug report if the issue persists."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:65
+#, python-format
+msgid "Please submit at most %(num)d form."
+msgid_plural "Please submit at most %(num)d forms."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:70
+#, python-format
+msgid "Please submit at least %(num)d form."
+msgid_plural "Please submit at least %(num)d forms."
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:484
+#: .\venv\Lib\site-packages\django\forms\formsets.py:491
+msgid "Order"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\formsets.py:499
+msgid "Delete"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:901
+#, python-format
+msgid "Please correct the duplicate data for %(field)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:906
+#, python-format
+msgid "Please correct the duplicate data for %(field)s, which must be unique."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:913
+#, python-format
+msgid ""
+"Please correct the duplicate data for %(field_name)s which must be unique "
+"for the %(lookup)s in %(date_field)s."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:922
+msgid "Please correct the duplicate values below."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1359
+msgid "The inline value did not match the parent instance."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1450
+msgid "Select a valid choice. That choice is not one of the available choices."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\models.py:1594
+#, python-format
+msgid "“%(pk)s” is not a valid value."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\utils.py:227
+#, python-format
+msgid ""
+"%(datetime)s couldn’t be interpreted in time zone %(current_timezone)s; it "
+"may be ambiguous or it may not exist."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:461
+msgid "Clear"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:462
+msgid "Currently"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:463
+msgid "Change"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:800
+msgid "Unknown"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:801
+msgid "Yes"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\forms\widgets.py:802
+msgid "No"
+msgstr ""
+
+#. Translators: Please do not add spaces around commas.
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:873
+msgid "yes,no,maybe"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:903
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:920
+#, python-format
+msgid "%(size)d byte"
+msgid_plural "%(size)d bytes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:922
+#, python-format
+msgid "%s KB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:924
+#, python-format
+msgid "%s MB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:926
+#, python-format
+msgid "%s GB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:928
+#, python-format
+msgid "%s TB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\template\defaultfilters.py:930
+#, python-format
+msgid "%s PB"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:74
+msgid "p.m."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:75
+msgid "a.m."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:80
+msgid "PM"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:81
+msgid "AM"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:153
+msgid "midnight"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dateformat.py:155
+msgid "noon"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:7
+msgid "Monday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:8
+msgid "Tuesday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:9
+msgid "Wednesday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:10
+msgid "Thursday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:11
+msgid "Friday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:12
+msgid "Saturday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:13
+msgid "Sunday"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:16
+msgid "Mon"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:17
+msgid "Tue"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:18
+msgid "Wed"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:19
+msgid "Thu"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:20
+msgid "Fri"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:21
+msgid "Sat"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:22
+msgid "Sun"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:25
+msgid "January"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:26
+msgid "February"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:27
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:28
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:29
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:30
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:31
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:32
+msgid "August"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:33
+msgid "September"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:34
+msgid "October"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:35
+msgid "November"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:36
+msgid "December"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:39
+msgid "jan"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:40
+msgid "feb"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:41
+msgid "mar"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:42
+msgid "apr"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:43
+msgid "may"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:44
+msgid "jun"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:45
+msgid "jul"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:46
+msgid "aug"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:47
+msgid "sep"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:48
+msgid "oct"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:49
+msgid "nov"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:50
+msgid "dec"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:53
+msgctxt "abbrev. month"
+msgid "Jan."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:54
+msgctxt "abbrev. month"
+msgid "Feb."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:55
+msgctxt "abbrev. month"
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:56
+msgctxt "abbrev. month"
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:57
+msgctxt "abbrev. month"
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:58
+msgctxt "abbrev. month"
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:59
+msgctxt "abbrev. month"
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:60
+msgctxt "abbrev. month"
+msgid "Aug."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:61
+msgctxt "abbrev. month"
+msgid "Sept."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:62
+msgctxt "abbrev. month"
+msgid "Oct."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:63
+msgctxt "abbrev. month"
+msgid "Nov."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:64
+msgctxt "abbrev. month"
+msgid "Dec."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:67
+msgctxt "alt. month"
+msgid "January"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:68
+msgctxt "alt. month"
+msgid "February"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:69
+msgctxt "alt. month"
+msgid "March"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:70
+msgctxt "alt. month"
+msgid "April"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:71
+msgctxt "alt. month"
+msgid "May"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:72
+msgctxt "alt. month"
+msgid "June"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:73
+msgctxt "alt. month"
+msgid "July"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:74
+msgctxt "alt. month"
+msgid "August"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:75
+msgctxt "alt. month"
+msgid "September"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:76
+msgctxt "alt. month"
+msgid "October"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:77
+msgctxt "alt. month"
+msgid "November"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\dates.py:78
+msgctxt "alt. month"
+msgid "December"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\ipv6.py:8
+msgid "This is not a valid IPv6 address."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\text.py:75
+#, python-format
+msgctxt "String to return when truncating text"
+msgid "%(truncated_text)s…"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\text.py:286
+msgid "or"
+msgstr ""
+
+#. Translators: This string is used as a separator between list elements
+#: .\venv\Lib\site-packages\django\utils\text.py:305
+#: .\venv\Lib\site-packages\django\utils\timesince.py:135
+msgid ", "
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:8
+#, python-format
+msgid "%(num)d year"
+msgid_plural "%(num)d years"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:9
+#, python-format
+msgid "%(num)d month"
+msgid_plural "%(num)d months"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:10
+#, python-format
+msgid "%(num)d week"
+msgid_plural "%(num)d weeks"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:11
+#, python-format
+msgid "%(num)d day"
+msgid_plural "%(num)d days"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:12
+#, python-format
+msgid "%(num)d hour"
+msgid_plural "%(num)d hours"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\utils\timesince.py:13
+#, python-format
+msgid "%(num)d minute"
+msgid_plural "%(num)d minutes"
+msgstr[0] ""
+msgstr[1] ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:29
+msgid "Forbidden"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:30
+msgid "CSRF verification failed. Request aborted."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:34
+msgid ""
+"You are seeing this message because this HTTPS site requires a “Referer "
+"header” to be sent by your web browser, but none was sent. This header is "
+"required for security reasons, to ensure that your browser is not being "
+"hijacked by third parties."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:40
+msgid ""
+"If you have configured your browser to disable “Referer” headers, please re-"
+"enable them, at least for this site, or for HTTPS connections, or for “same-"
+"origin” requests."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:45
+msgid ""
+"If you are using the tag or "
+"including the “Referrer-Policy: no-referrer” header, please remove them. The "
+"CSRF protection requires the “Referer” header to do strict referer checking. "
+"If you’re concerned about privacy, use alternatives like for links to third-party sites."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:54
+msgid ""
+"You are seeing this message because this site requires a CSRF cookie when "
+"submitting forms. This cookie is required for security reasons, to ensure "
+"that your browser is not being hijacked by third parties."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:60
+msgid ""
+"If you have configured your browser to disable cookies, please re-enable "
+"them, at least for this site, or for “same-origin” requests."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\csrf.py:66
+msgid "More information is available with DEBUG=True."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:44
+msgid "No year specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:64
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:115
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:214
+msgid "Date out of range"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:94
+msgid "No month specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:147
+msgid "No day specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:194
+msgid "No week specified"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:349
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:380
+#, python-format
+msgid "No %(verbose_name_plural)s available"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:652
+#, python-format
+msgid ""
+"Future %(verbose_name_plural)s not available because %(class_name)s."
+"allow_future is False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\dates.py:692
+#, python-format
+msgid "Invalid date string “%(datestr)s” given format “%(format)s”"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\detail.py:56
+#, python-format
+msgid "No %(verbose_name)s found matching the query"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:70
+msgid "Page is not “last”, nor can it be converted to an int."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:77
+#, python-format
+msgid "Invalid page (%(page_number)s): %(message)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\generic\list.py:169
+#, python-format
+msgid "Empty list and “%(class_name)s.allow_empty” is False."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:49
+msgid "Directory indexes are not allowed here."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:51
+#, python-format
+msgid "“%(path)s” does not exist"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\static.py:68
+#: .\venv\Lib\site-packages\django\views\templates\directory_index.html:8
+#: .\venv\Lib\site-packages\django\views\templates\directory_index.html:11
+#, python-format
+msgid "Index of %(directory)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:7
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:204
+msgid "The install worked successfully! Congratulations!"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:206
+#, python-format
+msgid ""
+"View release notes for Django %(version)s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:208
+#, python-format
+msgid ""
+"You are seeing this page because DEBUG=True is in your settings file and you have not configured any "
+"URLs."
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:217
+msgid "Django Documentation"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:218
+msgid "Topics, references, & how-to’s"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:226
+msgid "Tutorial: A Polling App"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:227
+msgid "Get started with Django"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:235
+msgid "Django Community"
+msgstr ""
+
+#: .\venv\Lib\site-packages\django\views\templates\default_urlconf.html:236
+msgid "Connect, get help, or contribute"
+msgstr ""
From b2d5681ece23650ae3fc40817ba1177155f62d2f Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 13:42:18 +0500
Subject: [PATCH 6/9] full commit
---
core/asgi.py | 19 +++++++++----------
core/config/__init__.py | 2 ++
core/settings/base.py | 1 +
core/urls.py | 5 +++--
4 files changed, 15 insertions(+), 12 deletions(-)
diff --git a/core/asgi.py b/core/asgi.py
index 762ffa4..0188a94 100644
--- a/core/asgi.py
+++ b/core/asgi.py
@@ -1,16 +1,15 @@
-"""
-ASGI config for config project.
-
-It exposes the ASGI callable as a module-level variable named ``application``.
-
-For more information on this file, see
-https://docs.djangoproject.com/en/5.0/howto/deployment/asgi/
-"""
-
import os
from django.core.asgi import get_asgi_application
-os.environ.setdefault("DJANGO_SETTINGS_MODULE", "core.settings")
+from dotenv import load_dotenv
+load_dotenv()
+
+os.environ.setdefault(
+ "DJANGO_SETTINGS_MODULE",
+ os.getenv("DJANGO_SETTINGS_MODULE", "core.settings.development")
+)
application = get_asgi_application()
+
+app = application
\ No newline at end of file
diff --git a/core/config/__init__.py b/core/config/__init__.py
index 6cc4c3b..9c65ab1 100644
--- a/core/config/__init__.py
+++ b/core/config/__init__.py
@@ -1,3 +1,5 @@
from .apps import * # noqa
from .jwt import * # noqa
from .rest_framework import * # noqa
+from .unfold_navigation import * # noqa
+from .unfold import * # noqa
diff --git a/core/settings/base.py b/core/settings/base.py
index a3b406e..861c16f 100644
--- a/core/settings/base.py
+++ b/core/settings/base.py
@@ -62,6 +62,7 @@
}
WSGI_APPLICATION = "core.wsgi.application"
+ASGI_APPLICATION = "core.asgi.application"
AUTH_PASSWORD_VALIDATORS = [
{
diff --git a/core/urls.py b/core/urls.py
index cbb25fa..2dc1816 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -23,19 +23,20 @@
}
# URLs
-urlpatterns = [
+urlpatterns = i18n_patterns(
path("admin/", admin.site.urls),
path("i18n", include("django.conf.urls.i18n")),
path("", include("apps.blog.urls", namespace="blog")),
path("users/", include("apps.users.urls", namespace="users")),
path("robots.txt", TemplateView.as_view(template_name="bunin/robots.txt")),
+ path("rosetta/", include("rosetta.urls")),
path(
"sitemap.xml",
sitemap,
{"sitemaps": sitemaps},
name="django.contrib.sitemaps.views.sitemap",
),
-]
+)
# API Endpoints
urlpatterns += [
From 7d88b1829821eb70978f4098861927e53477c8c8 Mon Sep 17 00:00:00 2001
From: Akromjon <152626511+RustamovAkrom@users.noreply.github.com>
Date: Thu, 21 Nov 2024 18:42:48 +0500
Subject: [PATCH 7/9] adevanced update admin panel
---
apps/blog/admin.py | 11 +-
apps/users/admin.py | 6 +-
core/config/unfold.py | 67 ++
core/config/unfold_navigation.py | 49 +
core/settings/base.py | 8 +-
core/urls.py | 8 +-
media/avatars/1727198193049.jpg | Bin 0 -> 16242 bytes
...ence_room_setting_with_modern_lightin.webp | Bin 0 -> 15794 bytes
static/css/tailwind.css | 945 ++++++++++++++++++
static/images/django-logo.png | Bin 0 -> 28071 bytes
static/images/login.jpg | Bin 0 -> 772266 bytes
11 files changed, 1081 insertions(+), 13 deletions(-)
create mode 100644 media/avatars/1727198193049.jpg
create mode 100644 media/avatars/DALLE_2024-09-27_14_PN7dbHS.30.15_-_A_young_man_with_short_hair_and_glasses_wearing_a_formal_business_suit._The_background_is_a_professional_conference_room_setting_with_modern_lightin.webp
create mode 100644 static/css/tailwind.css
create mode 100644 static/images/django-logo.png
create mode 100644 static/images/login.jpg
diff --git a/apps/blog/admin.py b/apps/blog/admin.py
index 91d1cdd..fd6b756 100644
--- a/apps/blog/admin.py
+++ b/apps/blog/admin.py
@@ -1,9 +1,10 @@
from django.contrib import admin
from .models import Post, PostComment, PostLike, PostDislike, PostCommentLike
+from unfold.admin import ModelAdmin
@admin.register(Post)
-class PostAdmin(admin.ModelAdmin):
+class PostAdmin(ModelAdmin):
list_display = ["title", "content", "author", "is_active"]
search_fields = ["title", "content"]
list_filter = ["author", "is_active"]
@@ -12,20 +13,20 @@ class PostAdmin(admin.ModelAdmin):
@admin.register(PostComment)
-class PostCommentAdmin(admin.ModelAdmin):
+class PostCommentAdmin(ModelAdmin):
pass
@admin.register(PostLike)
-class PostLikeAdmin(admin.ModelAdmin):
+class PostLikeAdmin(ModelAdmin):
pass
@admin.register(PostDislike)
-class PostDislike(admin.ModelAdmin):
+class PostDislike(ModelAdmin):
pass
@admin.register(PostCommentLike)
-class PostCommentLikeAdmin(admin.ModelAdmin):
+class PostCommentLikeAdmin(ModelAdmin):
pass
diff --git a/apps/users/admin.py b/apps/users/admin.py
index 269ec5f..43b9313 100644
--- a/apps/users/admin.py
+++ b/apps/users/admin.py
@@ -1,9 +1,11 @@
from django.contrib import admin
+from django.contrib.auth.admin import UserAdmin as BaseUserAdmin
from .models import User, UserProfile
+from unfold.admin import ModelAdmin
@admin.register(User)
-class UserAdmin(admin.ModelAdmin):
+class UserAdmin(ModelAdmin):
list_display = ["username", "post_count"]
search_fields = ["first_name", "last_name", "username"]
list_display_links = ["username"]
@@ -13,5 +15,5 @@ def get_post_count(self):
@admin.register(UserProfile)
-class UserProfileAdmin(admin.ModelAdmin):
+class UserProfileAdmin(ModelAdmin):
pass
diff --git a/core/config/unfold.py b/core/config/unfold.py
index e69de29..e4c6447 100644
--- a/core/config/unfold.py
+++ b/core/config/unfold.py
@@ -0,0 +1,67 @@
+from django.templatetags.static import static
+
+from . import unfold_navigation as navigation
+
+
+UNFOLD = {
+ "SITE_TITLE": "Akromjon BLOG",
+ "SITE_HEADER": "Akromjon BLOG",
+ "SITE_URL": "/",
+ "SITE_ICON": {
+ "light": lambda request: static("images/django-logo.png"),
+ "dark": lambda request: static("images/django-logo.png"),
+ },
+ "SITE_FAVICONS": [
+ {
+ "rel": "icon",
+ "sizes": "32x32",
+ "type": "image/svg+xml",
+ "href": lambda request: static("images/django-logo.png"),
+ },
+ ],
+ "SITE_SYMBOL": "speed",
+ "SHOW_HISTORY": True,
+ "SHOW_VIEW_ON_SITE": True,
+ "STYLES": [
+ lambda request: static("css/tailwind.css"),
+ ],
+ "LOGIN": {
+ "image": lambda request: static("images/login.jpg"),
+ },
+ "COLORS": {
+ "font": {
+ "subtle-light": "107 114 128",
+ "subtle-dark": "156 163 175",
+ "default-light": "75 85 99",
+ "default-dark": "209 213 219",
+ "important-light": "17 24 39",
+ "important-dark": "243 244 246",
+ },
+ "primary": {
+ "50": "65 144 176",
+ "100": "65 144 176",
+ "200": "65 144 176",
+ "300": "65 144 176",
+ "400": "65 144 176",
+ "500": "65 144 176",
+ "600": "65 144 176",
+ "700": "65 144 176",
+ "800": "65 144 176",
+ "900": "65 144 176",
+ "950": "65 144 176",
+ },
+ },
+ "EXTENSIONS": {
+ "modeltranslation": {
+ "flags": {
+ "uz": "uz",
+ "ru": "🇷🇺",
+ }
+ },
+ },
+ "SIDEBAR": {
+ "show_search": True,
+ "show_all_applications": True,
+ "navigation": navigation.PAGES
+ }
+}
\ No newline at end of file
diff --git a/core/config/unfold_navigation.py b/core/config/unfold_navigation.py
index e69de29..749ae28 100644
--- a/core/config/unfold_navigation.py
+++ b/core/config/unfold_navigation.py
@@ -0,0 +1,49 @@
+from django.urls import reverse_lazy
+from django.utils.translation import gettext_lazy as _
+
+
+def user_has_group_or_permission(user, permission):
+ if user.is_superuser:
+ return True
+
+ group_names = user.groups.values_list("name", flat=True)
+ if not group_names:
+ return True
+
+ return user.groups.filter(permissions__codename=permission).exists()
+
+
+PAGES = [
+ {
+ "seperator": True,
+ "items": [
+ {
+ "title": _("Home"),
+ "icon": "home",
+ "link": reverse_lazy("admin:index"),
+ },
+ ],
+ },
+ {
+ "seperator": True,
+ "title": _("Users"),
+ "items": [
+ {
+ "title": _("Groups"),
+ "icon": "person_add",
+ "link": reverse_lazy("admin:auth_group_changelist"),
+ "permission": lambda request: user_has_group_or_permission(
+ request.user, "view_group",
+ ),
+ },
+ {
+ "title": _("Users"),
+ "icon": "person_add",
+ "link": reverse_lazy("admin:users_user_changelist"),
+ "permission": lambda request: user_has_group_or_permission(
+ request.user, "view_user",
+ ),
+ },
+ ],
+ },
+]
\ No newline at end of file
diff --git a/core/settings/base.py b/core/settings/base.py
index 861c16f..db58ac0 100644
--- a/core/settings/base.py
+++ b/core/settings/base.py
@@ -19,7 +19,7 @@
ALLOWED_HOSTS = str(os.getenv("ALLOWED_HOSTS")).split(",")
-INSTALLED_APPS = DEFAULT_APPS + PROJECT_APPS + THIRD_PARTY_APPS # NOQA
+INSTALLED_APPS = THIRD_PARTY_APPS + DEFAULT_APPS + PROJECT_APPS # NOQA
MIDDLEWARE = [
@@ -101,8 +101,8 @@
LOGIN_REDIRECT_URL = "/"
STATIC_URL = "static/"
-STATIC_ROOT = BASE_DIR.joinpath("staticfiles")
-STATICFILES_DIRS = [BASE_DIR.joinpath("static")]
+STATICFILES_DIRS = [str(BASE_DIR.joinpath("static"))]
+STATIC_ROOT = str(BASE_DIR.joinpath("staticfiles"))
# AUTHENTICATION_BACKENDS = (
# 'apps.users.authentication.JWTAdminAuthentication',
@@ -110,7 +110,7 @@
# )
MEDIA_URL = "media/"
-MEDIA_ROOT = BASE_DIR.joinpath("media/")
+MEDIA_ROOT = str(BASE_DIR.joinpath("media/"))
DEFAULT_AUTO_FIELD = "django.db.models.BigAutoField"
diff --git a/core/urls.py b/core/urls.py
index 2dc1816..be5fcd3 100644
--- a/core/urls.py
+++ b/core/urls.py
@@ -23,13 +23,17 @@
}
# URLs
-urlpatterns = i18n_patterns(
+urlpatterns = [
path("admin/", admin.site.urls),
path("i18n", include("django.conf.urls.i18n")),
+ path("rosetta/", include("rosetta.urls")),
+]
+
+# Translated urls
+urlpatterns += i18n_patterns(
path("", include("apps.blog.urls", namespace="blog")),
path("users/", include("apps.users.urls", namespace="users")),
path("robots.txt", TemplateView.as_view(template_name="bunin/robots.txt")),
- path("rosetta/", include("rosetta.urls")),
path(
"sitemap.xml",
sitemap,
diff --git a/media/avatars/1727198193049.jpg b/media/avatars/1727198193049.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9214f00082590e6a4dd3b8a5c33517e5fffb45be
GIT binary patch
literal 16242
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
literal 0
HcmV?d00001
diff --git a/media/avatars/DALLE_2024-09-27_14_PN7dbHS.30.15_-_A_young_man_with_short_hair_and_glasses_wearing_a_formal_business_suit._The_background_is_a_professional_conference_room_setting_with_modern_lightin.webp b/media/avatars/DALLE_2024-09-27_14_PN7dbHS.30.15_-_A_young_man_with_short_hair_and_glasses_wearing_a_formal_business_suit._The_background_is_a_professional_conference_room_setting_with_modern_lightin.webp
new file mode 100644
index 0000000000000000000000000000000000000000..ff9cc12c9456a6e6dd0593190208e54d77df8a8e
GIT binary patch
literal 15794
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
literal 0
HcmV?d00001
diff --git a/static/css/tailwind.css b/static/css/tailwind.css
new file mode 100644
index 0000000..5b0c2f7
--- /dev/null
+++ b/static/css/tailwind.css
@@ -0,0 +1,945 @@
+/*! tailwindcss v3.4.3 | MIT License | https://tailwindcss.com*/
+*, :after, :before {
+ box-sizing: border-box;
+ border: 0 solid #e5e7eb
+}
+
+:after, :before {
+ --tw-content: ""
+}
+
+:host, html {
+ line-height: 1.5;
+ -webkit-text-size-adjust: 100%;
+ -moz-tab-size: 4;
+ -o-tab-size: 4;
+ tab-size: 4;
+ font-family: ui-sans-serif, system-ui, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
+ font-feature-settings: normal;
+ font-variation-settings: normal;
+ -webkit-tap-highlight-color: transparent
+}
+
+body {
+ margin: 0;
+ line-height: inherit
+}
+
+hr {
+ height: 0;
+ color: inherit;
+ border-top-width: 1px
+}
+
+abbr:where([title]) {
+ -webkit-text-decoration: underline dotted;
+ text-decoration: underline dotted
+}
+
+h1, h2, h3, h4, h5, h6 {
+ font-size: inherit;
+ font-weight: inherit
+}
+
+a {
+ color: inherit;
+ text-decoration: inherit
+}
+
+b, strong {
+ font-weight: bolder
+}
+
+code, kbd, pre, samp {
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
+ font-feature-settings: normal;
+ font-variation-settings: normal;
+ font-size: 1em
+}
+
+small {
+ font-size: 80%
+}
+
+sub, sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: initial
+}
+
+sub {
+ bottom: -.25em
+}
+
+sup {
+ top: -.5em
+}
+
+table {
+ text-indent: 0;
+ border-color: inherit;
+ border-collapse: collapse
+}
+
+button, input, optgroup, select, textarea {
+ font-family: inherit;
+ font-feature-settings: inherit;
+ font-variation-settings: inherit;
+ font-size: 100%;
+ font-weight: inherit;
+ line-height: inherit;
+ letter-spacing: inherit;
+ color: inherit;
+ margin: 0;
+ padding: 0
+}
+
+button, select {
+ text-transform: none
+}
+
+button, input:where([type=button]), input:where([type=reset]), input:where([type=submit]) {
+ -webkit-appearance: button;
+ background-color: initial;
+ background-image: none
+}
+
+:-moz-focusring {
+ outline: auto
+}
+
+:-moz-ui-invalid {
+ box-shadow: none
+}
+
+progress {
+ vertical-align: initial
+}
+
+::-webkit-inner-spin-button, ::-webkit-outer-spin-button {
+ height: auto
+}
+
+[type=search] {
+ -webkit-appearance: textfield;
+ outline-offset: -2px
+}
+
+::-webkit-search-decoration {
+ -webkit-appearance: none
+}
+
+::-webkit-file-upload-button {
+ -webkit-appearance: button;
+ font: inherit
+}
+
+summary {
+ display: list-item
+}
+
+blockquote, dd, dl, figure, h1, h2, h3, h4, h5, h6, hr, p, pre {
+ margin: 0
+}
+
+fieldset {
+ margin: 0
+}
+
+fieldset, legend {
+ padding: 0
+}
+
+menu, ol, ul {
+ list-style: none;
+ margin: 0;
+ padding: 0
+}
+
+dialog {
+ padding: 0
+}
+
+textarea {
+ resize: vertical
+}
+
+input::-moz-placeholder, textarea::-moz-placeholder {
+ opacity: 1;
+ color: #9ca3af
+}
+
+input::placeholder, textarea::placeholder {
+ opacity: 1;
+ color: #9ca3af
+}
+
+[role=button], button {
+ cursor: pointer
+}
+
+:disabled {
+ cursor: default
+}
+
+audio, canvas, embed, iframe, img, object, svg, video {
+ display: block;
+ vertical-align: middle
+}
+
+img, video {
+ max-width: 100%;
+ height: auto
+}
+
+[hidden] {
+ display: none
+}
+
+*, ::backdrop, :after, :before {
+ --tw-border-spacing-x: 0;
+ --tw-border-spacing-y: 0;
+ --tw-translate-x: 0;
+ --tw-translate-y: 0;
+ --tw-rotate: 0;
+ --tw-skew-x: 0;
+ --tw-skew-y: 0;
+ --tw-scale-x: 1;
+ --tw-scale-y: 1;
+ --tw-pan-x: ;
+ --tw-pan-y: ;
+ --tw-pinch-zoom: ;
+ --tw-scroll-snap-strictness: proximity;
+ --tw-gradient-from-position: ;
+ --tw-gradient-via-position: ;
+ --tw-gradient-to-position: ;
+ --tw-ordinal: ;
+ --tw-slashed-zero: ;
+ --tw-numeric-figure: ;
+ --tw-numeric-spacing: ;
+ --tw-numeric-fraction: ;
+ --tw-ring-inset: ;
+ --tw-ring-offset-width: 0px;
+ --tw-ring-offset-color: #fff;
+ --tw-ring-color: #3b82f680;
+ --tw-ring-offset-shadow: 0 0 #0000;
+ --tw-ring-shadow: 0 0 #0000;
+ --tw-shadow: 0 0 #0000;
+ --tw-shadow-colored: 0 0 #0000;
+ --tw-blur: ;
+ --tw-brightness: ;
+ --tw-contrast: ;
+ --tw-grayscale: ;
+ --tw-hue-rotate: ;
+ --tw-invert: ;
+ --tw-saturate: ;
+ --tw-sepia: ;
+ --tw-drop-shadow: ;
+ --tw-backdrop-blur: ;
+ --tw-backdrop-brightness: ;
+ --tw-backdrop-contrast: ;
+ --tw-backdrop-grayscale: ;
+ --tw-backdrop-hue-rotate: ;
+ --tw-backdrop-invert: ;
+ --tw-backdrop-opacity: ;
+ --tw-backdrop-saturate: ;
+ --tw-backdrop-sepia: ;
+ --tw-contain-size: ;
+ --tw-contain-layout: ;
+ --tw-contain-paint: ;
+ --tw-contain-style:
+}
+
+.\!container {
+ width: 100% !important
+}
+
+.container {
+ width: 100%
+}
+
+@media (min-width: 640px) {
+ .\!container {
+ max-width: 640px !important
+ }
+
+ .container {
+ max-width: 640px
+ }
+}
+
+@media (min-width: 768px) {
+ .\!container {
+ max-width: 768px !important
+ }
+
+ .container {
+ max-width: 768px
+ }
+}
+
+@media (min-width: 1024px) {
+ .\!container {
+ max-width: 1024px !important
+ }
+
+ .container {
+ max-width: 1024px
+ }
+}
+
+@media (min-width: 1280px) {
+ .\!container {
+ max-width: 1280px !important
+ }
+
+ .container {
+ max-width: 1280px
+ }
+}
+
+@media (min-width: 1536px) {
+ .\!container {
+ max-width: 1536px !important
+ }
+
+ .container {
+ max-width: 1536px
+ }
+}
+
+.visible {
+ visibility: visible
+}
+
+.collapse {
+ visibility: collapse
+}
+
+.static {
+ position: static
+}
+
+.\!fixed {
+ position: fixed !important
+}
+
+.fixed {
+ position: fixed
+}
+
+.absolute {
+ position: absolute
+}
+
+.relative {
+ position: relative
+}
+
+.sticky {
+ position: sticky
+}
+
+.left-0 {
+ left: 0
+}
+
+.left-5 {
+ left: 1.25rem
+}
+
+.top-0 {
+ top: 0
+}
+
+.z-\[99\] {
+ z-index: 99
+}
+
+.float-right {
+ float: right
+}
+
+.m-2 {
+ margin: .5rem
+}
+
+.mx-4 {
+ margin-left: 1rem;
+ margin-right: 1rem
+}
+
+.mb-1 {
+ margin-bottom: .25rem
+}
+
+.mb-3 {
+ margin-bottom: .75rem
+}
+
+.mb-5 {
+ margin-bottom: 1.25rem
+}
+
+.ml-2 {
+ margin-left: .5rem
+}
+
+.ml-auto {
+ margin-left: auto
+}
+
+.mr-2 {
+ margin-right: .5rem
+}
+
+.mr-auto {
+ margin-right: auto
+}
+
+.mt-10 {
+ margin-top: 2.5rem
+}
+
+.mt-3 {
+ margin-top: .75rem
+}
+
+.mt-4 {
+ margin-top: 1rem
+}
+
+.mt-5 {
+ margin-top: 1.25rem
+}
+
+.mb-10 {
+ margin-bottom: 2.5rem
+}
+
+.mt-2 {
+ margin-top: .5rem
+}
+
+.block {
+ display: block
+}
+
+.inline-block {
+ display: inline-block
+}
+
+.inline {
+ display: inline
+}
+
+.flex {
+ display: flex
+}
+
+.inline-flex {
+ display: inline-flex
+}
+
+.table {
+ display: table
+}
+
+.table-caption {
+ display: table-caption
+}
+
+.table-cell {
+ display: table-cell
+}
+
+.grid {
+ display: grid
+}
+
+.contents {
+ display: contents
+}
+
+.\!hidden {
+ display: none !important
+}
+
+.hidden {
+ display: none
+}
+
+.size-2 {
+ width: .5rem;
+ height: .5rem
+}
+
+.h-1 {
+ height: .25rem
+}
+
+.h-14 {
+ height: 3.5rem
+}
+
+.h-16 {
+ height: 4rem
+}
+
+.h-3 {
+ height: .75rem
+}
+
+.h-8 {
+ height: 2rem
+}
+
+.h-\[100vh\] {
+ height: 100vh
+}
+
+.max-h-\[400px\] {
+ max-height: 400px
+}
+
+.w-\[100vw\] {
+ width: 100vw
+}
+
+.w-\[90\%\] {
+ width: 90%
+}
+
+.w-full {
+ width: 100%
+}
+
+.max-w-\[500px\] {
+ max-width: 500px
+}
+
+.max-w-\[90vw\] {
+ max-width: 90vw
+}
+
+.max-w-\[20px\] {
+ max-width: 20px
+}
+
+.max-w-\[300px\] {
+ max-width: 300px
+}
+
+.flex-shrink, .shrink {
+ flex-shrink: 1
+}
+
+.flex-grow, .grow {
+ flex-grow: 1
+}
+
+.border-collapse {
+ border-collapse: collapse
+}
+
+.transform {
+ transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))
+}
+
+.cursor-pointer {
+ cursor: pointer
+}
+
+.resize {
+ resize: both
+}
+
+.grid-cols-1 {
+ grid-template-columns:repeat(1, minmax(0, 1fr))
+}
+
+.grid-cols-2 {
+ grid-template-columns:repeat(2, minmax(0, 1fr))
+}
+
+.flex-col {
+ flex-direction: column
+}
+
+.flex-wrap {
+ flex-wrap: wrap
+}
+
+.items-center {
+ align-items: center
+}
+
+.justify-end {
+ justify-content: flex-end
+}
+
+.justify-center {
+ justify-content: center
+}
+
+.gap-10 {
+ gap: 2.5rem
+}
+
+.gap-8 {
+ gap: 2rem
+}
+
+.gap-2 {
+ gap: .5rem
+}
+
+.gap-5 {
+ gap: 1.25rem
+}
+
+.gap-x-3 {
+ -moz-column-gap: .75rem;
+ column-gap: .75rem
+}
+
+.truncate {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap
+}
+
+.rounded {
+ border-radius: .25rem
+}
+
+.rounded-xl {
+ border-radius: .75rem
+}
+
+.border {
+ border-width: 1px
+}
+
+.border-black {
+ --tw-border-opacity: 1;
+ border-color: rgb(0 0 0/var(--tw-border-opacity))
+}
+
+.bg-blue-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(59 130 246/var(--tw-bg-opacity))
+}
+
+.bg-gray-200 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(229 231 235/var(--tw-bg-opacity))
+}
+
+.bg-orange-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(249 115 22/var(--tw-bg-opacity))
+}
+
+.bg-white {
+ --tw-bg-opacity: 1;
+ background-color: rgb(255 255 255/var(--tw-bg-opacity))
+}
+
+.bg-red-500 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(239 68 68/var(--tw-bg-opacity))
+}
+
+.bg-gray-400 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(156 163 175/var(--tw-bg-opacity))
+}
+
+.bg-gray-700 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(55 65 81/var(--tw-bg-opacity))
+}
+
+.bg-blue-400 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(96 165 250/var(--tw-bg-opacity))
+}
+
+.bg-green-400 {
+ --tw-bg-opacity: 1;
+ background-color: rgb(74 222 128/var(--tw-bg-opacity))
+}
+
+.\!bg-gray-700 {
+ --tw-bg-opacity: 1 !important;
+ background-color: rgb(55 65 81/var(--tw-bg-opacity)) !important
+}
+
+.\!bg-orange-500 {
+ --tw-bg-opacity: 1 !important;
+ background-color: rgb(249 115 22/var(--tw-bg-opacity)) !important
+}
+
+.\!bg-red-500 {
+ --tw-bg-opacity: 1 !important;
+ background-color: rgb(239 68 68/var(--tw-bg-opacity)) !important
+}
+
+.p-1 {
+ padding: .25rem
+}
+
+.p-14 {
+ padding: 3.5rem
+}
+
+.p-16 {
+ padding: 4rem
+}
+
+.p-2 {
+ padding: .5rem
+}
+
+.p-3 {
+ padding: .75rem
+}
+
+.p-4 {
+ padding: 1rem
+}
+
+.p-5 {
+ padding: 1.25rem
+}
+
+.p-8 {
+ padding: 2rem
+}
+
+.px-\[40px\] {
+ padding-left: 40px;
+ padding-right: 40px
+}
+
+.py-3 {
+ padding-top: .75rem;
+ padding-bottom: .75rem
+}
+
+.py-2 {
+ padding-top: .5rem;
+ padding-bottom: .5rem
+}
+
+.px-3 {
+ padding-left: .75rem;
+ padding-right: .75rem
+}
+
+.text-center {
+ text-align: center
+}
+
+.indent-1 {
+ text-indent: .25rem
+}
+
+.text-\[20px\] {
+ font-size: 20px
+}
+
+.text-\[25px\] {
+ font-size: 25px
+}
+
+.text-\[30px\] {
+ font-size: 30px
+}
+
+.text-\[40px\] {
+ font-size: 40px
+}
+
+.text-sm {
+ font-size: .875rem;
+ line-height: 1.25rem
+}
+
+.text-\[27px\] {
+ font-size: 27px
+}
+
+.font-\[400\] {
+ font-weight: 400
+}
+
+.font-\[500\] {
+ font-weight: 500
+}
+
+.font-\[600\] {
+ font-weight: 600
+}
+
+.font-bold {
+ font-weight: 700
+}
+
+.uppercase {
+ text-transform: uppercase
+}
+
+.lowercase {
+ text-transform: lowercase
+}
+
+.capitalize {
+ text-transform: capitalize
+}
+
+.italic {
+ font-style: italic
+}
+
+.text-black {
+ --tw-text-opacity: 1;
+ color: rgb(0 0 0/var(--tw-text-opacity))
+}
+
+.text-blue-500 {
+ --tw-text-opacity: 1;
+ color: rgb(59 130 246/var(--tw-text-opacity))
+}
+
+.text-red-500 {
+ --tw-text-opacity: 1;
+ color: rgb(239 68 68/var(--tw-text-opacity))
+}
+
+.text-white {
+ --tw-text-opacity: 1;
+ color: rgb(255 255 255/var(--tw-text-opacity))
+}
+
+.\!text-white {
+ --tw-text-opacity: 1 !important;
+ color: rgb(255 255 255/var(--tw-text-opacity)) !important
+}
+
+.text-\[px\] {
+ color: px
+}
+
+.underline {
+ text-decoration-line: underline
+}
+
+.line-through {
+ text-decoration-line: line-through
+}
+
+.antialiased {
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale
+}
+
+.shadow {
+ --tw-shadow: 0 1px 3px 0 #0000001a, 0 1px 2px -1px #0000001a;
+ --tw-shadow-colored: 0 1px 3px 0 var(--tw-shadow-color), 0 1px 2px -1px var(--tw-shadow-color)
+}
+
+.shadow, .shadow-md {
+ box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow)
+}
+
+.shadow-md {
+ --tw-shadow: 0 4px 6px -1px #0000001a, 0 2px 4px -2px #0000001a;
+ --tw-shadow-colored: 0 4px 6px -1px var(--tw-shadow-color), 0 2px 4px -2px var(--tw-shadow-color)
+}
+
+.outline {
+ outline-style: solid
+}
+
+.ring {
+ --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
+ --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(3px + var(--tw-ring-offset-width)) var(--tw-ring-color);
+ box-shadow: var(--tw-ring-offset-shadow), var(--tw-ring-shadow), var(--tw-shadow, 0 0 #0000)
+}
+
+.blur {
+ --tw-blur: blur(8px)
+}
+
+.blur, .grayscale {
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
+}
+
+.grayscale {
+ --tw-grayscale: grayscale(100%)
+}
+
+.\!invert {
+ --tw-invert: invert(100%) !important;
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important
+}
+
+.invert {
+ --tw-invert: invert(100%);
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
+}
+
+.\!filter {
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow) !important
+}
+
+.filter {
+ filter: var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)
+}
+
+.backdrop-blur-sm {
+ --tw-backdrop-blur: blur(4px);
+ -webkit-backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);
+ backdrop-filter: var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)
+}
+
+.transition {
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, -webkit-backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter;
+ transition-property: color, background-color, border-color, text-decoration-color, fill, stroke, opacity, box-shadow, transform, filter, backdrop-filter, -webkit-backdrop-filter;
+ transition-timing-function: cubic-bezier(.4, 0, .2, 1);
+ transition-duration: .15s
+}
+
+.ease-out {
+ transition-timing-function: cubic-bezier(0, 0, .2, 1)
+}
+
+.\[a-zA-Z\:\\-\] {
+ a-z-a--z: \-
+}
+
+@media (min-width: 640px) {
+ .sm\:grid-cols-2 {
+ grid-template-columns:repeat(2, minmax(0, 1fr))
+ }
+}
+
+@media (min-width: 768px) {
+ .md\:grid-cols-2 {
+ grid-template-columns:repeat(2, minmax(0, 1fr))
+ }
+
+ .md\:grid-cols-3 {
+ grid-template-columns:repeat(3, minmax(0, 1fr))
+ }
+}
+
+@media (min-width: 1024px) {
+ .lg\:grid-cols-4 {
+ grid-template-columns:repeat(4, minmax(0, 1fr))
+ }
+}
\ No newline at end of file
diff --git a/static/images/django-logo.png b/static/images/django-logo.png
new file mode 100644
index 0000000000000000000000000000000000000000..81ddb8553439f2cc6e87ed6ab141ea3343f05477
GIT binary patch
literal 28071
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