refactored product app, see changes

This commit is contained in:
Anatoly 2019-11-05 18:04:34 +03:00
parent d46ba31654
commit 87dacfec7f
13 changed files with 188 additions and 234 deletions

View File

@ -1,52 +0,0 @@
# Generated by Django 2.2.4 on 2019-11-01 13:23
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import utils.models
class Migration(migrations.Migration):
dependencies = [
('location', '0020_merge_20191030_1714'),
]
operations = [
migrations.CreateModel(
name='WineSubRegion',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
],
options={
'verbose_name': 'wine region',
'verbose_name_plural': 'wine regions',
},
),
migrations.CreateModel(
name='WineVillage',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
('description', utils.models.TJSONField(help_text='{"en-GB":"some text"}', verbose_name='description')),
],
options={
'verbose_name': 'wine village',
'verbose_name_plural': 'wine villages',
},
),
migrations.RemoveField(
model_name='wineappellation',
name='wine_region',
),
migrations.AddField(
model_name='wineregion',
name='coordinates',
field=django.contrib.gis.db.models.fields.PointField(blank=True, default=None, null=True, srid=4326, verbose_name='Coordinates'),
),
migrations.AlterField(
model_name='wineregion',
name='name',
field=models.CharField(max_length=255, verbose_name='name'),
),
]

View File

@ -1,33 +0,0 @@
# Generated by Django 2.2.4 on 2019-11-01 13:23
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('product', '0003_auto_20191101_1323'),
('location', '0021_auto_20191101_1323'),
]
operations = [
migrations.DeleteModel(
name='WineAppellation',
),
migrations.AddField(
model_name='winevillage',
name='wine_region',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='location.WineRegion', verbose_name='wine region'),
),
migrations.AddField(
model_name='winevillage',
name='wine_sub_region',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='location.WineSubRegion', verbose_name='wine sub region'),
),
migrations.AddField(
model_name='winesubregion',
name='country',
field=models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='location.Country', verbose_name='country'),
),
]

View File

@ -1,12 +1,19 @@
"""Product admin conf."""
from django.contrib import admin
from utils.admin import BaseModelAdminMixin
from .models import Product, ProductType, ProductSubType, Unit, Characteristic
from .models import Product, ProductType, ProductSubType, Unit, \
Characteristic, ProductCharacteristic
class ProductCharacteristics(admin.TabularInline):
model = ProductCharacteristic
extra = 0
@admin.register(Product)
class ProductAdmin(BaseModelAdminMixin, admin.ModelAdmin):
"""Admin page for model Product."""
inlines = [ProductCharacteristics, ]
@admin.register(ProductType)

View File

