Настроил сеелери, начал привязку lyngsat
This commit is contained in:
@@ -1,229 +1,229 @@
|
||||
"""
|
||||
Переиспользуемые миксины для представлений mainapp.
|
||||
|
||||
Этот модуль содержит миксины для стандартизации общей логики в представлениях,
|
||||
включая проверку прав доступа, обработку координат и сообщений.
|
||||
"""
|
||||
|
||||
# Standard library imports
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
# Django imports
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
from django.contrib.gis.geos import Point
|
||||
|
||||
|
||||
class RoleRequiredMixin(UserPassesTestMixin):
|
||||
"""
|
||||
Mixin для проверки роли пользователя.
|
||||
|
||||
Проверяет, что пользователь имеет одну из требуемых ролей для доступа к представлению.
|
||||
|
||||
Attributes:
|
||||
required_roles (list): Список допустимых ролей для доступа.
|
||||
По умолчанию ['admin', 'moderator'].
|
||||
|
||||
Example:
|
||||
class MyView(RoleRequiredMixin, View):
|
||||
required_roles = ['admin', 'moderator']
|
||||
|
||||
def get(self, request):
|
||||
# Только пользователи с ролью admin или moderator могут получить доступ
|
||||
return render(request, 'template.html')
|
||||
"""
|
||||
|
||||
required_roles = ["admin", "moderator"]
|
||||
|
||||
def test_func(self) -> bool:
|
||||
"""
|
||||
Проверяет, имеет ли пользователь требуемую роль.
|
||||
|
||||
Returns:
|
||||
bool: True если пользователь имеет одну из требуемых ролей, иначе False.
|
||||
"""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if not hasattr(self.request.user, "customuser"):
|
||||
return False
|
||||
|
||||
return self.request.user.customuser.role in self.required_roles
|
||||
|
||||
|
||||
class CoordinateProcessingMixin:
|
||||
"""
|
||||
Mixin для обработки координат из POST данных форм.
|
||||
|
||||
Предоставляет методы для извлечения и обработки координат различных типов
|
||||
(геолокация, кубсат, оперативники) из POST запроса и применения их к объекту Geo.
|
||||
|
||||
Example:
|
||||
class MyFormView(CoordinateProcessingMixin, FormView):
|
||||
def form_valid(self, form):
|
||||
geo_instance = Geo()
|
||||
self.process_coordinates(geo_instance)
|
||||
geo_instance.save()
|
||||
return super().form_valid(form)
|
||||
"""
|
||||
|
||||
def process_coordinates(self, geo_instance, prefix: str = "geo") -> None:
|
||||
"""
|
||||
Обрабатывает координаты из POST данных и применяет их к объекту Geo.
|
||||
|
||||
Извлекает координаты геолокации, кубсата и оперативников из POST запроса
|
||||
и устанавливает соответствующие поля объекта Geo.
|
||||
|
||||
Args:
|
||||
geo_instance: Экземпляр модели Geo для обновления координат.
|
||||
prefix (str): Префикс для полей формы (по умолчанию 'geo').
|
||||
|
||||
Note:
|
||||
Метод ожидает следующие поля в request.POST:
|
||||
- geo_longitude, geo_latitude: координаты геолокации
|
||||
- kupsat_longitude, kupsat_latitude: координаты кубсата
|
||||
- valid_longitude, valid_latitude: координаты оперативников
|
||||
"""
|
||||
# Обрабатываем координаты геолокации
|
||||
geo_coords = self._extract_coordinates("geo")
|
||||
if geo_coords:
|
||||
geo_instance.coords = Point(geo_coords[0], geo_coords[1], srid=4326)
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_coords = self._extract_coordinates("kupsat")
|
||||
if kupsat_coords:
|
||||
geo_instance.coords_kupsat = Point(
|
||||
kupsat_coords[0], kupsat_coords[1], srid=4326
|
||||
)
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_coords = self._extract_coordinates("valid")
|
||||
if valid_coords:
|
||||
geo_instance.coords_valid = Point(
|
||||
valid_coords[0], valid_coords[1], srid=4326
|
||||
)
|
||||
|
||||
def _extract_coordinates(self, coord_type: str) -> Optional[Tuple[float, float]]:
|
||||
"""
|
||||
Извлекает координаты указанного типа из POST данных.
|
||||
|
||||
Args:
|
||||
coord_type (str): Тип координат ('geo', 'kupsat', 'valid').
|
||||
|
||||
Returns:
|
||||
Optional[Tuple[float, float]]: Кортеж (longitude, latitude) или None,
|
||||
если координаты не найдены или невалидны.
|
||||
"""
|
||||
longitude_key = f"{coord_type}_longitude"
|
||||
latitude_key = f"{coord_type}_latitude"
|
||||
|
||||
longitude = self.request.POST.get(longitude_key)
|
||||
latitude = self.request.POST.get(latitude_key)
|
||||
|
||||
if longitude and latitude:
|
||||
try:
|
||||
return (float(longitude), float(latitude))
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
return None
|
||||
|
||||
def process_timestamp(self, geo_instance) -> None:
|
||||
"""
|
||||
Обрабатывает дату и время из POST данных и применяет к объекту Geo.
|
||||
|
||||
Args:
|
||||
geo_instance: Экземпляр модели Geo для обновления timestamp.
|
||||
|
||||
Note:
|
||||
Метод ожидает следующие поля в request.POST:
|
||||
- timestamp_date: дата в формате YYYY-MM-DD
|
||||
- timestamp_time: время в формате HH:MM
|
||||
"""
|
||||
timestamp_date = self.request.POST.get("timestamp_date")
|
||||
timestamp_time = self.request.POST.get("timestamp_time")
|
||||
|
||||
if timestamp_date and timestamp_time:
|
||||
try:
|
||||
naive_datetime = datetime.strptime(
|
||||
f"{timestamp_date} {timestamp_time}", "%Y-%m-%d %H:%M"
|
||||
)
|
||||
geo_instance.timestamp = naive_datetime
|
||||
except ValueError:
|
||||
# Если формат даты/времени неверный, пропускаем
|
||||
pass
|
||||
|
||||
|
||||
class FormMessageMixin:
|
||||
"""
|
||||
Mixin для стандартизации сообщений об успехе и ошибках в формах.
|
||||
|
||||
Автоматически добавляет сообщения пользователю при успешной или неуспешной
|
||||
обработке формы.
|
||||
|
||||
Attributes:
|
||||
success_message (str): Сообщение при успешной обработке формы.
|
||||
error_message (str): Сообщение при ошибке обработки формы.
|
||||
|
||||
Example:
|
||||
class MyFormView(FormMessageMixin, FormView):
|
||||
success_message = "Данные успешно сохранены!"
|
||||
error_message = "Ошибка при сохранении данных"
|
||||
|
||||
def form_valid(self, form):
|
||||
# Автоматически добавит success_message
|
||||
return super().form_valid(form)
|
||||
"""
|
||||
|
||||
success_message = "Операция выполнена успешно"
|
||||
error_message = "Произошла ошибка при обработке формы"
|
||||
|
||||
def form_valid(self, form):
|
||||
"""
|
||||
Обрабатывает валидную форму и добавляет сообщение об успехе.
|
||||
|
||||
Args:
|
||||
form: Валидная форма Django.
|
||||
|
||||
Returns:
|
||||
HttpResponse: Результат обработки родительского метода form_valid.
|
||||
"""
|
||||
if self.success_message:
|
||||
messages.success(self.request, self.success_message)
|
||||
return super().form_valid(form)
|
||||
|
||||
def form_invalid(self, form):
|
||||
"""
|
||||
Обрабатывает невалидную форму и добавляет сообщение об ошибке.
|
||||
|
||||
Args:
|
||||
form: Невалидная форма Django.
|
||||
|
||||
Returns:
|
||||
HttpResponse: Результат обработки родительского метода form_invalid.
|
||||
"""
|
||||
if self.error_message:
|
||||
messages.error(self.request, self.error_message)
|
||||
return super().form_invalid(form)
|
||||
|
||||
def get_success_message(self) -> str:
|
||||
"""
|
||||
Возвращает сообщение об успехе.
|
||||
|
||||
Может быть переопределен в подклассах для динамического формирования сообщения.
|
||||
|
||||
Returns:
|
||||
str: Сообщение об успехе.
|
||||
"""
|
||||
return self.success_message
|
||||
|
||||
def get_error_message(self) -> str:
|
||||
"""
|
||||
Возвращает сообщение об ошибке.
|
||||
|
||||
Может быть переопределен в подклассах для динамического формирования сообщения.
|
||||
|
||||
Returns:
|
||||
str: Сообщение об ошибке.
|
||||
"""
|
||||
return self.error_message
|
||||
"""
|
||||
Переиспользуемые миксины для представлений mainapp.
|
||||
|
||||
Этот модуль содержит миксины для стандартизации общей логики в представлениях,
|
||||
включая проверку прав доступа, обработку координат и сообщений.
|
||||
"""
|
||||
|
||||
# Standard library imports
|
||||
from datetime import datetime
|
||||
from typing import Optional, Tuple
|
||||
|
||||
# Django imports
|
||||
from django.contrib import messages
|
||||
from django.contrib.auth.mixins import UserPassesTestMixin
|
||||
from django.contrib.gis.geos import Point
|
||||
|
||||
|
||||
class RoleRequiredMixin(UserPassesTestMixin):
|
||||
"""
|
||||
Mixin для проверки роли пользователя.
|
||||
|
||||
Проверяет, что пользователь имеет одну из требуемых ролей для доступа к представлению.
|
||||
|
||||
Attributes:
|
||||
required_roles (list): Список допустимых ролей для доступа.
|
||||
По умолчанию ['admin', 'moderator'].
|
||||
|
||||
Example:
|
||||
class MyView(RoleRequiredMixin, View):
|
||||
required_roles = ['admin', 'moderator']
|
||||
|
||||
def get(self, request):
|
||||
# Только пользователи с ролью admin или moderator могут получить доступ
|
||||
return render(request, 'template.html')
|
||||
"""
|
||||
|
||||
required_roles = ["admin", "moderator"]
|
||||
|
||||
def test_func(self) -> bool:
|
||||
"""
|
||||
Проверяет, имеет ли пользователь требуемую роль.
|
||||
|
||||
Returns:
|
||||
bool: True если пользователь имеет одну из требуемых ролей, иначе False.
|
||||
"""
|
||||
if not self.request.user.is_authenticated:
|
||||
return False
|
||||
|
||||
if not hasattr(self.request.user, "customuser"):
|
||||
return False
|
||||
|
||||
return self.request.user.customuser.role in self.required_roles
|
||||
|
||||
|
||||
class CoordinateProcessingMixin:
|
||||
"""
|
||||
Mixin для обработки координат из POST данных форм.
|
||||
|
||||
Предоставляет методы для извлечения и обработки координат различных типов
|
||||
(геолокация, кубсат, оперативники) из POST запроса и применения их к объекту Geo.
|
||||
|
||||
Example:
|
||||
class MyFormView(CoordinateProcessingMixin, FormView):
|
||||
def form_valid(self, form):
|
||||
geo_instance = Geo()
|
||||
self.process_coordinates(geo_instance)
|
||||
geo_instance.save()
|
||||
return super().form_valid(form)
|
||||
"""
|
||||
|
||||
def process_coordinates(self, geo_instance, prefix: str = "geo") -> None:
|
||||
"""
|
||||
Обрабатывает координаты из POST данных и применяет их к объекту Geo.
|
||||
|
||||
Извлекает координаты геолокации, кубсата и оперативников из POST запроса
|
||||
и устанавливает соответствующие поля объекта Geo.
|
||||
|
||||
Args:
|
||||
geo_instance: Экземпляр модели Geo для обновления координат.
|
||||
prefix (str): Префикс для полей формы (по умолчанию 'geo').
|
||||
|
||||
Note:
|
||||
Метод ожидает следующие поля в request.POST:
|
||||
- geo_longitude, geo_latitude: координаты геолокации
|
||||
- kupsat_longitude, kupsat_latitude: координаты кубсата
|
||||
- valid_longitude, valid_latitude: координаты оперативников
|
||||
"""
|
||||
# Обрабатываем координаты геолокации
|
||||
geo_coords = self._extract_coordinates("geo")
|
||||
if geo_coords:
|
||||
geo_instance.coords = Point(geo_coords[0], geo_coords[1], srid=4326)
|
||||
|
||||
# Обрабатываем координаты Кубсата
|
||||
kupsat_coords = self._extract_coordinates("kupsat")
|
||||
if kupsat_coords:
|
||||
geo_instance.coords_kupsat = Point(
|
||||
kupsat_coords[0], kupsat_coords[1], srid=4326
|
||||
)
|
||||
|
||||
# Обрабатываем координаты оперативников
|
||||
valid_coords = self._extract_coordinates("valid")
|
||||
if valid_coords:
|
||||
geo_instance.coords_valid = Point(
|
||||
valid_coords[0], valid_coords[1], srid=4326
|
||||
)
|
||||
|
||||
def _extract_coordinates(self, coord_type: str) -> Optional[Tuple[float, float]]:
|
||||
"""
|
||||
Извлекает координаты указанного типа из POST данных.
|
||||
|
||||
Args:
|
||||
coord_type (str): Тип координат ('geo', 'kupsat', 'valid').
|
||||
|
||||
Returns:
|
||||
Optional[Tuple[float, float]]: Кортеж (longitude, latitude) или None,
|
||||
если координаты не найдены или невалидны.
|
||||
"""
|
||||
longitude_key = f"{coord_type}_longitude"
|
||||
latitude_key = f"{coord_type}_latitude"
|
||||
|
||||
longitude = self.request.POST.get(longitude_key)
|
||||
latitude = self.request.POST.get(latitude_key)
|
||||
|
||||
if longitude and latitude:
|
||||
try:
|
||||
return (float(longitude), float(latitude))
|
||||
except (ValueError, TypeError):
|
||||
return None
|
||||
return None
|
||||
|
||||
def process_timestamp(self, geo_instance) -> None:
|
||||
"""
|
||||
Обрабатывает дату и время из POST данных и применяет к объекту Geo.
|
||||
|
||||
Args:
|
||||
geo_instance: Экземпляр модели Geo для обновления timestamp.
|
||||
|
||||
Note:
|
||||
Метод ожидает следующие поля в request.POST:
|
||||
- timestamp_date: дата в формате YYYY-MM-DD
|
||||
- timestamp_time: время в формате HH:MM
|
||||
"""
|
||||
timestamp_date = self.request.POST.get("timestamp_date")
|
||||
timestamp_time = self.request.POST.get("timestamp_time")
|
||||
|
||||
if timestamp_date and timestamp_time:
|
||||
try:
|
||||
naive_datetime = datetime.strptime(
|
||||
f"{timestamp_date} {timestamp_time}", "%Y-%m-%d %H:%M"
|
||||
)
|
||||
geo_instance.timestamp = naive_datetime
|
||||
except ValueError:
|
||||
# Если формат даты/времени неверный, пропускаем
|
||||
pass
|
||||
|
||||
|
||||
class FormMessageMixin:
|
||||
"""
|
||||
Mixin для стандартизации сообщений об успехе и ошибках в формах.
|
||||
|
||||
Автоматически добавляет сообщения пользователю при успешной или неуспешной
|
||||
обработке формы.
|
||||
|
||||
Attributes:
|
||||
success_message (str): Сообщение при успешной обработке формы.
|
||||
error_message (str): Сообщение при ошибке обработки формы.
|
||||
|
||||
Example:
|
||||
class MyFormView(FormMessageMixin, FormView):
|
||||
success_message = "Данные успешно сохранены!"
|
||||
error_message = "Ошибка при сохранении данных"
|
||||
|
||||
def form_valid(self, form):
|
||||
# Автоматически добавит success_message
|
||||
return super().form_valid(form)
|
||||
"""
|
||||
|
||||
success_message = "Операция выполнена успешно"
|
||||
error_message = "Произошла ошибка при обработке формы"
|
||||
|
||||
def form_valid(self, form):
|
||||
"""
|
||||
Обрабатывает валидную форму и добавляет сообщение об успехе.
|
||||
|
||||
Args:
|
||||
form: Валидная форма Django.
|
||||
|
||||
Returns:
|
||||
HttpResponse: Результат обработки родительского метода form_valid.
|
||||
"""
|
||||
if self.success_message:
|
||||
messages.success(self.request, self.success_message)
|
||||
return super().form_valid(form)
|
||||
|
||||
def form_invalid(self, form):
|
||||
"""
|
||||
Обрабатывает невалидную форму и добавляет сообщение об ошибке.
|
||||
|
||||
Args:
|
||||
form: Невалидная форма Django.
|
||||
|
||||
Returns:
|
||||
HttpResponse: Результат обработки родительского метода form_invalid.
|
||||
"""
|
||||
if self.error_message:
|
||||
messages.error(self.request, self.error_message)
|
||||
return super().form_invalid(form)
|
||||
|
||||
def get_success_message(self) -> str:
|
||||
"""
|
||||
Возвращает сообщение об успехе.
|
||||
|
||||
Может быть переопределен в подклассах для динамического формирования сообщения.
|
||||
|
||||
Returns:
|
||||
str: Сообщение об успехе.
|
||||
"""
|
||||
return self.success_message
|
||||
|
||||
def get_error_message(self) -> str:
|
||||
"""
|
||||
Возвращает сообщение об ошибке.
|
||||
|
||||
Может быть переопределен в подклассах для динамического формирования сообщения.
|
||||
|
||||
Returns:
|
||||
str: Сообщение об ошибке.
|
||||
"""
|
||||
return self.error_message
|
||||
|
||||
Reference in New Issue
Block a user