2009-03-03 4 views
19
class dbview(models.Model): 
    # field definitions omitted for brevity 
    class Meta: 
     db_table = 'read_only_view' 

def main(request): 
    result = dbview.objects.all() 

перехвачено исключение во время рендеринга: (1054, «Неизвестный столбец„ read_only_view идентификатор“в„списке полей“»)Джанго: Запросы чтения только просматривать, без первичного ключа

Существует нет первичного ключа Я вижу в представлении. Есть ли обходной путь?

Комментарий:
У меня нет контроля над представлением, с которым я обращаюсь с Django. В браузере MySQL отображаются столбцы, но первичный ключ отсутствует.

ответ

17

Когда вы говорите: «Я не имею никакого контроля над видом я обращающимся с Django. В браузере MySQL отображаются столбцы, но первичный ключ отсутствует.

Я предполагаю, что вы имеете в виду, что это устаревшая таблица, и вам не разрешено добавлять или изменять столбцы?

Если это так, и там действительно нет первичного ключа (даже столбца строки или не-int *), тогда таблица не была настроена очень хорошо, и производительность вполне могла бы вонять.

Это не имеет значения для вас. Все, что вам нужно, это столбец, который гарантированно будет уникальным для каждой строки. Установите, что в вашей модели будет «primary_key = True», и Django будет счастлив.

  • Есть еще одна возможность, которая была бы проблематичной. Если нет столбца, который гарантированно будет уникальным, тогда таблица может использовать составные первичные ключи. То есть - это указание, что два столбца, взятые вместе, предоставят уникальный первичный ключ. Это вполне допустимое реляционное моделирование, но, к сожалению, не поддерживается Django. В этом случае вы не можете делать ничего, кроме необработанного SQL, если не сможете добавить еще один столбец.
+0

Большое вам спасибо, это действительно полезно! – dmi

+0

Очень полезно. Одно добавление; если столбец, который вы хотите использовать для первичного ключа, является CHAR-типом, он не может превышать 255 символов. –

+6

На самом деле это не относится к вопросу, относящемуся к представлению db, а не к таблице. Вы указываете одно из своих полей как pk для django, независимо от того, является оно или нет. Вы можете уйти от этого, так как никогда не будет никакой вставки/обновления в отношении через ORM. См. [Ответ от David S] (http://stackoverflow.com/a/11594959/519015) и мой комментарий по этому поводу для получения дополнительной информации об этой технике. –

1

При запуске syncdb должно существовать автоматически сгенерированное поле id (если в вашей модели нет первичного ключа, то Django вставляет AutoField для вас).

Эта ошибка означает, что Django запрашивает вашу базу данных для поля id, но не существует. Можете ли вы запустить django manage.py dbshell, а затем DESCRIBE read_only_view; и опубликовать результат? Это покажет все столбцы, которые находятся в базе данных.

В качестве альтернативы вы можете включить определение модели, которое вы исключили? (И подтвердить, что вы не изменили определение модели, так как вы запускали syncdb?)

+0

Спасибо, я должен был сделать это более ясным в начале. См. Обновление. – dmi

+0

Я не прошу увидеть строку, к которой вы обращаетесь, я просто хочу увидеть ваше определение модели (не одно и то же). – obeattie

+0

Определения модели следующие: text = models.CharField() Однако я не могу определить поле с 'primary_key = True', потому что у представления нет первичного ключа. – dmi

3

Если там действительно нет первичного ключа в представлении, то нет обходной путь.

Django requires each model to have exactly one field primary_key=True.

+0

Спасибо! Если я не вижу первичный ключ в представлении, это означает, что первичного ключа нет ...? Думаю, я просто вернусь к необработанному SQL. – dmi

+0

Не обязательно. См. Мой комментарий ниже. –

12

У меня есть эта проблема все время. У меня есть представление, что я не могу или не хочу меняться, но хочу иметь страницу для отображения составной информации (возможно, в разделе администратора). Я просто переопределить сохранить и поднять NotImplementedError:

def save(self, **kwargs): 
     raise NotImplementedError() 

(хотя это, вероятно, не требуется в большинстве случаев, но это заставляет меня чувствовать себя немного лучше)

Я также набор удалось Ложные в Meta класс.

class Meta: 
     managed = False 

Затем я просто выбираю любое поле и отмечаю его как первичный ключ. Неважно, действительно ли это уникально для вас, просто делаете фильтры для отображения информации на странице и т. Д.

Кажется, что все в порядке. Пожалуйста, отправьте, если есть какие-либо проблемы с этой техникой, которые я пропускаю.

+2

Вы можете пометить не уникальное поле как первичный ключ для доступа только для чтения, но это имеет последствия для таких вещей, как 'queryset.distinct(). Count()' и сравнения экземпляров. В качестве обходного пути для последнего вы можете переопределить '__eq __()' на модели. –

+0

Что-то, что вы можете сделать для представления, если вы хотите иметь идентификатор, использует функцию 'row_number()' (по крайней мере, в PostgreSQL). 'SELECT row_number() OVER (поле ORDER BY ASC) AS id,' – Bobort