От 1 до 1..0 в Django / MySQL - PullRequest
       22

От 1 до 1..0 в Django / MySQL

0 голосов
/ 13 марта 2012

Я хотел бы получить несколько советов о том, как обрабатывать отношения от 1 до 1..0 в Django.

У меня есть список товаров, которые имеют множество атрибутов, которые в большинстве случаев не имеют значения (до 95% товаров). Вместо того, чтобы хранить их в таблице продуктов, я поместил их в отдельные таблицы, поэтому у меня есть следующее (с редкими атрибутами возраста и веса):

products
    id
    colour
    height
    width

product_age
    id
    product_id (FK)
    age

product_weight
    id
    product_id (FK)
    weight

и т.д.

Во-первых, я знаю, что в InnoDB пустые значения не занимают места, поэтому я думаю, что, возможно, это не повлияет на производительность, если я переместу разреженные атрибуты в таблицу продуктов

Во-вторых, если я сохраню все эти отношения от 1 до 1..0, как мне справиться с этим в models.py. У меня сейчас есть:

class Product(models.Model):
    colour = models.CharField(max_length=13)
    height = models.CharField(max_length=13)
    width = models.CharField(max_length=13)

class ProductAge(models.Model):
    product_id = models.ForeignKey(Product)
    age = models.CharField(max_length=13)

class ProductWeight(models.Model):
    product_id = models.ForeignKey(Product)
    weight = models.CharField(max_length=13)

Громко иметь все это как разные объекты, а это значит, что мне придется помнить, какие атрибуты являются отдельными объектами при кодировании.

Любая помощь будет оценена. Спасибо

UPDATE

Наследование работает здесь, но все еще кажется немного грязным. Мне нужно что-то вроде:

class Product(models.Model):
    colour = models.CharField(max_length=13)
    height = models.CharField(max_length=13)
    width = models.CharField(max_length=13)

class ProductWithAge(Product):
    age = models.CharField(max_length=13)

class ProductWithAgeAndWeight(Product):
    weight = models.CharField(max_length=13)

Тогда я бы фактически использовал в своем коде только ProductWithAgeAndWeight, поскольку я мог получить доступ ко всем полям давать из этого. База данных будет разделять данные между тремя таблицами. Может быть, проблема в моем названии ... есть мысли?

Ответы [ 3 ]

1 голос
/ 14 марта 2012

Вы должны использовать OneToOneField.

class ProductAge(models.Model):
    age = models.CharField(max_length=13)

class ProductWeight(models.Model):
    weight = models.CharField(max_length=13)

class Product(models.Model):
    colour = models.CharField(max_length=13)
    height = models.CharField(max_length=13)
    width = models.CharField(max_length=13)
    age = models.OneToOneField(ProductAge, null=True, blank=True)
    weight = models.OneToOneField(ProductWeight, null=True, blank=True)

Таким образом, вы можете напрямую обращаться к атрибутам .age и .weight напрямую из экземпляра product.

При настройке внешних ключей вы получите список с помощью .age_set и .weight_set, проверьте, не является ли список пустым, затем возьмите первый элемент. Утомительно и подвержено ошибкам. И наследство - это просто не тот путь, по которому можно идти.

0 голосов
/ 14 марта 2012

Не думаю, что вам нужны отдельные первичные ключи во 2 дополнительных таблицах. product_id достаточно:

products
    id
    colour
    height
    width

product_age
    product_id (PK) (FK)
    age

product_weight
    product_id (PK) (FK)
    weight

Модель будет:

class Product(models.Model):
    colour = models.CharField(max_length=13)
    height = models.CharField(max_length=13)
    width = models.CharField(max_length=13)

class ProductAge(models.Model):
    product_id = models.ForeignKey(Product)
    product_id.primary_key=True 
    age = models.CharField(max_length=13)

class ProductWeight(models.Model):
    product_id = models.ForeignKey(Product)
    product_id.primary_key=True 
    weight = models.CharField(max_length=13)

Если вы хотите избежать сложностей при вставке / обновлении продуктов, вам следует работать с одной таблицей products, которая допускает пустые значения в 2 рядах. Нули действительно занимают место, но это не так уж и важно, что вам не все равно.

0 голосов
/ 14 марта 2012

Я думаю, что то, к чему вы стремитесь, лучше всего достигается с помощью менеджеров моделей, и одна таблица для продуктов или 2 таблицы, одна таблица «Product» и другая таблица «ProductAttribute», в которой хранятся такие вещи, как {'attribute_name': 'age', 'attribute_value': 13, 'product_id': 3 '} с ProductAttributeManager

https://docs.djangoproject.com/en/dev/topics/db/managers/

...