@ -1,106 +0,0 @@
# Generated by Django 2.2.4 on 2019-11-01 13:23
import django.contrib.gis.db.models.fields
from django.db import migrations, models
import django.db.models.deletion
import utils.models
class Migration(migrations.Migration):
dependencies = [
('location', '0021_auto_20191101_1323'),
('product', '0002_product_slug'),
]
operations = [
migrations.CreateModel(
name='Characteristic',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', utils.models.TJSONField(blank=True, help_text='{"en-GB":"some text"}', null=True, verbose_name='name')),
('value', models.CharField(blank=True, max_length=255, null=True, verbose_name='value')),
('priority', models.IntegerField(default=None, null=True, unique=True)),
],
options={
'verbose_name': 'characteristic',
'verbose_name_plural': 'characteristics',
},
bases=(utils.models.TranslatedFieldsMixin, models.Model),
),
migrations.CreateModel(
name='Unit',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
('value', models.CharField(max_length=255, verbose_name='value')),
],
options={
'verbose_name': 'unit',
'verbose_name_plural': 'units',
},
),
migrations.CreateModel(
name='WineStandard',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
('standard_type', models.CharField(choices=[('Appellation', 'Appellation'), ('Classification', 'Classification'), ('WineQuality', 'Wine quality'), ('YardClassification', 'Yard classification')], max_length=30, verbose_name='standard type')),
('coordinates', django.contrib.gis.db.models.fields.PointField(blank=True, default=None, null=True, srid=4326, verbose_name='Coordinates')),
],
options={
'verbose_name': 'wine standard',
'verbose_name_plural': 'wine standards',
},
),
migrations.RemoveField(
model_name='product',
name='wine_appellation',
),
migrations.AddField(
model_name='product',
name='wine_village',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='location.WineVillage', verbose_name='wine appellation'),
),
migrations.RemoveField(
model_name='product',
name='characteristics',
),
migrations.AlterField(
model_name='product',
name='establishment',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='products', to='establishment.Establishment', verbose_name='establishment'),
),
migrations.AlterField(
model_name='product',
name='name',
field=models.CharField(default=None, max_length=255, null=True, verbose_name='name'),
),
migrations.AlterField(
model_name='productsubtype',
name='index_name',
field=models.CharField(choices=[('rum', 'Rum'), ('other', 'Other'), ('extra brut', 'extra brut'), ('brut', 'brut'), ('brut nature', 'brut nature'), ('demi-sec', 'demi-sec'), ('Extra Dry', 'Extra Dry'), ('dosage zero', 'dosage zero'), ('sec', 'sec'), ('doux', 'doux'), ('moelleux', 'moelleux')], db_index=True, max_length=50, unique=True, verbose_name='Index name'),
),
migrations.CreateModel(
name='WineClassification',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, verbose_name='name')),
('standard', models.ForeignKey(on_delete=django.db.models.deletion.PROTECT, to='product.WineStandard', verbose_name='standard')),
],
options={
'verbose_name': 'wine classification',
'verbose_name_plural': 'wine classifications',
},
),
migrations.AddField(
model_name='product',
name='wine_standard',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, to='product.WineStandard', verbose_name='wine standard'),
),
migrations.AddField(
model_name='product',
name='characteristics',
field=models.ManyToManyField(to='product.Characteristic', verbose_name='characteristics'),
),
]

View File

@ -139,6 +139,7 @@ class Product(TranslatedFieldsMixin, BaseAttributes):
description = TJSONField(_('Description'), null=True, blank=True,
default=None, help_text='{"en-GB":"some text"}')
characteristics = models.ManyToManyField('Characteristic',
through='ProductCharacteristic',
verbose_name=_('characteristics'))
country = models.ManyToManyField('location.Country',
verbose_name=_('Country'))
@ -229,23 +230,38 @@ class Unit(models.Model):
return self.name
class Characteristic(TranslatedFieldsMixin, models.Model):
class Characteristic(models.Model):
"""Characteristic model."""
STR_FIELD_NAME = 'name'
name = TJSONField(_('name'), null=True, blank=True,
help_text='{"en-GB":"some text"}')
name = models.CharField(_('name'), max_length=255)
value = models.CharField(max_length=255, null=True, blank=True,
verbose_name=_('value'))
# unit = models.ForeignKey('Unit', on_delete=models.PROTECT)
priority = models.IntegerField(unique=True, null=True, default=None)
old_id = models.PositiveIntegerField(blank=True, null=True, default=None)
class Meta:
"""Meta model."""
verbose_name = _('characteristic')
verbose_name_plural = _('characteristics')
def __str__(self):
return self.name
class ProductCharacteristic(models.Model):
product = models.ForeignKey('Product', on_delete=models.CASCADE)
characteristic = models.ForeignKey('Characteristic', on_delete=models.CASCADE)
class Meta:
"""Meta class."""
verbose_name = _('product characteristic')
verbose_name_plural = _('product characteristics')
def __str__(self):
return f'{self.characteristic.name} - {self.characteristic.value}'
class WineStandardQuerySet(models.QuerySet):
"""Wine appellation queryset."""
@ -271,6 +287,7 @@ class WineStandard(models.Model):
verbose_name=_('standard type'))
coordinates = gis_models.PointField(
_('Coordinates'), blank=True, null=True, default=None)
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
objects = WineStandardQuerySet.as_manager()
@ -289,6 +306,12 @@ class WineClassification(models.Model):
name = models.CharField(_('name'), max_length=255)
standard = models.ForeignKey(WineStandard, on_delete=models.PROTECT,
verbose_name=_('standard'))
possible_color = models.ForeignKey(Characteristic, on_delete=models.PROTECT,
help_text=_('Legacy attribute'))
possible_subtype = models.ForeignKey(ProductSubType, on_delete=models.PROTECT,
blank=True, null=True, default=None,
help_text=_('Legacy attribute - possible_type'))
old_id = models.PositiveIntegerField(_('old id'), blank=True, null=True, default=None)
objects = WineClassificationQuerySet.as_manager()

