AuthApp add
This commit is contained in:
SDE
2023-06-21 13:48:00 +03:00
parent e8c653ac30
commit 0f2ac168d6
21 changed files with 877 additions and 27 deletions

0
AuthApp/__init__.py Normal file
View File

150
AuthApp/admin.py Normal file
View File

@@ -0,0 +1,150 @@
# coding=utf-8
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from BaseModels.admin_utils import *
from django.contrib.auth.models import User
from django.utils.translation import gettext_lazy as _
from AuthApp.models import *
from django.contrib.auth.models import Group
from django.db import models
from django.contrib.admin.models import LogEntry
from django.db.models import F, Value as V
from django.db.models.functions import Concat
from django.contrib.auth.admin import GroupAdmin as BaseGroupAdmin
from django.contrib.auth.models import Group
from django.contrib.admin import SimpleListFilter
class LogEntryAdmin(admin.ModelAdmin):
# pass
list_display = (
'__str__', 'action_time', 'user', 'content_type', 'object_id', 'object_repr', 'action_flag', 'change_message')
list_filter = ('content_type', 'action_flag')
search_fields = ['user__username', 'change_message', 'object_id', 'object_repr']
date_hierarchy = 'action_time'
def has_delete_permission(self, request, obj=None):
return False
admin.site.register(LogEntry, LogEntryAdmin)
class Admin_ProfileInline(admin.StackedInline):
fieldsets = (
(None, {
'classes': ['wide'],
'fields': (
('enable',),
('phone',),
('country', 'city'),
('authMailCode',),
('birthdate'),
'comment', 'creator'
)
}),
('Дополнительно', {
'classes': ['wide'],
'fields': (
('json_data',)
)
}),
)
model = UserProfile
can_delete = False
extra = 1
fk_name = 'user'
# filter_horizontal = ['regions', 'connected_mailings']
# raw_id_fields = ("company_obj", 'office')
verbose_name_plural = _(u'Профиль пользователя')
# list_display = ['company_obj', 'office', 'company_position', 'departament', 'creator']
readonly_fields = ['creator', ]
class Admin_User(UserAdmin):
fieldsets = (
(None, {
'classes': ['wide'],
'fields': (
('username', 'password'),
('first_name', 'last_name', 'email'),
('is_active', 'is_staff', 'is_superuser'),
('groups', 'user_permissions'),
('last_login', 'date_joined'),
# ('username', 'first_name', 'last_name'),
# ('password'),
# ('email', 'is_active'),
# ('is_staff')
)
}),
)
save_on_top = True
list_display = ['id', 'last_name', 'first_name', 'email', 'is_staff',
'is_active']
list_editable = ['is_staff', 'is_active']
list_display_links = ['first_name', 'last_name', 'email']
search_fields = ['first_name', 'last_name', 'email']
inlines = (Admin_ProfileInline,)
# actions = ['del_all_temp_users', ]
ordering = ['is_staff', 'last_name', 'first_name']
# Re-register UserAdmin
admin.site.unregister(User)
admin.site.register(User, Admin_User)
class Admin_UserProfile(Admin_BaseIconModel):
fieldsets = (
(None, {
'classes': ['wide'],
'fields': (
'user', 'enable',
('account_type',),
('phone',),
('country', 'city'),
('authMailCode',),
('birthdate'),
'creator'
)
}),
('1С', {
'classes': ['wide'],
'fields': (
('id_1s', 'name',),
)
}),
)
save_on_top = True
list_display = [
'id', 'user', 'enable', 'birthdate', 'modifiedDT', 'createDT'
]
list_editable = ['enable', 'birthdate']
list_display_links = ['id', ] # 'user__last_name', 'user__first_name']
search_fields = [
'id', 'user__last_name', 'user__first_name', 'user__email',
]
list_filter = ['enable', 'account_type']
# filter_horizontal = ['connected_mailings']
# raw_id_fields = ("favourites",)
verbose_name_plural = _(u'Профиль пользователя')
admin.site.register(UserProfile, Admin_UserProfile)

70
AuthApp/forms.py Normal file
View File

