diff --git a/dbapp/dbapp/settings/base.py b/dbapp/dbapp/settings/base.py index 8ecf2ff..8f486b6 100644 --- a/dbapp/dbapp/settings/base.py +++ b/dbapp/dbapp/settings/base.py @@ -150,6 +150,11 @@ USE_I18N = True USE_TZ = True +# Authentication settings +LOGIN_URL = 'login' +LOGIN_REDIRECT_URL = 'home' +LOGOUT_REDIRECT_URL = 'home' + # Static files (CSS, JavaScript, Images) # https://docs.djangoproject.com/en/5.2/howto/static-files/ diff --git a/dbapp/dbapp/urls.py b/dbapp/dbapp/urls.py index c494521..2b68550 100644 --- a/dbapp/dbapp/urls.py +++ b/dbapp/dbapp/urls.py @@ -17,6 +17,7 @@ Including another URLconf from django.contrib import admin from django.urls import path, include from mainapp import views +from django.contrib.auth import views as auth_views from debug_toolbar.toolbar import debug_toolbar_urls urlpatterns = [ @@ -24,5 +25,8 @@ urlpatterns = [ path('admin/', admin.site.urls, name='admin'), # path('admin/map/', views.show_map_view, name='admin_show_map'), path('', include('mainapp.urls')), - path('', include('mapsapp.urls')) + path('', include('mapsapp.urls')), + # Authentication URLs + path('login/', auth_views.LoginView.as_view(), name='login'), + path('logout/', views.custom_logout, name='logout'), ] + debug_toolbar_urls() diff --git a/dbapp/mainapp/admin.py b/dbapp/mainapp/admin.py index 6c9b831..88b9283 100644 --- a/dbapp/mainapp/admin.py +++ b/dbapp/mainapp/admin.py @@ -40,10 +40,17 @@ from .filters import GeoKupDistanceFilter, GeoValidDistanceFilter, UniqueToggleF admin.site.site_title = "Геолокация" admin.site.site_header = "Geolocation" admin.site.index_title = "Geo" +# Unregister default User and Group since we're customizing them admin.site.unregister(User) admin.site.unregister(Group) +class CustomUserInline(admin.StackedInline): + model = CustomUser + can_delete = False + verbose_name_plural = 'Дополнительная информация пользователя' + + class LocationForm(forms.ModelForm): latitude_geo = forms.FloatField(required=False, label="Широта") longitude_geo = forms.FloatField(required=False, label="Долгота") @@ -117,23 +124,18 @@ class GeoInline(admin.StackedInline): ) -class CustomUserInline(admin.StackedInline): - model = CustomUser - can_delete = False - verbose_name_plural = 'Дополнительная информация пользователя' - - -@admin.register(CustomUser) -class CustomUserAdmin(admin.ModelAdmin): - list_display = ('user', 'role') - list_filter = ('role',) - - class UserAdmin(BaseUserAdmin): inlines = [CustomUserInline] admin.site.register(User, UserAdmin) + +# @admin.register(CustomUser) +# class CustomUserAdmin(admin.ModelAdmin): +# list_display = ('user', 'role') +# list_filter = ('role',) +# raw_id_fields = ('user',) # For better performance with large number of users + @admin.register(SigmaParMark) class SigmaParMarkAdmin(admin.ModelAdmin): list_display = ("mark", "timestamp") @@ -410,7 +412,6 @@ class ParameterObjItemInline(admin.StackedInline): max_num = 1 verbose_name = "ВЧ загрузка" verbose_name_plural = "ВЧ загрузки" - @admin.register(ObjItem) @@ -430,6 +431,8 @@ class ObjectAdmin(admin.ModelAdmin): "distance_geo_kup", "distance_geo_valid", "distance_kup_valid", + "created_at", + "updated_at", ) list_display_links = ("name",) list_filter = ( @@ -452,18 +455,28 @@ class ObjectAdmin(admin.ModelAdmin): ordering = ("name",) inlines = [ParameterObjItemInline, GeoInline] actions = [show_on_map] - - + readonly_fields = ('created_at', 'created_by', 'updated_at', 'updated_by') def get_queryset(self, request): qs = super().get_queryset(request) - return qs.select_related('geo_obj').prefetch_related( + return qs.select_related('geo_obj', 'created_by', 'updated_by').prefetch_related( 'parameters_obj__id_satellite', 'parameters_obj__polarization', 'parameters_obj__modulation', 'parameters_obj__standard' ) + def get_readonly_fields(self, request, obj=None): + # Always make these fields readonly to preserve tracking + return self.readonly_fields + + def save_model(self, request, obj, form, change): + if not change: + if not obj.created_by_id: + obj.created_by = request.user.customuser if hasattr(request.user, 'customuser') else None + obj.updated_by = request.user.customuser if hasattr(request.user, 'customuser') else None + super().save_model(request, obj, form, change) + def sat_name(self, obj): param = next(iter(obj.parameters_obj.all()), None) if param and param.id_satellite: diff --git a/dbapp/mainapp/apps.py b/dbapp/mainapp/apps.py index 8aa89a8..7047f84 100644 --- a/dbapp/mainapp/apps.py +++ b/dbapp/mainapp/apps.py @@ -4,3 +4,6 @@ from django.apps import AppConfig class MainappConfig(AppConfig): default_auto_field = 'django.db.models.BigAutoField' name = 'mainapp' + + def ready(self): + import mainapp.signals # noqa diff --git a/dbapp/mainapp/management/commands/create_user_profiles.py b/dbapp/mainapp/management/commands/create_user_profiles.py new file mode 100644 index 0000000..50910df --- /dev/null +++ b/dbapp/mainapp/management/commands/create_user_profiles.py @@ -0,0 +1,20 @@ +from django.core.management.base import BaseCommand +from django.contrib.auth.models import User +from mainapp.models import CustomUser + + +class Command(BaseCommand): + help = 'Create CustomUser profiles for existing users who do not have them' + + def handle(self, *args, **options): + # Find all users who don't have a CustomUser profile + for user in User.objects.all(): + if not hasattr(user, 'customuser'): + custom_user = CustomUser.objects.create(user=user) + self.stdout.write( + self.style.SUCCESS(f'Created CustomUser for {user.username}') + ) + + self.stdout.write( + self.style.SUCCESS('Successfully ensured all users have CustomUser profiles') + ) \ No newline at end of file diff --git a/dbapp/mainapp/migrations/0001_initial.py b/dbapp/mainapp/migrations/0001_initial.py index fe3ada0..66f8653 100644 --- a/dbapp/mainapp/migrations/0001_initial.py +++ b/dbapp/mainapp/migrations/0001_initial.py @@ -1,7 +1,9 @@ -# Generated by Django 5.2.7 on 2025-10-13 12:47 +# Generated by Django 5.2.7 on 2025-10-31 13:36 import django.contrib.gis.db.models.fields +import django.contrib.gis.db.models.functions import django.db.models.deletion +import django.db.models.expressions import mainapp.models from django.conf import settings from django.db import migrations, models @@ -31,7 +33,7 @@ class Migration(migrations.Migration): name='Modulation', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=20, unique=True, verbose_name='Модуляция')), + ('name', models.CharField(db_index=True, max_length=20, unique=True, verbose_name='Модуляция')), ], options={ 'verbose_name': 'Модуляция', @@ -53,7 +55,7 @@ class Migration(migrations.Migration): name='Satellite', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=30, unique=True, verbose_name='Имя спутника')), + ('name', models.CharField(db_index=True, max_length=100, unique=True, verbose_name='Имя спутника')), ('norad', models.IntegerField(blank=True, null=True, verbose_name='NORAD ID')), ], options={ @@ -61,6 +63,18 @@ class Migration(migrations.Migration): 'verbose_name_plural': 'Спутники', }, ), + migrations.CreateModel( + name='SigmaParMark', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('mark', models.BooleanField(blank=True, null=True, verbose_name='Наличие сигнала')), + ('timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Время')), + ], + options={ + 'verbose_name': 'Отметка', + 'verbose_name_plural': 'Отметки', + }, + ), migrations.CreateModel( name='Standard', fields=[ @@ -85,35 +99,30 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='Geo', + name='ObjItem', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Время')), - ('coords', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координата геолокации')), - ('location', models.CharField(blank=True, max_length=255, null=True, verbose_name='Метоположение')), - ('comment', models.CharField(blank=True, max_length=255, verbose_name='Комментарий')), - ('coords_kupsat', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координаты Кубсата')), - ('coords_valid', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координаты оперативников')), - ('is_average', models.BooleanField(blank=True, null=True, verbose_name='Усреднённое')), - ('id_user_add', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='geos_added', to='mainapp.customuser', verbose_name='Пользователь')), - ('mirrors', models.ManyToManyField(related_name='geo_mirrors', to='mainapp.mirror', verbose_name='Зеркала')), + ('name', models.CharField(blank=True, db_index=True, max_length=100, null=True, verbose_name='Имя объекта')), + ('id_user_add', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems', to='mainapp.customuser', verbose_name='Пользователь')), ], options={ - 'verbose_name': 'Гео', - 'verbose_name_plural': 'Гео', + 'verbose_name': 'Объект', + 'verbose_name_plural': 'Объекты', }, ), migrations.CreateModel( name='Parameter', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('frequency', models.FloatField(blank=True, default=0, null=True, verbose_name='Частота, МГц')), + ('frequency', models.FloatField(blank=True, db_index=True, default=0, null=True, verbose_name='Частота, МГц')), ('freq_range', models.FloatField(blank=True, default=0, null=True, verbose_name='Полоса частот, МГц')), ('bod_velocity', models.FloatField(blank=True, default=0, null=True, verbose_name='Символьная скорость, БОД')), ('snr', models.FloatField(blank=True, default=0, null=True, verbose_name='ОСШ')), ('id_user_add', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parameter_added', to='mainapp.customuser', verbose_name='Пользователь')), ('modulation', models.ForeignKey(blank=True, default=mainapp.models.get_default_modulation, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='modulations', to='mainapp.modulation', verbose_name='Модуляция')), + ('objitems', models.ManyToManyField(blank=True, related_name='parameters_obj', to='mainapp.objitem', verbose_name='Источники')), ('polarization', models.ForeignKey(blank=True, default=mainapp.models.get_default_polarization, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='polarizations', to='mainapp.polarization', verbose_name='Поляризация')), + ('id_satellite', models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='parameters', to='mainapp.satellite', verbose_name='Спутник')), ('standard', models.ForeignKey(blank=True, default=mainapp.models.get_default_standard, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='standards', to='mainapp.standard', verbose_name='Стандарт')), ], options={ @@ -122,26 +131,74 @@ class Migration(migrations.Migration): }, ), migrations.CreateModel( - name='ObjItem', + name='SourceType', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(blank=True, max_length=100, null=True, verbose_name='Имя объекта')), - ('id_geo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='objitems', to='mainapp.geo', verbose_name='Геоданные')), - ('id_user_add', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems', to='mainapp.customuser', verbose_name='Пользователь')), - ('id_vch_load', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='objitems', to='mainapp.parameter', verbose_name='ВЧ загрузка')), - ('id_satellite', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='objitems', to='mainapp.satellite', verbose_name='Спутник')), + ('name', models.CharField(max_length=50, unique=True, verbose_name='Тип источника')), + ('objitem', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='source_type_obj', to='mainapp.objitem', verbose_name='Гео')), ], options={ - 'verbose_name': 'Объект', - 'verbose_name_plural': 'Объекты', + 'verbose_name': 'Тип источника', + 'verbose_name_plural': 'Типы источников', }, ), - migrations.AddConstraint( - model_name='geo', - constraint=models.UniqueConstraint(fields=('timestamp', 'coords'), name='unique_geo_combination'), + migrations.CreateModel( + name='SigmaParameter', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('transfer', models.FloatField(choices=[(-1.0, '-'), (9750.0, '9750 МГц'), (10750.0, '10750 МГц')], default=-1.0, verbose_name='Перенос по частоте')), + ('status', models.CharField(blank=True, max_length=20, null=True, verbose_name='Статус')), + ('frequency', models.FloatField(blank=True, db_index=True, default=0, null=True, verbose_name='Частота, МГц')), + ('transfer_frequency', models.GeneratedField(db_persist=True, expression=models.ExpressionWrapper(django.db.models.expressions.CombinedExpression(models.F('frequency'), '+', models.F('transfer')), output_field=models.FloatField()), null=True, output_field=models.FloatField(), verbose_name='Частота в Ku, МГц')), + ('freq_range', models.FloatField(blank=True, default=0, null=True, verbose_name='Полоса частот, МГц')), + ('power', models.FloatField(blank=True, default=0, null=True, verbose_name='Мощность, дБм')), + ('bod_velocity', models.FloatField(blank=True, default=0, null=True, verbose_name='Символьная скорость, БОД')), + ('snr', models.FloatField(blank=True, default=0, null=True, verbose_name='ОСШ, Дб')), + ('packets', models.BooleanField(blank=True, null=True, verbose_name='Пакетность')), + ('datetime_begin', models.DateTimeField(blank=True, null=True, verbose_name='Время начала измерения')), + ('datetime_end', models.DateTimeField(blank=True, null=True, verbose_name='Время окончания измерения')), + ('id_satellite', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, related_name='sigmapar_sat', to='mainapp.satellite', verbose_name='Спутник')), + ('modulation', models.ForeignKey(blank=True, default=mainapp.models.get_default_modulation, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='modulations_sigma', to='mainapp.modulation', verbose_name='Модуляция')), + ('parameter', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sigma_parameter', to='mainapp.parameter', verbose_name='ВЧ')), + ('polarization', models.ForeignKey(blank=True, default=mainapp.models.get_default_polarization, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='polarizations_sigma', to='mainapp.polarization', verbose_name='Поляризация')), + ('mark', models.ManyToManyField(blank=True, to='mainapp.sigmaparmark', verbose_name='Отметка')), + ('standard', models.ForeignKey(blank=True, default=mainapp.models.get_default_standard, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='standards_sigma', to='mainapp.standard', verbose_name='Стандарт')), + ], + options={ + 'verbose_name': 'ВЧ sigma', + 'verbose_name_plural': 'ВЧ sigma', + }, ), - migrations.AddConstraint( - model_name='objitem', - constraint=models.UniqueConstraint(fields=('id_vch_load', 'id_geo'), name='unique_objitem_combination'), + migrations.CreateModel( + name='Geo', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('timestamp', models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Время')), + ('coords', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координата геолокации')), + ('location', models.CharField(blank=True, max_length=255, null=True, verbose_name='Метоположение')), + ('comment', models.CharField(blank=True, max_length=255, verbose_name='Комментарий')), + ('coords_kupsat', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координаты Кубсата')), + ('coords_valid', django.contrib.gis.db.models.fields.PointField(blank=True, null=True, srid=4326, verbose_name='Координаты оперативников')), + ('is_average', models.BooleanField(blank=True, null=True, verbose_name='Усреднённое')), + ('distance_coords_kup', models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords', 'coords_kupsat'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и гео, км')), + ('distance_coords_valid', models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords', 'coords_valid'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между гео и оперативным отделом, км')), + ('distance_kup_valid', models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords_valid', 'coords_kupsat'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и оперативным отделом, км')), + ('id_user_add', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='geos_added', to='mainapp.customuser', verbose_name='Пользователь')), + ('mirrors', models.ManyToManyField(related_name='geo_mirrors', to='mainapp.mirror', verbose_name='Зеркала')), + ('objitem', models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='geo_obj', to='mainapp.objitem', verbose_name='Гео')), + ], + options={ + 'verbose_name': 'Гео', + 'verbose_name_plural': 'Гео', + 'constraints': [models.UniqueConstraint(fields=('timestamp', 'coords'), name='unique_geo_combination')], + }, + ), + migrations.AddIndex( + model_name='parameter', + index=models.Index(fields=['id_satellite', 'frequency'], name='mainapp_par_id_sate_cbfab2_idx'), + ), + migrations.AddIndex( + model_name='parameter', + index=models.Index(fields=['frequency', 'polarization'], name='mainapp_par_frequen_75a049_idx'), ), ] diff --git a/dbapp/mainapp/migrations/0002_geo_distance_coords_kup.py b/dbapp/mainapp/migrations/0002_geo_distance_coords_kup.py deleted file mode 100644 index 2765567..0000000 --- a/dbapp/mainapp/migrations/0002_geo_distance_coords_kup.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-15 09:23 - -import django.contrib.gis.db.models.functions -import django.db.models.expressions -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='geo', - name='distance_coords_kup', - field=models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords', 'coords_kupsat'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и гео'), - ), - ] diff --git a/dbapp/mainapp/migrations/0002_objitem_created_at_objitem_created_by_and_more.py b/dbapp/mainapp/migrations/0002_objitem_created_at_objitem_created_by_and_more.py new file mode 100644 index 0000000..8669b50 --- /dev/null +++ b/dbapp/mainapp/migrations/0002_objitem_created_at_objitem_created_by_and_more.py @@ -0,0 +1,35 @@ +# Generated by Django 5.2.7 on 2025-10-31 13:56 + +import django.db.models.deletion +import django.utils.timezone +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='objitem', + name='created_at', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Дата создания'), + ), + migrations.AddField( + model_name='objitem', + name='created_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems_created', to='mainapp.customuser', verbose_name='Создан пользователем'), + ), + migrations.AddField( + model_name='objitem', + name='updated_at', + field=models.DateTimeField(default=django.utils.timezone.now, verbose_name='Дата последнего изменения'), + ), + migrations.AddField( + model_name='objitem', + name='updated_by', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems_updated', to='mainapp.customuser', verbose_name='Изменен пользователем'), + ), + ] diff --git a/dbapp/mainapp/migrations/0003_alter_objitem_created_at_alter_objitem_updated_at.py b/dbapp/mainapp/migrations/0003_alter_objitem_created_at_alter_objitem_updated_at.py new file mode 100644 index 0000000..2503260 --- /dev/null +++ b/dbapp/mainapp/migrations/0003_alter_objitem_created_at_alter_objitem_updated_at.py @@ -0,0 +1,23 @@ +# Generated by Django 5.2.7 on 2025-10-31 14:02 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('mainapp', '0002_objitem_created_at_objitem_created_by_and_more'), + ] + + operations = [ + migrations.AlterField( + model_name='objitem', + name='created_at', + field=models.DateTimeField(auto_now_add=True, verbose_name='Дата создания'), + ), + migrations.AlterField( + model_name='objitem', + name='updated_at', + field=models.DateTimeField(auto_now=True, verbose_name='Дата последнего изменения'), + ), + ] diff --git a/dbapp/mainapp/migrations/0003_geo_distance_coords_valid_geo_distance_kup_valid_and_more.py b/dbapp/mainapp/migrations/0003_geo_distance_coords_valid_geo_distance_kup_valid_and_more.py deleted file mode 100644 index 9db723c..0000000 --- a/dbapp/mainapp/migrations/0003_geo_distance_coords_valid_geo_distance_kup_valid_and_more.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-15 09:43 - -import django.contrib.gis.db.models.functions -import django.db.models.expressions -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0002_geo_distance_coords_kup'), - ] - - operations = [ - migrations.AddField( - model_name='geo', - name='distance_coords_valid', - field=models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords', 'coords_valid'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между гео и оперативным отделом, км'), - ), - migrations.AddField( - model_name='geo', - name='distance_kup_valid', - field=models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords_valid', 'coords_kupsat'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и оперативным отделом, км'), - ), - migrations.AlterField( - model_name='geo', - name='distance_coords_kup', - field=models.GeneratedField(db_persist=True, expression=django.db.models.expressions.CombinedExpression(django.contrib.gis.db.models.functions.Distance('coords', 'coords_kupsat'), '/', models.Value(1000)), null=True, output_field=models.FloatField(), verbose_name='Расстояние между купсатом и гео, км'), - ), - ] diff --git a/dbapp/mainapp/migrations/0004_sigmaparameter.py b/dbapp/mainapp/migrations/0004_sigmaparameter.py deleted file mode 100644 index 75bbbeb..0000000 --- a/dbapp/mainapp/migrations/0004_sigmaparameter.py +++ /dev/null @@ -1,36 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-16 12:50 - -import django.db.models.deletion -import mainapp.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0003_geo_distance_coords_valid_geo_distance_kup_valid_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='SigmaParameter', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('status', models.CharField(blank=True, max_length=20, null=True, verbose_name='Статус')), - ('frequency', models.FloatField(blank=True, default=0, null=True, verbose_name='Частота, МГц')), - ('freq_range', models.FloatField(blank=True, default=0, null=True, verbose_name='Полоса частот, МГц')), - ('power', models.FloatField(blank=True, default=0, null=True, verbose_name='Мощность, дБм')), - ('bod_velocity', models.FloatField(blank=True, default=0, null=True, verbose_name='Символьная скорость, БОД')), - ('snr', models.FloatField(blank=True, default=0, null=True, verbose_name='ОСШ, Дб')), - ('packets', models.BooleanField(blank=True, null=True, verbose_name='Пакетность')), - ('datetime_begin', models.DateTimeField(blank=True, null=True, verbose_name='Время начала измерения')), - ('datetime_end', models.DateTimeField(blank=True, null=True, verbose_name='Время окончания измерения')), - ('modulation', models.ForeignKey(blank=True, default=mainapp.models.get_default_modulation, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='modulations_sigma', to='mainapp.modulation', verbose_name='Модуляция')), - ('standard', models.ForeignKey(blank=True, default=mainapp.models.get_default_standard, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='standards_sigma', to='mainapp.standard', verbose_name='Стандарт')), - ], - options={ - 'verbose_name': 'ВЧ sigma', - 'verbose_name_plural': 'ВЧ sigma', - }, - ), - ] diff --git a/dbapp/mainapp/migrations/0005_sigmaparameter_id_satellite.py b/dbapp/mainapp/migrations/0005_sigmaparameter_id_satellite.py deleted file mode 100644 index 78de627..0000000 --- a/dbapp/mainapp/migrations/0005_sigmaparameter_id_satellite.py +++ /dev/null @@ -1,20 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-20 07:57 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0004_sigmaparameter'), - ] - - operations = [ - migrations.AddField( - model_name='sigmaparameter', - name='id_satellite', - field=models.ForeignKey(default=2, on_delete=django.db.models.deletion.PROTECT, related_name='sigmapar_sat', to='mainapp.satellite', verbose_name='Спутник'), - preserve_default=False, - ), - ] diff --git a/dbapp/mainapp/migrations/0006_remove_objitem_id_satellite_parameter_id_satellite.py b/dbapp/mainapp/migrations/0006_remove_objitem_id_satellite_parameter_id_satellite.py deleted file mode 100644 index d32435e..0000000 --- a/dbapp/mainapp/migrations/0006_remove_objitem_id_satellite_parameter_id_satellite.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-20 11:57 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0005_sigmaparameter_id_satellite'), - ] - - operations = [ - migrations.RemoveField( - model_name='objitem', - name='id_satellite', - ), - migrations.AddField( - model_name='parameter', - name='id_satellite', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='parameters', to='mainapp.satellite', verbose_name='Спутник'), - ), - ] diff --git a/dbapp/mainapp/migrations/0007_alter_parameter_id_satellite.py b/dbapp/mainapp/migrations/0007_alter_parameter_id_satellite.py deleted file mode 100644 index d288cb7..0000000 --- a/dbapp/mainapp/migrations/0007_alter_parameter_id_satellite.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-20 11:58 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0006_remove_objitem_id_satellite_parameter_id_satellite'), - ] - - operations = [ - migrations.AlterField( - model_name='parameter', - name='id_satellite', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.PROTECT, related_name='parameters', to='mainapp.satellite', verbose_name='Спутник'), - ), - ] diff --git a/dbapp/mainapp/migrations/0008_alter_geo_timestamp_alter_objitem_name_and_more.py b/dbapp/mainapp/migrations/0008_alter_geo_timestamp_alter_objitem_name_and_more.py deleted file mode 100644 index d3bbd5a..0000000 --- a/dbapp/mainapp/migrations/0008_alter_geo_timestamp_alter_objitem_name_and_more.py +++ /dev/null @@ -1,38 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 11:21 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0007_alter_parameter_id_satellite'), - ] - - operations = [ - migrations.AlterField( - model_name='geo', - name='timestamp', - field=models.DateTimeField(blank=True, db_index=True, null=True, verbose_name='Время'), - ), - migrations.AlterField( - model_name='objitem', - name='name', - field=models.CharField(blank=True, db_index=True, max_length=100, null=True, verbose_name='Имя объекта'), - ), - migrations.AlterField( - model_name='parameter', - name='frequency', - field=models.FloatField(blank=True, db_index=True, default=0, null=True, verbose_name='Частота, МГц'), - ), - migrations.AlterField( - model_name='satellite', - name='name', - field=models.CharField(db_index=True, max_length=30, unique=True, verbose_name='Имя спутника'), - ), - migrations.AlterField( - model_name='sigmaparameter', - name='frequency', - field=models.FloatField(blank=True, db_index=True, default=0, null=True, verbose_name='Частота, МГц'), - ), - ] diff --git a/dbapp/mainapp/migrations/0009_parameter_id_sigma_parameter.py b/dbapp/mainapp/migrations/0009_parameter_id_sigma_parameter.py deleted file mode 100644 index af7c76d..0000000 --- a/dbapp/mainapp/migrations/0009_parameter_id_sigma_parameter.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 12:08 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0008_alter_geo_timestamp_alter_objitem_name_and_more'), - ] - - operations = [ - migrations.AddField( - model_name='parameter', - name='id_sigma_parameter', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sigma_parameter', to='mainapp.sigmaparameter', verbose_name='ВЧ с sigma'), - ), - ] diff --git a/dbapp/mainapp/migrations/0010_sigmaparmark_sigmaparameter_mark.py b/dbapp/mainapp/migrations/0010_sigmaparmark_sigmaparameter_mark.py deleted file mode 100644 index 6049caf..0000000 --- a/dbapp/mainapp/migrations/0010_sigmaparmark_sigmaparameter_mark.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 12:38 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0009_parameter_id_sigma_parameter'), - ] - - operations = [ - migrations.CreateModel( - name='SigmaParMark', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('mark', models.BooleanField(blank=True, null=True, verbose_name='Наличие сигнала')), - ('timestamp', models.DateTimeField(blank=True, null=True, verbose_name='Время')), - ], - options={ - 'verbose_name': 'Отметка', - 'verbose_name_plural': 'Отметки', - }, - ), - migrations.AddField( - model_name='sigmaparameter', - name='mark', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='mainapp.sigmaparmark', verbose_name='Отметка'), - ), - ] diff --git a/dbapp/mainapp/migrations/0011_remove_sigmaparameter_mark_sigmaparameter_mark.py b/dbapp/mainapp/migrations/0011_remove_sigmaparameter_mark_sigmaparameter_mark.py deleted file mode 100644 index 226aea9..0000000 --- a/dbapp/mainapp/migrations/0011_remove_sigmaparameter_mark_sigmaparameter_mark.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 13:15 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0010_sigmaparmark_sigmaparameter_mark'), - ] - - operations = [ - migrations.RemoveField( - model_name='sigmaparameter', - name='mark', - ), - migrations.AddField( - model_name='sigmaparameter', - name='mark', - field=models.ManyToManyField(blank=True, null=True, to='mainapp.sigmaparmark', verbose_name='Отметка'), - ), - ] diff --git a/dbapp/mainapp/migrations/0012_alter_sigmaparameter_mark.py b/dbapp/mainapp/migrations/0012_alter_sigmaparameter_mark.py deleted file mode 100644 index 7246fe2..0000000 --- a/dbapp/mainapp/migrations/0012_alter_sigmaparameter_mark.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 13:16 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0011_remove_sigmaparameter_mark_sigmaparameter_mark'), - ] - - operations = [ - migrations.AlterField( - model_name='sigmaparameter', - name='mark', - field=models.ManyToManyField(blank=True, to='mainapp.sigmaparmark', verbose_name='Отметка'), - ), - ] diff --git a/dbapp/mainapp/migrations/0013_parameter_mainapp_par_id_sate_cbfab2_idx_and_more.py b/dbapp/mainapp/migrations/0013_parameter_mainapp_par_id_sate_cbfab2_idx_and_more.py deleted file mode 100644 index 872fe8e..0000000 --- a/dbapp/mainapp/migrations/0013_parameter_mainapp_par_id_sate_cbfab2_idx_and_more.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-22 13:48 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0012_alter_sigmaparameter_mark'), - ] - - operations = [ - migrations.AddIndex( - model_name='parameter', - index=models.Index(fields=['id_satellite', 'frequency'], name='mainapp_par_id_sate_cbfab2_idx'), - ), - migrations.AddIndex( - model_name='parameter', - index=models.Index(fields=['frequency', 'polarization'], name='mainapp_par_frequen_75a049_idx'), - ), - ] diff --git a/dbapp/mainapp/migrations/0014_alter_modulation_name.py b/dbapp/mainapp/migrations/0014_alter_modulation_name.py deleted file mode 100644 index 71bce80..0000000 --- a/dbapp/mainapp/migrations/0014_alter_modulation_name.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-23 08:12 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0013_parameter_mainapp_par_id_sate_cbfab2_idx_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='modulation', - name='name', - field=models.CharField(db_index=True, max_length=20, unique=True, verbose_name='Модуляция'), - ), - ] diff --git a/dbapp/mainapp/migrations/0015_alter_parameter_id_sigma_parameter.py b/dbapp/mainapp/migrations/0015_alter_parameter_id_sigma_parameter.py deleted file mode 100644 index 9306a1f..0000000 --- a/dbapp/mainapp/migrations/0015_alter_parameter_id_sigma_parameter.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-23 09:40 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0014_alter_modulation_name'), - ] - - operations = [ - migrations.AlterField( - model_name='parameter', - name='id_sigma_parameter', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sigma_parameter', to='mainapp.sigmaparameter', verbose_name='ВЧ с sigma'), - ), - ] diff --git a/dbapp/mainapp/migrations/0016_remove_parameter_id_sigma_parameter_and_more.py b/dbapp/mainapp/migrations/0016_remove_parameter_id_sigma_parameter_and_more.py deleted file mode 100644 index 3171be4..0000000 --- a/dbapp/mainapp/migrations/0016_remove_parameter_id_sigma_parameter_and_more.py +++ /dev/null @@ -1,23 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-23 09:58 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0015_alter_parameter_id_sigma_parameter'), - ] - - operations = [ - migrations.RemoveField( - model_name='parameter', - name='id_sigma_parameter', - ), - migrations.AddField( - model_name='sigmaparameter', - name='parameter', - field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='sigma_parameter', to='mainapp.parameter', verbose_name='ВЧ с sigma'), - ), - ] diff --git a/dbapp/mainapp/migrations/0017_alter_sigmaparameter_parameter.py b/dbapp/mainapp/migrations/0017_alter_sigmaparameter_parameter.py deleted file mode 100644 index 68c6211..0000000 --- a/dbapp/mainapp/migrations/0017_alter_sigmaparameter_parameter.py +++ /dev/null @@ -1,19 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-23 12:52 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0016_remove_parameter_id_sigma_parameter_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='sigmaparameter', - name='parameter', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='sigma_parameter', to='mainapp.parameter', verbose_name='ВЧ'), - ), - ] diff --git a/dbapp/mainapp/migrations/0018_sigmaparameter_polarization_sigmaparameter_transfer_and_more.py b/dbapp/mainapp/migrations/0018_sigmaparameter_polarization_sigmaparameter_transfer_and_more.py deleted file mode 100644 index b3059f3..0000000 --- a/dbapp/mainapp/migrations/0018_sigmaparameter_polarization_sigmaparameter_transfer_and_more.py +++ /dev/null @@ -1,31 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-27 13:10 - -import django.db.models.deletion -import django.db.models.expressions -import mainapp.models -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0017_alter_sigmaparameter_parameter'), - ] - - operations = [ - migrations.AddField( - model_name='sigmaparameter', - name='polarization', - field=models.ForeignKey(blank=True, default=mainapp.models.get_default_polarization, null=True, on_delete=django.db.models.deletion.SET_DEFAULT, related_name='polarizations_sigma', to='mainapp.polarization', verbose_name='Поляризация'), - ), - migrations.AddField( - model_name='sigmaparameter', - name='transfer', - field=models.FloatField(choices=[(-1.0, '-'), (9750.0, '9750 МГц'), (10750.0, '10750 МГц')], default=-1.0, verbose_name='Перенос по частоте'), - ), - migrations.AddField( - model_name='sigmaparameter', - name='transfer_frequency', - field=models.GeneratedField(db_persist=True, expression=models.ExpressionWrapper(django.db.models.expressions.CombinedExpression(models.F('frequency'), '+', models.F('transfer')), output_field=models.FloatField()), null=True, output_field=models.FloatField(), verbose_name='Частота в Ku, МГц'), - ), - ] diff --git a/dbapp/mainapp/migrations/0019_alter_satellite_name.py b/dbapp/mainapp/migrations/0019_alter_satellite_name.py deleted file mode 100644 index eeec1fb..0000000 --- a/dbapp/mainapp/migrations/0019_alter_satellite_name.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-28 05:41 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0018_sigmaparameter_polarization_sigmaparameter_transfer_and_more'), - ] - - operations = [ - migrations.AlterField( - model_name='satellite', - name='name', - field=models.CharField(db_index=True, max_length=100, unique=True, verbose_name='Имя спутника'), - ), - ] diff --git a/dbapp/mainapp/migrations/0020_sourcetype_objitem_id_source_type.py b/dbapp/mainapp/migrations/0020_sourcetype_objitem_id_source_type.py deleted file mode 100644 index 4359cb1..0000000 --- a/dbapp/mainapp/migrations/0020_sourcetype_objitem_id_source_type.py +++ /dev/null @@ -1,30 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-29 14:00 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0019_alter_satellite_name'), - ] - - operations = [ - migrations.CreateModel( - name='SourceType', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=50, unique=True, verbose_name='Тип источника')), - ], - options={ - 'verbose_name': 'Тип источника', - 'verbose_name_plural': 'Типы источников', - }, - ), - migrations.AddField( - model_name='objitem', - name='id_source_type', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='objitems', to='mainapp.sourcetype', verbose_name='Тип источника'), - ), - ] diff --git a/dbapp/mainapp/migrations/0021_remove_objitem_unique_objitem_combination_and_more.py b/dbapp/mainapp/migrations/0021_remove_objitem_unique_objitem_combination_and_more.py deleted file mode 100644 index 2d01e77..0000000 --- a/dbapp/mainapp/migrations/0021_remove_objitem_unique_objitem_combination_and_more.py +++ /dev/null @@ -1,45 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-30 06:40 - -import django.db.models.deletion -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0020_sourcetype_objitem_id_source_type'), - ] - - operations = [ - migrations.RemoveConstraint( - model_name='objitem', - name='unique_objitem_combination', - ), - migrations.RemoveField( - model_name='objitem', - name='id_geo', - ), - migrations.RemoveField( - model_name='objitem', - name='id_source_type', - ), - migrations.RemoveField( - model_name='objitem', - name='id_vch_load', - ), - migrations.AddField( - model_name='geo', - name='objitem', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='geo_obj', to='mainapp.objitem', verbose_name='Гео'), - ), - migrations.AddField( - model_name='parameter', - name='objitem', - field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='parameters_obj', to='mainapp.objitem', verbose_name='Источник'), - ), - migrations.AddField( - model_name='sourcetype', - name='objitem', - field=models.OneToOneField(null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='source_type_obj', to='mainapp.objitem', verbose_name='Гео'), - ), - ] diff --git a/dbapp/mainapp/migrations/0022_remove_parameter_objitem_parameter_objitems.py b/dbapp/mainapp/migrations/0022_remove_parameter_objitem_parameter_objitems.py deleted file mode 100644 index 228f335..0000000 --- a/dbapp/mainapp/migrations/0022_remove_parameter_objitem_parameter_objitems.py +++ /dev/null @@ -1,22 +0,0 @@ -# Generated by Django 5.2.7 on 2025-10-30 07:05 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('mainapp', '0021_remove_objitem_unique_objitem_combination_and_more'), - ] - - operations = [ - migrations.RemoveField( - model_name='parameter', - name='objitem', - ), - migrations.AddField( - model_name='parameter', - name='objitems', - field=models.ManyToManyField(blank=True, related_name='parameters_obj', to='mainapp.objitem', verbose_name='Источники'), - ), - ] diff --git a/dbapp/mainapp/models.py b/dbapp/mainapp/models.py index 2a0296a..7bc3f23 100644 --- a/dbapp/mainapp/models.py +++ b/dbapp/mainapp/models.py @@ -3,6 +3,7 @@ from django.contrib.auth.models import User from django.contrib.gis.db import models as gis from django.contrib.gis.db.models import functions from django.db.models import F, ExpressionWrapper +from django.utils import timezone def get_default_polarization(): obj, created = Polarization.objects.get_or_create( @@ -113,8 +114,15 @@ class ObjItem(models.Model): # id_satellite = models.ForeignKey(Satellite, on_delete=models.PROTECT, related_name="objitems", verbose_name="Спутник") # id_vch_load = models.ForeignKey(Parameter, on_delete=models.CASCADE, related_name="objitems", verbose_name="ВЧ загрузка") # id_geo = models.ForeignKey(Geo, on_delete=models.CASCADE, related_name="objitems", verbose_name="Геоданные") - id_user_add = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="objitems", verbose_name="Пользователь", null=True, blank=True) + # id_user_add = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="objitems", verbose_name="Пользователь", null=True, blank=True) # id_source_type = models.ForeignKey(SourceType, on_delete=models.SET_NULL, related_name="objitems", verbose_name='Тип источника', null=True, blank=True) + + created_at = models.DateTimeField(auto_now_add=True, verbose_name="Дата создания") + created_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="objitems_created", + null=True, blank=True, verbose_name="Создан пользователем") + updated_at = models.DateTimeField(auto_now=True, verbose_name="Дата последнего изменения") + updated_by = models.ForeignKey(CustomUser, on_delete=models.SET_NULL, related_name="objitems_updated", + null=True, blank=True, verbose_name="Изменен пользователем") def __str__(self): diff --git a/dbapp/mainapp/signals.py b/dbapp/mainapp/signals.py new file mode 100644 index 0000000..0efba85 --- /dev/null +++ b/dbapp/mainapp/signals.py @@ -0,0 +1,11 @@ +from django.db.models.signals import post_save +from django.dispatch import receiver +from django.contrib.auth.models import User +from .models import CustomUser + + +@receiver(post_save, sender=User) +def create_or_update_user_profile(sender, instance, created, **kwargs): + if created: + CustomUser.objects.create(user=instance) + instance.customuser.save() \ No newline at end of file diff --git a/dbapp/mainapp/templates/mainapp/base.html b/dbapp/mainapp/templates/mainapp/base.html index 839b041..5c8b524 100644 --- a/dbapp/mainapp/templates/mainapp/base.html +++ b/dbapp/mainapp/templates/mainapp/base.html @@ -22,6 +22,7 @@
diff --git a/dbapp/mainapp/templates/mainapp/login_required.html b/dbapp/mainapp/templates/mainapp/login_required.html new file mode 100644 index 0000000..e344016 --- /dev/null +++ b/dbapp/mainapp/templates/mainapp/login_required.html @@ -0,0 +1,19 @@ +{% extends 'mainapp/base.html' %} + +{% block title %}Войдите в систему{% endblock %} + +{% block content %} +