View File

@ -1,12 +1,12 @@
from pprint import pprint
from transfer.models import EstablishmentBacklinks, WineColor
from transfer import models as transfer_models
from transfer.serializers.partner import PartnerSerializer
from transfer.serializers.product import WineColorSerializer
from transfer.serializers import product as product_serializers
def transfer_partner():
queryset = EstablishmentBacklinks.objects.filter(type="Partner")
queryset = transfer_models.EstablishmentBacklinks.objects.filter(type="Partner")
serialized_data = PartnerSerializer(data=list(queryset.values()), many=True)
if serialized_data.is_valid():
@ -16,16 +16,41 @@ def transfer_partner():
def transfer_wine_color():
queryset = WineColor.objects.all()
serialized_data = WineColorSerializer(data=list(queryset.values()),
many=True)
queryset = transfer_models.WineColor.objects.all()
serialized_data = product_serializers.WineColorSerializer(
data=list(queryset.values()),
many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
pprint(f"CharacteristicSerializer errors: {serialized_data.errors}")
pprint(f"WineColorSerializer errors: {serialized_data.errors}")
def transfer_wine_standard():
queryset = transfer_models.WineClassification.objects.filter(parent_id__isnull=True)
serialized_data = product_serializers.WineStandardSerializer(
data=list(queryset.values()),
many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
pprint(f"WineStandardSerializer errors: {serialized_data.errors}")
def transfer_wine_classifications():
queryset = transfer_models.WineClassification.objects.filter(parent_id__isnull=False)
serialized_data = product_serializers.WineStandardClassificationSerializer(
data=list(queryset.values()),
many=True)
if serialized_data.is_valid():
serialized_data.save()
else:
pprint(f"WineStandardClassificationSerializer errors: {serialized_data.errors}")
data_types = {
"partner": [transfer_partner],
"wine_color": [transfer_wine_color],
"wine_standard": [transfer_wine_standard],
"wine_classification": [transfer_wine_classifications],
}

View File

@ -27,6 +27,9 @@ class Command(BaseCommand):
LONG_DATA_TYPES = [
'update_country_flag',
'wine_color',
'wine_standard',
'wine_classification',
]
def handle(self, *args, **options):

View File

@ -909,6 +909,16 @@ class WineColor(MigrateMixin):
db_table = 'wine_colors'
class WineType(MigrateMixin):
using = 'legacy'
name = models.CharField(max_length=255)
class Meta:
managed = False
db_table = 'wine_types'
class WineClassification(MigrateMixin):
using = 'legacy'
@ -927,17 +937,6 @@ class WineClassification(MigrateMixin):
db_table = 'wine_classifications'
class WineTypes(MigrateMixin):
using = 'legacy'
name = models.CharField(max_length=255, blank=True, null=True)
fra_encima_id = models.IntegerField(blank=True, null=True)
class Meta:
managed = False
db_table = 'wine_types'
# class Products(models.Model):
# establishment = models.ForeignKey('Establishments', models.DO_NOTHING, blank=True, null=True)
# brand = models.CharField(max_length=255, blank=True, null=True)

View File

@ -1,17 +1,21 @@
from django.contrib.gis.db.models.fields import Point
from rest_framework import serializers
from product.models import Characteristic
from product import models
from transfer.models import WineColor, WineType, WineClassification
class WineColorSerializer(serializers.ModelSerializer):
NAME = 'Wine color'
NAME = 'wine_color'
id = serializers.IntegerField()
name = serializers.CharField(allow_null=True)
order_number = serializers.IntegerField(allow_null=True)
class Meta:
model = Characteristic
model = models.Characteristic
fields = (
'id',
'name',
'value',
'priority',
@ -19,8 +23,87 @@ class WineColorSerializer(serializers.ModelSerializer):
)
def validate(self, attrs):
attrs['old_id'] = attrs.pop('id')
attrs['value'] = attrs['name']
attrs['name'] = {'en-GB': self.NAME}
attrs['priority'] = attrs['order_number']
attrs.pop('order_number')
attrs['name'] = self.NAME
attrs['priority'] = attrs.pop('order_number')
return attrs
class WineStandardSerializer(serializers.ModelSerializer):
id = serializers.IntegerField()
name = serializers.CharField()
type = serializers.ChoiceField(choices=models.WineStandard.STANDARDS,
allow_null=True)
longitude = serializers.FloatField(allow_null=True)
latitude = serializers.FloatField(allow_null=True)
class Meta:
model = models.WineStandard
fields = (
'id',
'name',
'type',
'longitude',
'latitude',
)
def validate(self, attrs):
latitude = attrs.pop('latitude', None)
longitude = attrs.pop('longitude', None)
attrs['coordinates'] = self.get_point(latitude, longitude)
attrs['old_id'] = attrs.get('id')
attrs['standard_type'] = attrs.pop('type', None)
return attrs
def get_point(self, latitude, longitude):
if latitude and longitude:
return Point(x=longitude, y=latitude, srid=4326)
class WineStandardClassificationSerializer(serializers.ModelSerializer):
id = serializers.IntegerField()
name = serializers.CharField()
possible_type_id = serializers.IntegerField(allow_null=True)
possible_color_id = serializers.IntegerField()
parent_id = serializers.IntegerField()
class Meta:
model = models.WineClassification
fields = (
'id',
'name',
'possible_type_id',
'possible_color_id',
'parent_id',
)
def validate(self, attrs):
possible_type_id = attrs.pop('possible_type_id', None)
possible_color_id = attrs.pop('possible_color_id', None)
parent_id = attrs.pop('parent_id', None)
attrs['old_id'] = attrs.pop('id', None)
attrs['possible_subtype'] = self.get_possible_type(possible_type_id)
attrs['possible_color'] = self.get_possible_color(possible_color_id)
attrs['standard'] = self.get_wine_standard(parent_id)
return attrs
def get_possible_type(self, possible_type_id):
legacy_qs = WineClassification.objects.filter(id=possible_type_id)
if legacy_qs.exists():
qs = models.ProductSubType.objects.filter(index_name=legacy_qs.first())
if qs.exists():
return qs.first()
def get_possible_color(self, possible_color_id):
qs = models.Characteristic.objects.filter(name=WineColorSerializer.NAME,
old_id=possible_color_id)
if qs.exists():
return qs.first()
def get_wine_standard(self, parent_id):
qs = models.WineStandard.objects.filter(old_id=parent_id)
if qs.exists():
return qs.first()

View File

@ -74,7 +74,6 @@ PROJECT_APPS = [
'comment.apps.CommentConfig',
'favorites.apps.FavoritesConfig',
'rating.apps.RatingConfig',
# 'transfer.apps.TransferConfig',
'tag.apps.TagConfig',
'product.apps.ProductConfig',
]
@ -157,16 +156,6 @@ DATABASES = {
'HOST': os.environ.get('DB_HOSTNAME'),
'PORT': os.environ.get('DB_PORT'),
},
# 'legacy': {
# 'ENGINE': 'django.db.backends.mysql',
# # 'HOST': '172.17.0.1',
# # 'HOST': '172.23.0.1',
# 'HOST': 'mysql_db',
# 'PORT': 3306,
# 'NAME': 'dev',
# 'USER': 'dev',
# 'PASSWORD': 'octosecret123'
# }
}

View File

@ -34,6 +34,22 @@ MEDIA_ROOT = os.path.join(PUBLIC_ROOT, MEDIA_LOCATION)
# SORL thumbnails
THUMBNAIL_DEBUG = True
# ADDED TRANSFER APP
INSTALLED_APPS.append('transfer.apps.TransferConfig')
# ADDED LEGACY DB CONNECTOR
DATABASES.update({
'legacy': {
'ENGINE': 'django.db.backends.mysql',
# 'HOST': '172.17.0.1',
# 'HOST': '172.23.0.1',
'HOST': 'mysql_db',
'PORT': 3306,
'NAME': 'dev',
'USER': 'dev',
'PASSWORD': 'octosecret123'}})
# LOGGING
LOGGING = {

View File

@ -42,7 +42,6 @@ django-storages==1.7.2
sorl-thumbnail==12.5.0
# mysqlclient==1.4.4
PyYAML==5.1.2
# temp solution

View File

@ -1,3 +1,4 @@
-r base.txt
ipdb
ipython
ipython
mysqlclient==1.4.4