@@ -0,0 +1,70 @@
# # coding=utf-8
# from django import forms
# from django.contrib.auth.forms import AuthenticationForm
# from django.utils.translation import ugettext_lazy as _
# from django.core.exceptions import ValidationError
# from .models import *
# # from djng.styling.bootstrap3.forms import Bootstrap3ModelForm
# # from djng.forms import fields, NgModelFormMixin, NgFormValidationMixin, NgModelForm
# # from datetimepicker.widgets import DateTimePicker
# # from datetimepicker.helpers import js_loader_url
#
#
#
# # class PersonForm(NgModelFormMixin, NgFormValidationMixin, NgModelForm, Bootstrap3ModelForm):
# #
# # form_name = 'person_form'
# # scope_prefix = 'person_data'
# #
# # class Meta:
# # model = UserProfile
# # fields = ['name', 'departament', 'company', 'company_position',
# # 'days_to_order_cancellation_default', 'days_to_pay_default',
# # 'pay_terms', 'birthdate',
# # 'phone', 'email', 'discount', 'document_sign_person']
#
#
#
# def emailValid(value):
# if User.objects.filter(username=value, is_active=True):
# raise ValidationError(_(u'пользователь с таким e-mail уже существует, воспользуйтесь восстановлением пароля'))
#
# def check_authorizationBy_cleaned_data(cleaned_data):
# from django.contrib.auth import authenticate
# print('check_authorizationBy_cleaned_data')
# username = cleaned_data.get('username')
# password = cleaned_data.get('password')
#
# user = authenticate(username=username, password=password)
# # print(user)
# if user:
# # if user.is_active:
# return user
#
# def check_activate_by_user(reg_user):
# print('check_activate_by_user')
# if reg_user:
# if reg_user.is_active:
# return True
#
# return False
#
# class LoginForm(AuthenticationForm):
# username = forms.EmailField(label=_('Email'), widget=forms.TextInput())
# password = forms.CharField(min_length=8, label=_('Пароль'), widget=forms.PasswordInput(render_value=False))
#
# def clean(self):
# # print('check')
# cleaned_data = super(LoginForm, self).clean()
# reg_user = check_authorizationBy_cleaned_data(cleaned_data)
# # print(reg_user)
# if not reg_user:
# raise ValidationError(_(u'Пользователь с введенными регистрационными данными не зарегистрирован. Проверьте правильность ввода e-mail и пароля.'))
# else:
# if not check_activate_by_user(reg_user):
# raise ValidationError(_(u'Указанная учетная запись не была Активирована'))
# return cleaned_data
#
#
# class ResetPassword_byEmail_Form(AuthenticationForm):
# email = forms.EmailField(label=_('Email'), widget=forms.TextInput())

View File

@@ -0,0 +1,44 @@
# Generated by Django 4.2.2 on 2023-06-20 14:50
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name='UserProfile',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название')),
('name_plural', models.TextField(blank=True, null=True, verbose_name='Название (множественное число)')),
('order', models.IntegerField(blank=True, null=True, verbose_name='Очередность отображения')),
('createDT', models.DateTimeField(auto_now_add=True, verbose_name='Дата и время создания')),
('modifiedDT', models.DateTimeField(blank=True, null=True, verbose_name='Дата и время последнего изменения')),
('enable', models.BooleanField(db_index=True, default=True, verbose_name='Включено')),
('json_data', models.JSONField(blank=True, default=dict, verbose_name='Дополнительные данные')),
('account_type', models.CharField(choices=[('Перевозчик', 'mover'), ('Отправитель', 'sender')], default='base_account', max_length=250, verbose_name='Тип учетной записи')),
('authMailCode', models.CharField(blank=True, max_length=32, null=True)),
('phone', models.CharField(blank=True, max_length=100, null=True, verbose_name='Телефон')),
('country', models.CharField(blank=True, max_length=250, null=True, verbose_name='Страна')),
('city', models.TextField(blank=True, null=True, verbose_name='Город')),
('birthdate', models.DateField(blank=True, null=True, verbose_name='Дата рождения')),
('comment', models.TextField(blank=True, null=True, verbose_name='Дополнительные сведения')),
('creator', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='rel_users_for_creator', to=settings.AUTH_USER_MODEL, verbose_name='Создатель')),
('user', models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='user_profile', to=settings.AUTH_USER_MODEL, verbose_name='Пользователь')),
],
options={
'verbose_name': 'Профиль',
'verbose_name_plural': 'Профили',
'ordering': ('user__last_name', 'user__first_name'),
},
),
]

