union_auto_test/core/models.py

1441 lines
56 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import re
import requests
from django.conf import settings
from django.db import models
from django.urls import reverse
from django.template.defaultfilters import slugify
from django.utils.html import format_html
from django_ckeditor_5.fields import CKEditor5Field
from django.utils import timezone
from django.utils.dateformat import DateFormat
from filer.fields.folder import FilerFolderField
from filer.fields.image import FilerImageField, FilerFileField
from easy_thumbnails.files import get_thumbnailer
from unidecode import unidecode
from googletrans import Translator
ReviewSource = (
('1', 'Яндекс'),
('2', '2ГИС'),
('3', 'VL.ru'),
)
TransportCategory = (
('1', 'Япония'),
('2', 'Корея'),
)
Currency = (
('¥', 'Йены'),
('', 'Воны'),
)
Import_type = (
('ЭПТС', 'ЭПТС'),
('ГТД', 'ГТД'),
)
class StaticPage(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255)
content = CKEditor5Field(verbose_name='Контент', blank=True, null=True)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
class Meta:
verbose_name = 'текстовый раздел'
verbose_name_plural = 'текстовые разделы'
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('core:static_page', kwargs={'slug': self.slug})
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if StaticPage.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class StaticBlock(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255)
content = models.TextField(verbose_name='Контент', null=True, blank=True)
class Meta:
verbose_name = 'статический блок'
verbose_name_plural = 'статические блоки'
def __str__(self):
return self.title
class Category(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=255)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'категория новости'
verbose_name_plural = 'категории новостей'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Category.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class Article(models.Model):
category = models.ForeignKey(Category, verbose_name='Категория', related_name='articles', blank=True, null=True,
on_delete=models.SET_NULL)
cover = FilerImageField(verbose_name='Обложка', null=True, on_delete=models.SET_NULL)
title = models.CharField(verbose_name='Заголовок', max_length=255)
content = CKEditor5Field(verbose_name='Контент')
date = models.DateTimeField(verbose_name='Дата')
is_active = models.BooleanField(verbose_name='Отображать на сайте?', default=True)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
class Meta:
verbose_name = 'статья/новость'
verbose_name_plural = 'Статьи/новости'
ordering = ['-date']
def __str__(self):
return self.title
def get_thumbnail(self):
image = '-'
if self.cover:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.cover)['article_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Обложка'
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Article.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
@property
def get_date(self):
return DateFormat(timezone.make_naive(self.date)).format('j E Y')
def get_absolute_url(self):
return reverse('core:article_details', kwargs={'slug': self.slug})
class Question(models.Model):
title = models.CharField(verbose_name='Вопрос', max_length=255)
content = CKEditor5Field(verbose_name='Ответ')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
is_active = models.BooleanField(verbose_name='Отображать на сайте?', default=True)
class Meta:
verbose_name = 'FAQ'
verbose_name_plural = 'FAQ'
ordering = ('order',)
def __str__(self):
return self.title
class Video(models.Model):
title = models.CharField(verbose_name='Название', max_length=255)
link = models.CharField(verbose_name='Ссылка', max_length=512)
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
is_active = models.BooleanField(verbose_name='Отображать на сайте?', default=True)
on_main = models.BooleanField(verbose_name='На главной странице?', default=True)
cover = models.CharField(verbose_name='Обложка', max_length=512, blank=True, null=True,
help_text='Оставить пустым для автоматической генерации')
player_link = models.CharField(verbose_name='Ссылка плеера', max_length=512, blank=True, null=True,
help_text='Оставить пустым для автоматической генерации')
class Meta:
verbose_name = 'видео'
verbose_name_plural = 'видео'
ordering = ('order',)
def __str__(self):
return self.title
def _extract_video_params(self):
pattern = r"video(-?\d+)_(\d+)"
match = re.search(pattern, self.link)
if match:
owner_id = match.group(1)
video_id = match.group(2)
return owner_id, video_id
else:
return None, None
def _get_cover(self):
owner_id, video_id = self._extract_video_params()
cover = None
player_link = None
if owner_id and video_id:
url = settings.VK_VIDEO_ENDPOINT
data = {
'videos': f'{owner_id}_{video_id}',
'v': '5.199',
'access_token': settings.VK_TOKEN,
}
response = requests.get(url, params=data)
try:
cover = response.json().get('response').get('items')[0].get('image')[-1].get('url')
player_link = response.json().get('response').get('items')[0].get('player')
except:
pass
return cover, player_link
def save(self, *args, **kwargs) -> None:
if self.cover is None:
cover, player = self._get_cover()
if cover:
self.cover = cover
if player:
self.player_link = player
return super().save(*args, **kwargs)
class Review(models.Model):
name = models.CharField(verbose_name='Фамилия Имя', max_length=255)
date = models.DateField(verbose_name='Дата')
text = models.TextField(verbose_name='Отзыв')
screen = FilerImageField(verbose_name='Скрин', null=True, blank=True, on_delete=models.SET_NULL)
is_active = models.BooleanField(verbose_name='Активный', default=True)
on_main = models.BooleanField(verbose_name='На главной странице?', default=True)
source = models.CharField(verbose_name='Источник', blank=True, null=True, choices=ReviewSource, max_length=50)
class Meta:
verbose_name = 'отзыв'
verbose_name_plural = 'отзывы'
ordering = ('-date',)
def __str__(self):
return self.name
def get_thumbnail(self):
image = '-'
if self.screen:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.screen)['review_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Скрин'
@property
def get_date(self):
return DateFormat(self.date).format('j E Y')
class TransportBrand(models.Model):
title = models.CharField(verbose_name='Название', max_length=255)
db_id = models.CharField(max_length=255)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'марка'
verbose_name_plural = 'марки'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Category.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class TransportModel(models.Model):
brand = models.ForeignKey(TransportBrand, verbose_name='Марка', related_name='transport_models',
on_delete=models.CASCADE)
title = models.CharField(verbose_name='Название', max_length=255)
db_id = models.CharField(max_length=255)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
category = models.CharField(verbose_name='Категория', choices=TransportCategory, max_length=50, null=True)
class Meta:
verbose_name = 'модель'
verbose_name_plural = 'модели'
ordering = ('order',)
def __str__(self):
country = 'не определено'
if self.category == '1':
country = 'Япония'
elif self.category == '2':
country = 'Корея'
return f'{self.title} ({country})'
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Category.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class MachineryBrand(models.Model):
title = models.CharField(verbose_name='Название', max_length=255)
db_id = models.CharField(max_length=255)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'марка (спец техника)'
verbose_name_plural = 'марки (спец техника)'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Category.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class MachineryModel(models.Model):
brand = models.ForeignKey(MachineryBrand, verbose_name='Марка', related_name='machinery_models',
on_delete=models.CASCADE)
title = models.CharField(verbose_name='Название', max_length=255)
slug = models.CharField(verbose_name='Уникальный URL', max_length=512, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'модель (спец техника)'
verbose_name_plural = 'модели (спец техника)'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if Category.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class TransportExperience(models.Model):
category = models.CharField(verbose_name='Категория', choices=TransportCategory, max_length=50)
cover = FilerImageField(verbose_name='Обложка', null=True, blank=True, on_delete=models.SET_NULL)
slider = FilerFolderField(on_delete=models.CASCADE, verbose_name='Галерея', null=True, blank=True)
currency = models.CharField(verbose_name='Валюта', choices=Currency, max_length=50)
import_type = models.CharField(verbose_name='Ввоз', choices=Import_type, max_length=50, default='ЭПТС')
title = models.CharField(verbose_name='Заголовок', max_length=255, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
brand = models.ForeignKey(TransportBrand, verbose_name='Марка', related_name='transport_experience',
on_delete=models.CASCADE)
transport_model = models.ForeignKey(TransportModel, verbose_name='Модель', related_name='transport_experience',
on_delete=models.SET_NULL, null=True)
lot = models.CharField(verbose_name="Лот", max_length=100, null=True, blank=True)
auction = models.CharField(verbose_name="Аукцион", max_length=100, null=True, blank=True)
year = models.PositiveIntegerField(verbose_name='Год', null=True)
mileage = models.PositiveBigIntegerField(verbose_name='Пробег (км)', null=True, blank=True)
car_body = models.CharField(verbose_name='Кузов', max_length=255, null=True, blank=True)
rate = models.FloatField(verbose_name='Оценка', null=True, blank=True)
volume = models.PositiveIntegerField(verbose_name='Объем двигателя (см3)', null=True, blank=True)
power = models.PositiveIntegerField(verbose_name='Мощность (л.с.)', null=True, blank=True)
drive = models.CharField(verbose_name='Привод', max_length=255, null=True, blank=True)
transmission = models.CharField(verbose_name='Трансмиссия', max_length=255, null=True, blank=True)
equipment = models.CharField(verbose_name='Комплектация', max_length=255, null=True, blank=True)
comment = models.TextField(verbose_name='Комментарий', null=True, blank=True)
auction_price = models.PositiveBigIntegerField(verbose_name='Цена на аукционе (валюта)')
auction_price_rub = models.PositiveBigIntegerField(verbose_name='Цена на аукционе (руб.)')
delivery_price_rub = models.PositiveBigIntegerField(verbose_name='Доставка (руб.)')
tax_price_rub = models.PositiveBigIntegerField(verbose_name='Пошлина (руб.)')
is_active = models.BooleanField(verbose_name='Активный', default=True)
on_main = models.BooleanField(verbose_name='На главной странице?', default=True)
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'привезенное авто'
verbose_name_plural = 'привезенные авто'
ordering = ('order',)
def __str__(self):
if self.title:
return self.title
else:
return self.brand.title
def save(self, *args, **kwargs) -> None:
if self.title is None:
title = f'{self.brand.title} {self.transport_model.title}'
if self.volume:
eng_v = round(self.volume / 1000, 1)
title += f', {eng_v} л.'
if self.year:
title += f', {self.year}'
self.title = title
return super().save(*args, **kwargs)
def get_thumbnail(self):
image = '-'
if self.cover:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.cover)['experience_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Обложка'
@property
def full_title(self):
model_name = self.transport_model.title
brand_name = self.brand.title
full_title = ''
if brand_name:
full_title += brand_name.capitalize()
if model_name:
full_title += f' {model_name.capitalize()}'
if self.volume:
eng_v = round(self.volume / 1000, 1)
full_title += f', {eng_v} л.'
if self.year:
full_title += f', {self.year}'
return full_title
@property
def short_description(self):
description = ''
if self.volume:
description += f'{self.volume} cc'
if self.power:
description += f' / {self.power} л.с.'
if self.transmission:
description += f' / {self.transmission}'
if self.mileage:
description += f' / Пробег {self.mileage} км.'
description = description.strip(' / ')
return description
@property
def total_cost_rub(self):
return self.auction_price_rub + self.tax_price_rub + self.delivery_price_rub
@property
def currency_price_readable(self):
if self.auction_price_rub:
formatted_price = f"{self.auction_price_rub:,}".replace(',', ' ')
return f'{formatted_price} {self.currency}'
return 'не указана'
@property
def rub_price_readable(self):
if self.auction_price_rub:
formatted_price = f"{self.auction_price_rub:,}".replace(',', ' ')
return f'{formatted_price}'
return 'не указана'
@property
def get_absolute_url(self):
if self.category == '1':
return reverse('core:experience_japan_details', kwargs={'pk': self.id})
elif self.category == '2':
return reverse('core:experience_korea_details', kwargs={'pk': self.id})
class MachineryExperience(models.Model):
cover = FilerImageField(verbose_name='Обложка', null=True, blank=True, on_delete=models.SET_NULL)
slider = FilerFolderField(on_delete=models.CASCADE, verbose_name='Галерея', null=True, blank=True)
currency = models.CharField(verbose_name='Валюта', choices=Currency, max_length=50)
import_type = models.CharField(verbose_name='Ввоз', choices=Import_type, max_length=50, default='ЭПТС')
title = models.CharField(verbose_name='Заголовок', max_length=255, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
brand = models.ForeignKey(MachineryBrand, verbose_name='Марка', related_name='transport_experience',
on_delete=models.CASCADE)
transport_model = models.ForeignKey(MachineryModel, verbose_name='Модель', related_name='transport_experience',
on_delete=models.CASCADE)
lot = models.CharField(verbose_name="Лот", max_length=100, null=True, blank=True)
auction = models.CharField(verbose_name="Аукцион", max_length=100, null=True, blank=True)
year = models.PositiveIntegerField(verbose_name='Год', null=True)
mileage = models.PositiveBigIntegerField(verbose_name='Пробег (км)', null=True, blank=True)
car_body = models.CharField(verbose_name='Кузов', max_length=255, null=True, blank=True)
rate = models.FloatField(verbose_name='Оценка', null=True, blank=True)
volume = models.PositiveIntegerField(verbose_name='Объем двигателя (см3)', null=True, blank=True)
power = models.PositiveIntegerField(verbose_name='Мощность (л.с.)', null=True, blank=True)
drive = models.CharField(verbose_name='Привод', max_length=255, null=True, blank=True)
transmission = models.CharField(verbose_name='Трансмиссия', max_length=255, null=True, blank=True)
equipment = models.CharField(verbose_name='Комплектация', max_length=255, null=True, blank=True)
comment = models.TextField(verbose_name='Комментарий', null=True, blank=True)
auction_price = models.PositiveBigIntegerField(verbose_name='Цена на аукционе (валюта)')
auction_price_rub = models.PositiveBigIntegerField(verbose_name='Цена на аукционе (руб.)')
delivery_price_rub = models.PositiveBigIntegerField(verbose_name='Доставка (руб.)')
tax_price_rub = models.PositiveBigIntegerField(verbose_name='Пошлина (руб.)')
is_active = models.BooleanField(verbose_name='Активный', default=True)
on_main = models.BooleanField(verbose_name='На главной странице?', default=True)
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'привезенная (спец техника)'
verbose_name_plural = 'привезенные (спец техника)'
ordering = ('order',)
def __str__(self):
if self.title:
return self.title
else:
return self.brand.title
def save(self, *args, **kwargs) -> None:
if self.title is None:
title = f'{self.brand.title} {self.transport_model.title}'
if self.volume:
title += f', {self.volume} cc'
if self.year:
title += f', {self.year}'
self.title = title
return super().save(*args, **kwargs)
def get_thumbnail(self):
image = '-'
if self.cover:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.cover)['experience_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Обложка'
@property
def full_title(self):
model_name = self.transport_model.title
brand_name = self.brand.title
full_title = ''
if brand_name:
full_title += brand_name.capitalize()
if model_name:
full_title += f' {model_name.capitalize()}'
if self.volume:
full_title += f', {self.volume} cc'
if self.year:
full_title += f', {self.year}'
return full_title
@property
def short_description(self):
description = ''
if self.volume:
description += f'{self.volume} cc'
if self.power:
description += f' / {self.power} л.с.'
if self.transmission:
description += f' / {self.transmission}'
if self.mileage:
description += f' / Пробег {self.mileage} км.'
description = description.strip(' / ')
return description
@property
def total_cost_rub(self):
return self.auction_price_rub + self.tax_price_rub + self.delivery_price_rub
@property
def currency_price_readable(self):
if self.auction_price_rub:
formatted_price = f"{self.auction_price_rub:,}".replace(',', ' ')
return f'{formatted_price} {self.currency}'
return 'не указана'
@property
def rub_price_readable(self):
if self.auction_price_rub:
formatted_price = f"{self.auction_price_rub:,}".replace(',', ' ')
return f'{formatted_price}'
return 'не указана'
@property
def get_absolute_url(self):
return reverse('core:experience_machinery_details', kwargs={'pk': self.id})
class Rate(models.Model):
slug = models.CharField(verbose_name='Валютная пара', max_length=15)
rate = models.DecimalField(max_digits=10, decimal_places=3, default=0)
class Meta:
verbose_name = 'курс валют'
verbose_name_plural = 'курсы валют'
def __str__(self):
return str(self.rate)
class ColorFilter(models.Model):
title = models.CharField(verbose_name='Цвет', max_length=100, unique=True)
contain = models.CharField(verbose_name='Название цвета включает', max_length=100, unique=True)
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'фильтр цветы'
verbose_name_plural = 'фильтры цветов'
ordering = ('order',)
def __str__(self):
return self.title
class MainLot(models.Model):
category = models.CharField(max_length=5, default='1')
db_id = models.CharField(max_length=100, unique=True)
lot = models.CharField(max_length=100, null=True, blank=True)
auction_type = models.CharField(max_length=100, null=True, blank=True)
auction_date = models.CharField(max_length=100, null=True, blank=True)
auction = models.CharField(max_length=100, null=True, blank=True)
car_model = models.ForeignKey(TransportModel, related_name='main_lots', null=True, blank=True,
on_delete=models.CASCADE)
year = models.PositiveIntegerField(null=True, blank=True)
town = models.CharField(max_length=100, null=True, blank=True)
eng_v = models.PositiveIntegerField(null=True, blank=True)
pw = models.PositiveIntegerField(null=True, blank=True)
kuzov = models.CharField(max_length=100, null=True, blank=True)
grade = models.CharField(max_length=2016, null=True, blank=True)
color = models.CharField(max_length=100, null=True, blank=True)
kpp = models.CharField(max_length=100, null=True, blank=True)
kpp_type = models.CharField(max_length=100, null=True, blank=True)
priv = models.CharField(max_length=100, null=True, blank=True)
mileage = models.PositiveIntegerField(null=True, blank=True)
equip = models.CharField(max_length=4096, null=True, blank=True)
rate = models.CharField(max_length=100, null=True, blank=True)
start = models.PositiveIntegerField(null=True, blank=True)
finish = models.PositiveIntegerField(null=True, blank=True)
status = models.CharField(max_length=100, null=True, blank=True)
time = models.CharField(max_length=100, null=True, blank=True)
avg_price = models.PositiveIntegerField(null=True, blank=True)
avg_string = models.CharField(max_length=1000, null=True, blank=True)
auction_list = models.CharField(max_length=200, null=True, blank=True)
cover = models.CharField(max_length=200, null=True, blank=True)
images = models.TextField(null=True, blank=True)
serial = models.CharField(max_length=4096, null=True, blank=True)
info = models.TextField(max_length=8192, null=True, blank=True)
full_info = models.BooleanField(default=False)
class Meta:
verbose_name = 'лот (Япония)'
verbose_name_plural = 'лоты (Япония)'
@property
def currency_price(self):
if self.avg_price and self.avg_price > 0:
return self.avg_price
if self.start and self.start > 0:
return self.start
if self.finish and self.finish > 0:
return self.finish
return 'не указана'
@property
def currency_price_readable(self):
price = self.currency_price
if isinstance(price, int):
formatted_price = f"{price:,}".replace(',', ' ')
return f'{formatted_price} ¥'
return price
@property
def rub_price(self):
rate = Rate.objects.get(slug='rub-jpy')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
formatted_price = f"{price:,}".replace(',', ' ')
else:
return 'не указана'
return f'{formatted_price}'
@property
def rub_price_int(self):
rate = Rate.objects.get(slug='rub-jpy')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
return price
else:
return False
@property
def full_title(self):
if self.car_model:
model_name = self.car_model.title
brand_name = self.car_model.brand.title
else:
model_name = None
brand_name = None
full_title = ''
if brand_name:
full_title += brand_name.capitalize()
if model_name:
full_title += f' {model_name.capitalize()}'
if self.eng_v:
eng_v = round(self.eng_v / 1000, 1)
full_title += f', {eng_v} л.'
if self.year:
full_title += f', {self.year}'
return full_title
@property
def xml_description(self):
eng_v = ''
pw = ''
transmission = ''
if self.eng_v:
eng_v = round(self.eng_v / 1000, 1)
if self.pw:
pw = f' ({self.pw} л.с.)'
if self.kpp:
transmission = f' {self.kpp}'
return f'{eng_v}{transmission}{pw}'
@property
def get_absolute_url(self):
brand = ''
model = ''
try:
brand = self.car_model.brand.title.lower().replace(' ', '-')
except:
pass
try:
model = self.car_model.title.lower().replace(' ', '-')
model = f'-{model}'
except:
pass
if self.year:
year = f'-{self.year}'
else:
year = ''
url = f'{brand}{model}{year}-{self.db_id}'
url = url.strip('-')
return reverse('core:lot_japan', kwargs={'lot_id': url})
@property
def get_absolute_truck_url(self):
brand = ''
model = ''
try:
brand = self.car_model.brand.title.lower().replace(' ', '-')
except:
pass
try:
model = self.car_model.title.lower().replace(' ', '-')
model = f'-{model}'
except:
pass
if self.year:
year = f'-{self.year}'
else:
year = ''
url = f'{brand}{model}{year}-{self.db_id}'
url = url.strip('-')
return reverse('core:lot_truck', kwargs={'lot_id': url})
class KoreaLot(models.Model):
category = models.CharField(max_length=5, default='2')
db_id = models.CharField(max_length=100, unique=True)
lot = models.CharField(max_length=100, null=True, blank=True)
auction_date = models.CharField(max_length=100, null=True, blank=True)
auction = models.CharField(max_length=100, null=True, blank=True)
car_model = models.ForeignKey(TransportModel, related_name='korea_lots', null=True, blank=True,
on_delete=models.CASCADE)
year = models.PositiveIntegerField(null=True, blank=True)
eng_v = models.PositiveIntegerField(null=True, blank=True)
pw = models.PositiveIntegerField(null=True, blank=True)
kuzov = models.CharField(max_length=100, null=True, blank=True)
grade = models.CharField(max_length=2016, null=True, blank=True)
color = models.CharField(max_length=100, null=True, blank=True)
kpp = models.CharField(max_length=100, null=True, blank=True)
kpp_type = models.CharField(max_length=100, null=True, blank=True)
priv = models.CharField(max_length=100, null=True, blank=True)
mileage = models.PositiveIntegerField(null=True, blank=True)
equip = models.CharField(max_length=4096, null=True, blank=True)
rate = models.CharField(max_length=100, null=True, blank=True)
start = models.PositiveIntegerField(null=True, blank=True)
finish = models.PositiveIntegerField(null=True, blank=True)
status = models.CharField(max_length=100, null=True, blank=True)
time = models.CharField(max_length=100, null=True, blank=True)
avg_price = models.PositiveIntegerField(null=True, blank=True)
avg_string = models.CharField(max_length=1000, null=True, blank=True)
cover = models.CharField(max_length=200, null=True, blank=True)
images = models.TextField(null=True, blank=True)
serial = models.CharField(max_length=4096, null=True, blank=True)
info = models.TextField(max_length=8192, null=True, blank=True)
info_rus = models.TextField(max_length=8192, null=True, blank=True)
full_info = models.BooleanField(default=False)
class Meta:
verbose_name = 'лот (Корея)'
verbose_name_plural = 'лоты (Корея)'
@property
def currency_price(self):
if self.avg_price and self.avg_price > 0:
return self.avg_price
if self.start and self.start > 0:
return self.start
if self.finish and self.finish > 0:
return self.finish
return 'не указана'
@property
def rub_price_int(self):
rate = Rate.objects.get(slug='rub-krw')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
return price
else:
return False
@property
def currency_price_readable(self):
price = self.currency_price
if isinstance(price, int):
formatted_price = f"{price:,}".replace(',', ' ')
return f'{formatted_price}'
return price
@property
def rub_price(self):
rate = Rate.objects.get(slug='rub-krw')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
formatted_price = f"{price:,}".replace(',', ' ')
else:
return 'не указана'
return f'{formatted_price}'
@property
def full_title(self):
try:
model_name = self.car_model.title
brand_name = self.car_model.brand.title
except:
model_name = None
brand_name = None
full_title = ''
if brand_name:
full_title += brand_name.capitalize()
if model_name:
full_title += f' {model_name.capitalize()}'
if self.eng_v:
eng_v = round(self.eng_v / 1000, 1)
full_title += f', {eng_v} л.'
if self.year:
full_title += f', {self.year}'
return full_title
@property
def xml_description(self):
eng_v = ''
pw = ''
transmission = ''
if self.eng_v:
eng_v = round(self.eng_v / 1000, 1)
if self.pw:
pw = f' ({self.pw} л.с.)'
if self.kpp:
transmission = f' {self.kpp}'
return f'{eng_v}{transmission}{pw}'
@property
def get_absolute_url(self):
brand = ''
model = ''
try:
brand = self.car_model.brand.title.lower().replace(' ', '-')
except:
pass
try:
model = self.car_model.title.lower().replace(' ', '-')
model = f'-{model}'
except:
pass
if self.year:
year = f'-{self.year}'
else:
year = ''
url = f'{brand}{model}{year}-{self.db_id}'
url = url.strip('-')
return reverse('core:lot_korea', kwargs={'lot_id': url})
def translate_to_rus(self):
try:
translator = Translator()
text_rus = translator.translate(text=self.info, dest='ru', src='auto')
if text_rus.text:
return text_rus.text
return False
except:
return False
def save(self, *args, **kwargs) -> None:
if self.info and self.info_rus is None:
info_rus = self.translate_to_rus()
if info_rus:
self.info_rus = info_rus
return super().save(*args, **kwargs)
class MachineryLot(models.Model):
db_id = models.CharField(max_length=100, unique=True)
lot = models.CharField(max_length=100, null=True, blank=True)
auction_date = models.CharField(max_length=100, null=True, blank=True)
auction = models.CharField(max_length=100, null=True, blank=True)
group = models.CharField(max_length=100, null=True, blank=True)
category = models.CharField(max_length=100, null=True, blank=True)
gg = models.CharField(max_length=100, null=True, blank=True)
cc = models.CharField(max_length=100, null=True, blank=True)
machinery_model = models.ForeignKey(MachineryModel, related_name='machinery_lots', null=True, blank=True,
on_delete=models.CASCADE)
year = models.PositiveIntegerField(null=True, blank=True)
grade = models.CharField(max_length=2016, null=True, blank=True)
kpp = models.CharField(max_length=100, null=True, blank=True)
priv = models.CharField(max_length=100, null=True, blank=True)
mileage = models.PositiveIntegerField(null=True, blank=True)
rate = models.CharField(max_length=100, null=True, blank=True)
volume = models.CharField(max_length=100, null=True, blank=True)
price = models.PositiveIntegerField(null=True, blank=True)
finish = models.PositiveIntegerField(null=True, blank=True)
status = models.CharField(max_length=100, null=True, blank=True)
cover = models.CharField(max_length=200, null=True, blank=True)
auction_list = models.CharField(max_length=200, null=True, blank=True)
images = models.TextField(null=True, blank=True)
serial = models.CharField(max_length=4096, null=True, blank=True)
info = models.TextField(max_length=8192, null=True, blank=True)
info_rus = models.TextField(max_length=8192, null=True, blank=True)
machinery_filter = models.ForeignKey('MachineryFilter', related_name='machinery_lots', null=True, blank=True,
on_delete=models.CASCADE)
full_info = models.BooleanField(default=False)
class Meta:
verbose_name = 'лот (спец техника)'
verbose_name_plural = 'лоты (спец техника)'
@property
def currency_price(self):
if self.finish and self.finish > 0:
return self.finish
if self.price and self.price > 0:
return self.price
return 'не указана'
@property
def rub_price_int(self):
rate = Rate.objects.get(slug='rub-jpy')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
return price
else:
return False
@property
def currency_price_readable(self):
price = self.currency_price
if isinstance(price, int):
formatted_price = f"{price:,}".replace(',', ' ')
return f'{formatted_price} ¥'
return price
@property
def rub_price(self):
rate = Rate.objects.get(slug='rub-jpy')
if isinstance(self.currency_price, int):
price = int(self.currency_price / rate.rate)
formatted_price = f"{price:,}".replace(',', ' ')
else:
return 'не указана'
return f'{formatted_price}'
@property
def full_title(self):
try:
model_name = self.machinery_model.title
brand_name = self.machinery_model.brand.title
except:
model_name = None
brand_name = None
full_title = ''
if brand_name:
full_title += brand_name.capitalize()
if model_name:
full_title += f' {model_name.capitalize()}'
if self.cc:
full_title += f', {self.cc} cc'
if self.year:
full_title += f', {self.year}'
return full_title
@property
def get_absolute_url(self):
brand = ''
model = ''
try:
brand = self.machinery_model.brand.title.lower().replace(' ', '-')
except:
pass
try:
model = self.machinery_model.title.lower().replace(' ', '-')
model = f'-{model}'
except:
pass
if self.year:
year = f'-{self.year}'
else:
year = ''
url = f'{brand}{model}{year}-{self.db_id}'
url = url.strip('-')
return reverse('core:lot_machinery', kwargs={'lot_id': url})
def translate_to_rus(self):
try:
translator = Translator()
text_rus = translator.translate(text=self.info, dest='ru', src='auto')
if text_rus.text:
return text_rus.text
return False
except:
return False
def save(self, *args, **kwargs) -> None:
if self.info and self.info_rus is None:
info_rus = self.translate_to_rus()
if info_rus:
self.info_rus = info_rus
return super().save(*args, **kwargs)
class MachineryGroup(models.Model):
title = models.CharField(verbose_name='Группа спец. техники', max_length=100, unique=True)
class Meta:
verbose_name = 'группа спец. техники'
verbose_name_plural = 'группы спец. техники'
def __str__(self):
return self.title
class MachineryFilter(models.Model):
title = models.CharField(verbose_name='Название фильтра', max_length=100, unique=True)
groups = models.ManyToManyField(MachineryGroup, verbose_name='Группы спец. техники', related_name='filters')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
on_main = models.BooleanField(verbose_name='Отображать на главной?', default=True)
icon = FilerImageField(verbose_name='Иконка фильтра', null=True, on_delete=models.SET_NULL)
class Meta:
verbose_name = 'фильтр спец. техники'
verbose_name_plural = 'фильтры спец.техники'
ordering = ('order',)
def __str__(self):
return self.title
class Banner(models.Model):
title = models.CharField(verbose_name='Заголовок', max_length=100)
banner = FilerImageField(verbose_name='Баннер', null=True, on_delete=models.SET_NULL)
button_text = models.CharField(verbose_name='Текст кнопки', max_length=50)
is_active = models.BooleanField(verbose_name='Отображать на сайте?', default=True)
link = models.URLField()
class Meta:
verbose_name = 'баннер'
verbose_name_plural = 'баннеры'
def get_thumbnail(self):
image = '-'
if self.banner:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.banner)['banner_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Баннер'
class Document(models.Model):
title = models.TextField(verbose_name='Заголовок', null=True, blank=True)
file = FilerFileField(verbose_name='Файл', related_name="document_files", on_delete=models.SET_NULL, null=True,
blank=True)
slug = models.SlugField(verbose_name='Уникальный URL', max_length=255, unique=True, null=True, blank=True)
class Meta:
verbose_name = 'документ'
verbose_name_plural = 'документы'
def __str__(self):
return f'{self.title}'
@property
def get_file_size(self):
if self.file:
size_in_bytes = self.file.size
size_in_kb = int(size_in_bytes / 1024)
size_in_mb = int(size_in_bytes / (1024 * 1024))
if size_in_mb >= 1:
return f'{size_in_mb}МБ'
return f'{size_in_kb}КБ'
return False
class SeoAbove(models.Model):
h1 = models.CharField(verbose_name='H1 заголовок', max_length=512, blank=True, null=True)
meta_title = models.CharField(verbose_name='meta Title', max_length=512, blank=True, null=True)
meta_description = models.CharField(verbose_name='meta Description', max_length=512, blank=True, null=True)
meta_keywords = models.CharField(verbose_name='meta Keywords', max_length=512, blank=True, null=True)
og_image = FilerImageField(verbose_name='meta og image', null=True, blank=True, on_delete=models.SET_NULL)
slug = models.CharField(verbose_name='Слаг необходимой страницы', max_length=255, null=True, blank=True,
unique=True, help_text='Без домена.')
class Meta:
verbose_name = 'принудительное SEO'
verbose_name_plural = 'Принудительное SEO'
def __str__(self):
return f'{self.id} - {self.h1}'
class FormRequest(models.Model):
name = models.CharField(max_length=256, verbose_name="Имя")
phone = models.CharField(max_length=256, verbose_name="Номер")
comment = models.TextField(verbose_name="Комментарий", null=True, blank=True)
file = models.FileField(verbose_name="Конкурентное предложение", null=True, blank=True, upload_to="uploads/")
created_at = models.DateTimeField(verbose_name="Дата", auto_now_add=True)
class Meta:
verbose_name = 'заявка'
verbose_name_plural = 'заявки'
ordering = ('-created_at',)
def __str__(self):
return f'{self.name} - {self.phone}'
class StockAuto(models.Model):
cover = FilerImageField(verbose_name='Обложка', null=True, blank=True, on_delete=models.SET_NULL)
slider = FilerFolderField(on_delete=models.CASCADE, verbose_name='Галерея', null=True, blank=True)
city = models.ForeignKey('City', null=True, verbose_name='Город', blank=True, on_delete=models.SET_NULL,
related_name='autos_in_stock')
title = models.CharField(verbose_name='Заголовок', max_length=255, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
brand = models.ForeignKey(TransportBrand, verbose_name='Марка', related_name='autos_in_stock',
on_delete=models.CASCADE)
transport_model = models.ForeignKey(TransportModel, verbose_name='Модель', related_name='autos_in_stock',
on_delete=models.SET_NULL, null=True)
engine = models.ForeignKey('EngineType', null=True, verbose_name='Тип двигателя', blank=True,
on_delete=models.SET_NULL, related_name='autos_in_stock')
import_type = models.ForeignKey('ImportType', null=True, verbose_name='Ввоз', blank=True, on_delete=models.SET_NULL,
related_name='autos_in_stock')
year = models.PositiveIntegerField(verbose_name='Год', null=True)
mileage = models.PositiveBigIntegerField(verbose_name='Пробег (км)', null=True, blank=True,
help_text='Заполняется или поле "пробег" или поле "моточасы", при заполнении обоих будет отображен только пробег')
moto_hours = models.PositiveBigIntegerField(verbose_name='Маточасы', null=True, blank=True,
help_text='Заполняется или поле "пробег" или поле "моточасы", при заполнении обоих будет отображен только пробег')
car_body = models.CharField(verbose_name='Кузов', max_length=255, null=True, blank=True)
volume = models.PositiveIntegerField(verbose_name='Объем двигателя (см3)', null=True, blank=True)
power = models.PositiveIntegerField(verbose_name='Мощность (л.с.)', null=True, blank=True)
drive = models.CharField(verbose_name='Привод', max_length=255, null=True, blank=True)
transmission = models.CharField(verbose_name='Трансмиссия', max_length=255, null=True, blank=True)
equipment = models.CharField(verbose_name='Комплектация', max_length=255, null=True, blank=True)
comment = models.TextField(verbose_name='Комментарий', null=True, blank=True)
price = models.PositiveBigIntegerField(verbose_name='Цена (руб.)')
auction_price = models.IntegerField(default=0)
is_active = models.BooleanField(verbose_name='Активный', default=True)
on_main = models.BooleanField(verbose_name='На главной странице?', default=True)
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'авто в наличии'
verbose_name_plural = 'авто в наличии'
ordering = ('order',)
def __str__(self):
if self.title:
return self.title
else:
return self.brand.title
def save(self, *args, **kwargs) -> None:
if self.title is None:
title = f'{self.brand.title} {self.transport_model.title}'
if self.volume:
eng_v = round(self.volume / 1000, 1)
title += f', {eng_v} л.'
if self.year:
title += f', {self.year}'
self.title = title
return super().save(*args, **kwargs)
def get_thumbnail(self):
image = '-'
if self.cover:
image = format_html('<img src="{0}"/>', get_thumbnailer(self.cover)['experience_thumbnail'].url)
return image
get_thumbnail.allow_tags = True
get_thumbnail.short_description = 'Обложка'
@property
def short_description(self):
description = ''
if self.power:
description += f'{self.power} л.с.'
if self.transmission:
description += f' / {self.transmission}'
if self.mileage:
description += f' / Пробег {self.mileage} км.'
elif self.moto_hours:
description += f' / Моточасы: {self.mileage} мч.'
description = description.strip(' / ')
return description
@property
def readable_price(self):
return f"{self.price:,}".replace(',', ' ')
@property
def get_absolute_url(self):
brand = ''
model = ''
try:
brand = self.brand.title.lower().replace(' ', '-')
except:
pass
try:
model = self.transport_model.title.lower().replace(' ', '-')
model = f'-{model}'
except:
pass
if self.year:
year = f'-{self.year}'
else:
year = ''
url = f'{brand}{model}{year}-{self.id}'
url = url.strip('-')
return reverse('core:stock_auto_details', kwargs={'lot_id': url})
class City(models.Model):
title = models.CharField(verbose_name='Город/регион', max_length=128, unique=True)
slug = models.CharField(verbose_name='Уникальный URL', max_length=128, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'город/регион'
verbose_name_plural = 'города/регионы'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if StaticPage.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class Contact(models.Model):
phone = models.CharField(max_length=64)
bitrix_id = models.IntegerField()
def __str__(self):
return self.phone
class Lead(models.Model):
contact = models.ForeignKey(Contact, on_delete=models.CASCADE)
bitrix_id = models.IntegerField()
def __str__(self):
return str(self.bitrix_id)
class ImportType(models.Model):
title = models.CharField(verbose_name='Ввоз', max_length=128, unique=True)
slug = models.CharField(verbose_name='Уникальный URL', max_length=128, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'тип ввоза'
verbose_name_plural = 'типы ввоза'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if StaticPage.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class EngineType(models.Model):
title = models.CharField(verbose_name='Двигатель', max_length=128, unique=True)
slug = models.CharField(verbose_name='Уникальный URL', max_length=128, null=True, blank=True,
help_text='Оставить пустым для автоматической генерации')
order = models.PositiveIntegerField(verbose_name='Порядок', default=0, blank=False, null=False)
class Meta:
verbose_name = 'тип двигателя'
verbose_name_plural = 'типы двигателей'
ordering = ('order',)
def __str__(self):
return self.title
def save(self, *args, **kwargs) -> None:
if self.slug is None:
slug = f'{slugify(unidecode(self.title))}'
if StaticPage.objects.filter(slug=slug).exists():
slug = f'{slugify(unidecode(self.title))}-{self.id}'
self.slug = slug
return super().save(*args, **kwargs)
class BitrixEmployee(models.Model):
bitrix_id = models.IntegerField(verbose_name='ID пользователя в bitrix', unique=True)
active = models.BooleanField(verbose_name='Активен?', default=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
verbose_name = 'сотрудник Bitrix'
verbose_name_plural = 'сотрудники Bitrix'
ordering = ('updated_at',)
def __str__(self):
return str(self.bitrix_id)