Как работают поля модели Django?

Прежде всего, я не занимаюсь веб-программированием. Я столкнулся с джанго и немного почитал о моделях. Я был заинтригован следующим кодом (от djangoproject.com):


class Person(models.Model):
    first_name = models.CharField(max_length=50)
    last_name = models.CharField(max_length=50)

    def __str__(self):
        # Note use of django.utils.encoding.smart_str() here because
        # first_name and last_name will be unicode strings.
        return smart_str('%s %s' % (self.first_name, self.last_name))

По моему пониманию python, first_name и last_name являются переменными класса, не так ли? Как это используется в коде (потому что я предполагаю, что установка Person.first_name или Person.last_name повлияет на все экземпляры Person)? Почему он используется таким образом?

Ответ 1

Да, first_name и last_name являются переменными класса. Они определяют поля, которые будут созданы в таблице базы данных. Существует таблица Person, в которой есть столбцы first_name и last_name, поэтому для них имеет смысл находиться на уровне класса в этот момент.

Подробнее о моделях см. http://docs.djangoproject.com/en/dev/topics/db/models/

Когда дело доходит до обращения к экземплярам Person в коде, вы обычно делаете это через Django ORM, и в этот момент они по существу ведут себя как переменные экземпляра.

Подробнее о экземплярах модели см. http://docs.djangoproject.com/en/dev/ref/models/instances/?from=olddocs

Ответ 2

Суть вашего вопроса: "Почему эти переменные класса (которые я присваиваю объектам Field)) превращаются в переменные экземпляра (которые я назначаю данные) в Django ORM"? Ответ на это - магия Python метаклассы.

Метакласс позволяет подключать и изменять процесс создания класса Python (а не создание экземпляра этого класса, создание самого класса).

Объект Django Model (и, следовательно, ваши модели, которые являются подклассами) имеет метаклас ModelBase. Он просматривает все атрибуты класса вашей модели и любые экземпляры подкласса Field, которые он перемещает в список полей. Этот список присваивается как атрибут объекта _meta, который является атрибутом класса модели. Таким образом, вы всегда можете добраться до фактических объектов Field через MyModel._meta.fields или MyModel._meta.get_field('field_name').

Затем метод Model.__init__ может использовать список _meta.fields, чтобы определить, какие атрибуты экземпляра должны быть инициализированы при создании экземпляра модели.

Не бойтесь погрузиться в исходный код Django; это отличный источник образования!

Ответ 3

Не настоящий ответ, но для обогащения:

Person.first_name 

не будет работать

p = Person.objects.get(pk=x)
p.first_name

будет работать. поэтому экземпляр объекта лица имеет имя и фамилию, но статический контекст Person не делает.

Также обратите внимание: в Django есть диспетчеры моделей, которые позволяют "Person" выполнять статические операции запроса. (Https://docs.djangoproject.com/en/dev/topics/db/managers/#managers).

например,

peoples = Person.objects.all()