View File

@@ -0,0 +1,18 @@
# Generated by Django 4.2.2 on 2023-06-20 14:52
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('AuthApp', '0001_initial'),
]
operations = [
migrations.AlterField(
model_name='userprofile',
name='city',
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='Город'),
),
]

View File

82
AuthApp/models.py Normal file
View File

@@ -0,0 +1,82 @@
# coding=utf-8
from __future__ import unicode_literals
from django.contrib.auth.models import User
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.db.models.signals import post_save, pre_save
from django.contrib.contenttypes.fields import GenericRelation
from django.contrib.postgres.fields import JSONField
from BaseModels.base_models import BaseModel
from datetime import datetime
def user_name_str(self):
return f'{self.last_name} {self.first_name}'
User.add_to_class("__str__", user_name_str)
account_type_choices = (
(_('Перевозчик'), 'mover'),
(_('Отправитель'), 'sender')
)
class UserProfile(BaseModel):
account_type = models.CharField(
max_length=250, verbose_name=_('Тип учетной записи'), choices=account_type_choices, default='base_account')
user = models.OneToOneField(User, verbose_name=_('Пользователь'), related_name=u'user_profile',
null=True, blank=True, on_delete=models.CASCADE)
authMailCode = models.CharField(max_length=32, null=True, blank=True)
phone = models.CharField(max_length=100, verbose_name=_('Телефон'), null=True, blank=True)
country = models.CharField(max_length=250, verbose_name=_('Страна'), null=True, blank=True)
city = models.CharField(max_length=250, verbose_name=_('Город'), null=True, blank=True)
birthdate = models.DateField(verbose_name=_('Дата рождения'), null=True, blank=True)
comment = models.TextField(verbose_name=_('Дополнительные сведения'), null=True, blank=True)
creator = models.ForeignKey(
User, verbose_name=_('Создатель'), related_name='rel_users_for_creator', null=True, blank=True,
on_delete=models.SET_NULL
)
def __str__(self):
if self.user:
return '{0} {1}'.format(self.user.last_name, self.user.first_name)
else:
return str(self.id)
class Meta:
verbose_name = _(u'Профиль')
verbose_name_plural = _(u'Профили')
ordering = ('user__last_name', 'user__first_name')
def create_user_profile(sender, instance, created, **kwargs):
if created:
UserProfile.objects.create(user=instance)
post_save.connect(create_user_profile, sender=User, dispatch_uid='post_save_connect')
def preSaveUser(sender, instance, **kwargs):
if not instance.email:
instance.email = str(instance.username).lower()
try:
instance.user_profile.modifiedDT = datetime.now()
except:
pass
pre_save.connect(preSaveUser, sender=User, dispatch_uid='pre_save_connect')

3
AuthApp/tests.py Normal file
View File

@@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

18
AuthApp/translation.py Normal file
View File

@@ -0,0 +1,18 @@
from modeltranslation.translator import translator, TranslationOptions
from .models import *
# class UserProfile_TranslationOptions(TranslationOptions):
# fields = (
# 'name', 'phone', 'city',
# )
# translator.register(UserProfile, UserProfile_TranslationOptions)
#
# class User_TranslationOptions(TranslationOptions):
# fields = (
# 'first_name', 'description', 'text', 'title', 'FAQ_title'
# )
# translator.register(User, User_TranslationOptions)

57
AuthApp/urls.py Normal file
View File

