Как стереть поля или не разрешить добавлять содержимое в неправильные поля в модуле 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) и т. д.
Вопрос:
- Как удалить или не разрешить пользователям добавлять данные в неправильные поля?
- В шаблоне (форма публикации) Как показать только поле "Фильм", поле "Метаданные" и поле с правильным значением?
Код:
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.