Как стереть поля или не разрешить добавлять содержимое в неправильные поля в модуле django?

Спасибо заранее, за просмотр и ответ на мой вопрос,

Изображений:

Проблема: https://drive.google.com/file/d/0Bw4K4uUse4DYWHZmYW9kZWJtcE0/edit?usp=sharing

thePosibleSolution: (это фотошоповое изображение того, что я хочу сделать) https://drive.google.com/file/d/0Bw4K4uUse4DYcjZ1TnBVdUk4R3M/edit?usp=sharing

Фон:

В моем модуле django у меня есть 3 таблицы: фильмы, метаданные и таблица соединений, которая называется MoviesMetadata. В фильмах хранятся названия фильмов ("Бойцовский клуб"), в "Метаданных" хранятся названия метаданных ("Дата", "Режиссер", "Актеры", "Доход" и т. Д.) И тип этих метаданных (текст, дата, пользователи, десятичное число, целое число). Наконец, таблица соединений объединяет фильм с несколькими метаданными и значениями метаданных этого фильма в зависимости от типа метаданных (textValue, integerValue, usersValue, decimalValue и т. Д.).

Проблема:

Проблема заключается в том, что когда кто-то добавляет метаданные (дату) в фильм ("Бойцовский клуб"), ожидаемый результат заключается в том, что поле dateValue имеет некоторый контент (1999/10/15), но также пользователь может добавлять контент в textValue или другое тип значения, который не является типом этих метаданных. В конце концов, values для метаданных Date для фильма The Fight Club может быть 1999/10/15 (поле dateValue), admin (поле usersValue), 36,000,000.00 (поле decimalValue) и т. д.

Вопрос:

  1. Как удалить или не разрешить пользователям добавлять данные в неправильные поля?
  2. В шаблоне (форма публикации) Как показать только поле "Фильм", поле "Метаданные" и поле с правильным значением?

Код:

class Movies(models.Model):
    name = models.CharField(max_length=100)
    metadata = models.ManyToManyField(Metadata, through='MoviesMetadata')

    def __str__(self):
        return str(self.name)


class MoviesMetadata(models.Model):
    movie = models.ForeignKey(Movies)
    metadata = models.ForeignKey(Metadata)
    textValue = models.CharField(max_length=100, blank=True, null=True)
    dateValue = models.DateField(auto_now=False, auto_now_add=False, blank=True, null=True)
    userValue = models.ForeignKey(User, blank=True, null=True)
    decimalValue = models.DecimalField(max_digits=18, decimal_places=2, blank=True, null=True)

    def _value(self):
        '''
        @property returns only the values from the selected fieldtype,
        ignore the other fieldtypes values.
        '''
        if self.metadata.fieldtype == '0':
            return self.textValue
        elif self.metadata.fieldtype == '1':
            return self.dateValue
        elif self.metadata.fieldtype == '2':
            return self.userValue
        else:
            return self.decimalValue
    value = property(_value)

    def __str__(self):
        return ('%s: %s' % (self.metadata, self.value))


class Metadata(models.Model):
    name = models.CharField(max_length=100)
    METADATA_FIELD_TYPE = (
        ('0', 'Text Value'),
        ('1', 'Date Value'),
        ('2', 'User Value'),
        ('3', 'Decimal Value'),
    )
    fieldtype = models.CharField(max_length=1, choices=METADATA_FIELD_TYPE, default='0')

    def __str__(self):
        return ('%s (%s)' % (self.name, self.get_fieldtype_display()))

1 ответ

Вы используете анти-шаблон EAV СУБД. Вы (пытаетесь) встроить часть СУБД в свою программу + базу данных. СУБД уже существует для управления данными и метаданными. Используй это.

Не иметь класс / таблицу метаданных. Просто имейте атрибуты фильмов быть полями / столбцами фильмов.

Ваш класс / таблица метаданных тоже страдает от этого дополнительным образом. Не иметь поле / столбец, который представляет собой список, представляющий строку. Просто имейте имена элементов списка как имена полей / столбцов метаданных. За исключением этого, у вас не должно быть метаданных класса / таблицы. Потому что каждая такая строка кодирует атрибуты фильма. Конкретные поля / столбцы для фильмов должны быть просто в фильмах.

Из одного из ответов, связанных выше:

Представление о том, что нужно использовать EAV "чтобы каждый тип сущности можно было расширять с помощью настраиваемых полей", ошибочно. Просто реализуйте через вызовы, которые обновляют таблицы метаданных иногда вместо простого обновления обычных таблиц: DDL вместо DML.

Другие вопросы по тегам