@@ -0,0 +1,57 @@
# coding=utf-8
# from django.conf.urls import url
# from AuthApp.js_views import *
# from AuthApp.import_funcs import *
from AuthApp.views import *
from django.contrib.auth import views
urlpatterns = [
# ajax ----------------
# url(r'^login$', user_login_View_ajax, name='user_login_View_ajax'),
# url(r'^login_confirm$', user_login_confirm_ajax, name='user_login_confirm_ajax'),
#
# url(r'^logout$', user_logout_ajax, name='user_logout_View_ajax'),
# url(r'^logout_confirm$', user_logout_confirm_ajax, name='user_logout_confirm_ajax'),
#
# url(r'^check_exists_email$', check_exists_email_ajax, name='check_exists_email_ajax'),
#
# url(r'^registration$', user_registration_View_ajax, name='user_registration_View_ajax'),
# url(r'^user_registration_send_confirmation_mail$',
# user_registration_send_confirmation_mail_ajax, name='user_registration_send_confirmation_mail_ajax'),
#
# url(r'^password_recovery$', password_recovery_View_ajax, name='password_recovery_View_ajax'),
# url(r'^password_reset$', password_reset_send_mail_ajax, name='password_reset_send_mail_ajax'),
#
# url(r'^registration_by_order_data_and_send_confirmation_mail$',
# registration_by_order_data_and_send_confirmation_mail_ajax, name='registration_by_order_data_and_send_confirmation_mail_ajax'),
#
#
# # -----------------------
#
# url(r'^check_user_registration_and_activate/(?P<user_id>[\d+]*)/(?P<authCode>[0-9a-z\+\-\_]+)$',
# check_user_registration_and_activate,
# name='check_user_registration_and_activate'),
#
# # url(r'^user/password/reset/$',
# # 'django.contrib.auth.views.password_reset',
# # {'post_reset_redirect' : '/user/password/reset/done/',
# # 'password_reset_form': ResetForm
# # },
# # name="password_reset"),
# # url(r'^user/password/reset/done/$', views.password_reset_done, name='password_reset_done'),
# url(r'^reset/(?P<uidb64>[0-9A-Za-z_\-]+)/(?P<token>[0-9A-Za-z]{1,13}-[0-9A-Za-z]{1,20})/$',
# views.password_reset_confirm, name='password_reset_confirm'),
# url(r'^reset/done/$', views.password_reset_complete, name='password_reset_complete'),
#
#
# # import
# url(r'^import_one_user/(?P<user_id>[\d+]*)$',
# import_json_mipp_user_by_id, name='import_one_mipp'),
# url(r'^import_web_users$',
# import_json_mipp_webUsers, name='import_mipp_webUsers'),
#
# url(r'^import_invoices_for_user_by_user_id/(?P<user_id>[\d+]*)$',
# import_invoices_for_user_by_user_id, name='import_invoices_for_user_by_user_id'),
]

149
AuthApp/views.py Normal file
View File

@@ -0,0 +1,149 @@
# coding=utf-8
from django.shortcuts import render
from uuid import uuid1
from AuthApp.models import *
from django.contrib import auth
from django.http import HttpResponse, Http404
from django.template import loader, RequestContext
from django.contrib.auth.decorators import login_required
from BaseModels.mailSender import techSendMail
from django.utils.translation import gettext as _
from datetime import datetime
def create_personal_user(data, creator):
try:
user_id = str(uuid1().hex)[:10]
user_name = data['email']
mail = user_name
user = User.objects.create_user(username=user_name, email=mail, password=user_id)
if 'first_name' in data and data['first_name']:
user.first_name = data['first_name']
if 'last_name' in data and data['last_name']:
user.last_name = data['last_name']
user.is_staff = False
user.is_active = False
user.is_superuser = False
# user.set_password(user_id)
user.save()
user_communications_ads_list = []
if 'office__name' in data['user_profile']:
del data['user_profile']['office__name']
if 'communications' in data['user_profile']:
user_communications_ads_list.extend(data['user_profile']['communications'])
del data['user_profile']['communications']
if not 'creator' in data['user_profile'] and creator:
data['user_profile']['creator'] = creator
profiles = UserProfile.objects.filter(user=user).update(**data['user_profile'])
user.refresh_from_db()
return {
'name' : mail,
'pass' : user_id,
'user' : user
}
except Exception as e:
return {
'error': 'Ошибка добавление нового пользователя = {0}'.format(str(e)),
}
def decode_get_param(data):
import base64
import json
d = data['data'].encode()
token_data = base64.b64decode(d)
try:
request_data = token_data.decode('utf8')
except:
request_data = token_data
data = json.loads(request_data)
return data
def recovery_password_user(request, uidb64=None, token=None):
from django.contrib.auth.views import PasswordResetConfirmView
return PasswordResetConfirmView(request=request, uidb64=uidb64, token=token
)
def create_temporary_user():
from django.utils.translation import gettext as _
user_id = str(uuid1().hex)[:10]
user_name = u'user'+user_id
mail = user_id+u'@truenergy.by'
user = User.objects.create_user(mail, mail,user_id)
user.first_name = _(u'незарег. пользователь')
user.last_name = u''
user.is_staff = False
user.is_active = True
user.is_superuser = False
user.set_password(user_id)
# print(u'user_create_pass', user.password)
# p = user.get_profile()
# p.address = ''
# p.phone = ''
# p.group = None
# p.discount = 0
# p.pay_balance = 0
# p.authMailCode = uuid1().hex
# p.save()
user.save()
user.mipp_user.temporary_user = True
user.mipp_user.save()
# print('user',user)
# print('created profile',p)
# print('user created', user)
return {
'name' : mail,
'pass' : user_id,
'user' : user
}
def get_active_user(request):
if request.user.is_anonymous:
return None
else:
user = request.user
# try:
# bd = user.mipp_user.birthdate
# except MIPPUser.DoesNotExist:
# MIPPUser.objects.create(user=user)
return user
def get_active_user_if_anonymous_create_temporary(request):
user = get_active_user(request)
if not user:
new_user_Dict = create_temporary_user()
user = auth.authenticate(username=new_user_Dict['name'], password=new_user_Dict['pass'])
if user:
auth.login(request, user)
return user

View File

@@ -95,8 +95,8 @@ class AdminImageWidget(AdminFileWidget):
return mark_safe(u''.join(output))
def init_formfield_for_dbfield(class_model, self, db_field, **kwargs):
formfield = super(class_model, self).formfield_for_dbfield(db_field, **kwargs)
def init_formfield_for_dbfield(class_model, self, db_field, request, **kwargs):
formfield = super(class_model, self).formfield_for_dbfield(db_field, request, **kwargs)
if db_field.name == 'url' or db_field.name == 'name' or db_field.name == 'title' or db_field.name == 'name_plural':
formfield.widget = admin.widgets.AdminTextInputWidget(attrs={'style': 'width: 80%'})
if db_field.name == 'workListForServicePage':
@@ -258,8 +258,8 @@ class Admin_BaseIconModel(admin.ModelAdmin):
description_exists.short_description = u'Описание'
description_exists.allow_tags = True
def formfield_for_dbfield (self, db_field, **kwargs):
return init_formfield_for_dbfield(Admin_BaseIconModel, self, db_field, **kwargs)
def formfield_for_dbfield (self, db_field, request, **kwargs):
return init_formfield_for_dbfield(Admin_BaseIconModel, self, db_field, request, **kwargs)
formfield_overrides = {
models.ImageField: {'widget': AdminImageWidget},
@@ -273,15 +273,27 @@ class Admin_BaseIconModel(admin.ModelAdmin):
# from modeltranslation.admin import TranslationAdmin
# # class CustomTranslationAdmin(TranslationAdmin):
# # # def formfield_for_dbfield(self, db_field, **kwargs):
# # # field = super().formfield_for_dbfield(db_field, **kwargs)
# # # self.patch_translation_field(db_field, field, **kwargs)
# # # return field
#
#
# class AdminTranslation_BaseIconModel(Admin_BaseIconModel, TranslationAdmin):
#
# # def formfield_for_dbfield(self, db_field, **kwargs):
# # field = super(AdminTranslation_BaseIconModel, self).formfield_for_dbfield(db_field, **kwargs)
# # self.patch_translation_field(db_field, field, **kwargs)
# # return field
#
# class Media:
#
# js = (
# 'https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
# 'https://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js',
# 'modeltranslation/js/force_jquery.js',
# 'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
# 'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js',
# 'modeltranslation/js/tabbed_translation_fields.js',
# # 'cked/ckeditor/ckeditor.js'
# )
# css = {
# 'screen': ('modeltranslation/css/tabbed_translation_fields.css',),

View File

@@ -29,7 +29,10 @@ class BaseModel(models.Model):
json_data = models.JSONField(verbose_name=_('Дополнительные данные'), default=dict, blank=True)
def __str__(self):
if self.name:
return self.name
else:
return str(self.id)
def get_node_by_name(self, node_name):
if not self.json_data or not node_name in self.json_data:

View File

@@ -2,24 +2,23 @@ from sets.admin import *
from .models import *
from django.contrib import admin
class Admin_StaticPage(Admin_BaseModelViewPage):
class Admin_StaticPage(Admin_Trans_BaseModelViewPage):
def get_fieldsets(self, request, obj=None):
fieldsets = super(type(self), self).get_fieldsets(request, obj)
if not request.user.is_superuser and obj.url and obj.url in ('main', 'spec_technics', 'works'):
fieldsets[0][1]['fields'].pop(2)
fieldsets.insert(
1, ('Промо-хэдер', {
'classes': ['wide'],
'fields': (
'promo_header',
'title', 'description', 'text',
'picture',
)
})
)
# fieldsets.insert(
# 1, ('Промо-хэдер', {
# 'classes': ['wide'],
# 'fields': (
# 'promo_header',
# 'title', 'description', 'text',
# 'picture',
# )
#
# })
# )
return fieldsets
def has_delete_permission(self, request, obj=None):

View File

@@ -0,0 +1,144 @@
# Generated by Django 4.2.2 on 2023-06-20 15:48
import ckeditor.fields
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('GeneralApp', '0001_initial'),
]
operations = [
migrations.AddField(
model_name='block',
name='FAQ_title_en',
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок'),
),
migrations.AddField(
model_name='block',
name='FAQ_title_ru',
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок'),
),
migrations.AddField(
model_name='block',
name='description_en',
field=ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='block',
name='description_ru',
field=ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='block',
name='name_en',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='block',
name='name_ru',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='block',
name='text_en',
field=ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='block',
name='text_ru',
field=ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='block',
name='title_en',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
migrations.AddField(
model_name='block',
name='title_ru',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
migrations.AddField(
model_name='faqitem',
name='answer_en',
field=ckeditor.fields.RichTextField(null=True, verbose_name='Ответ'),
),
migrations.AddField(
model_name='faqitem',
name='answer_ru',
field=ckeditor.fields.RichTextField(null=True, verbose_name='Ответ'),
),
migrations.AddField(
model_name='faqitem',
name='name_en',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='faqitem',
name='name_ru',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='faqitem',
name='question_en',
field=models.TextField(null=True, verbose_name='Вопрос'),
),
migrations.AddField(
model_name='faqitem',
name='question_ru',
field=models.TextField(null=True, verbose_name='Вопрос'),
),
migrations.AddField(
model_name='staticpage',
name='FAQ_title_en',
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок'),
),
migrations.AddField(
model_name='staticpage',
name='FAQ_title_ru',
field=models.CharField(blank=True, max_length=250, null=True, verbose_name='FAQ Заголовок'),
),
migrations.AddField(
model_name='staticpage',
name='description_en',
field=ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='staticpage',
name='description_ru',
field=ckeditor.fields.RichTextField(blank=True, help_text='краткое описание страницы (до 240 символов)', null=True, verbose_name='Краткое описание'),
),
migrations.AddField(
model_name='staticpage',
name='name_en',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='staticpage',
name='name_ru',
field=models.TextField(blank=True, help_text='Название', null=True, verbose_name='Название'),
),
migrations.AddField(
model_name='staticpage',
name='text_en',
field=ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='staticpage',
name='text_ru',
field=ckeditor.fields.RichTextField(blank=True, null=True, verbose_name='Полное описание'),
),
migrations.AddField(
model_name='staticpage',
name='title_en',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
migrations.AddField(
model_name='staticpage',
name='title_ru',
field=models.TextField(blank=True, null=True, verbose_name='Заголовок'),
),
]

View File

@@ -39,7 +39,10 @@ class FAQitem(BaseModel):
answer = RichTextField(verbose_name='Ответ')
def __str__(self):
if self.question:
return self.question
else:
return self.id
class Meta:
verbose_name = 'FAQ'

23
GeneralApp/translation.py Normal file
View File

@@ -0,0 +1,23 @@
from modeltranslation.translator import translator, TranslationOptions
from .models import *
class StaticPage_TranslationOptions(TranslationOptions):
fields = (
'name', 'description', 'text', 'title', 'FAQ_title'
)
translator.register(StaticPage, StaticPage_TranslationOptions)
class Block_TranslationOptions(TranslationOptions):
fields = (
'name', 'description', 'text', 'title', 'FAQ_title'
)
translator.register(Block, Block_TranslationOptions)
class FAQitem_TranslationOptions(TranslationOptions):
fields = (
'name', 'question', 'answer'
)
translator.register(FAQitem, FAQitem_TranslationOptions)

View File

@@ -31,6 +31,8 @@ ALLOWED_HOSTS = []
# Application definition
INSTALLED_APPS = [
'modeltranslation',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
@@ -42,7 +44,10 @@ INSTALLED_APPS = [
'ckeditor',
'ckeditor_uploader',
'GeneralApp',
'AuthApp',
]
MIDDLEWARE = [
@@ -137,6 +142,31 @@ STATICFILES_DIRS = [
BASE_DIR / "static",
]
import os
LOCALE_PATHS = (
os.path.join(BASE_DIR,'locale'),
)
gettext = lambda s: s
LANGUAGES = (
(u'ru', gettext(u'Russian')),
(u'en', gettext(u'English')),
)
MODELTRANSLATION_LANGUAGES = ('ru', 'en')
MODELTRANSLATION_ENABLE_FALLBACKS = True
MODELTRANSLATION_FALLBACK_LANGUAGES = {
'default': ('ru','en'),
}
# Add custom languages not provided by Django
import django.conf.locale
LANG_INFO = dict(django.conf.locale.LANG_INFO.items()) #+ EXTRA_LANG_INFO.items())
django.conf.locale.LANG_INFO = LANG_INFO
# Default primary key field type
# https://docs.djangoproject.com/en/4.2/ref/settings/#default-auto-field

View File

@@ -8,6 +8,15 @@ urlpatterns = [
path('admin/', admin.site.urls),
path('ckeditor/', include('ckeditor_uploader.urls')),
path('', include('GeneralApp.urls')),
# path('', include('GeneralApp.urls')),
]
from django.conf.urls.i18n import i18n_patterns
urlpatterns += i18n_patterns(
path('admin/', admin.site.urls),
path('', include('GeneralApp.urls')),
)
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)

View File

@@ -3,3 +3,4 @@ django-ckeditor==6.5.1
psycopg2-binary==2.9.6
requests
Pillow
django-modeltranslation=0.18.10

View File

@@ -1,4 +1,4 @@
from BaseModels.admin_utils import Admin_BaseIconModel, Admin_GenericBaseIconStackedInline
from BaseModels.admin_utils import Admin_GenericBaseIconStackedInline, Admin_BaseIconModel
from copy import deepcopy
class AdminStacked_FAQitem(Admin_GenericBaseIconStackedInline):
@@ -36,12 +36,14 @@ class Admin_BaseModel(Admin_BaseIconModel):
list_display_links = ('id', 'name')
class Admin_BaseBlock(Admin_BaseModel):
class Admin_BaseBlock(Admin_BaseIconModel):
pass
def get_fieldsets(self, request, obj=None):
fieldsets = super(Admin_BaseBlock, self).get_fieldsets(request, obj)
return fieldsets
class Admin_BaseModelViewPage(Admin_BaseBlock):
class Admin_BaseModelViewPage(Admin_BaseIconModel):
pass
def get_fieldsets(self, request, obj=None):
fieldsets = super(Admin_BaseModelViewPage, self).get_fieldsets(request, obj)
# fieldsets = deepcopy(self.fieldsets)
@@ -66,3 +68,36 @@ class Admin_BaseModelViewPage(Admin_BaseBlock):
inlines = [AdminStacked_FAQitem]
from modeltranslation.admin import TranslationAdmin
class AdminTranslationBase(TranslationAdmin):
# def formfield_for_dbfield(self, db_field, **kwargs):
# field = super(AdminTranslation_BaseIconModel, self).formfield_for_dbfield(db_field, **kwargs)
# self.patch_translation_field(db_field, field, **kwargs)
# return field
class Media:
js = (
'modeltranslation/js/force_jquery.js',
'http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js',
'http://ajax.googleapis.com/ajax/libs/jqueryui/1.10.2/jquery-ui.min.js',
'modeltranslation/js/tabbed_translation_fields.js',
)
css = {
'screen': ('modeltranslation/css/tabbed_translation_fields.css',),
}
class Admin_Trans_BaseModel(Admin_BaseModel, AdminTranslationBase):
pass
#
# class Admin_Trans_BaseModelViewPage(AdminTranslation_BaseIconModel):
# pass
class Admin_Trans_BaseModelViewPage(Admin_BaseModelViewPage, AdminTranslationBase):
pass