Как добавить вычисляемое поле в модель Django

У меня есть простая модель Employee которая включает поля middlename и middlename .

На стороне администратора и, вероятно, в другом месте, я хотел бы показать это как:

  • Джанго. У вас нет прав редактировать что-либо
  • django подозрительная операция по загрузке изображения
  • Отключить кнопку «Назад» браузера после выхода из системы?
  • один-ко-многим встроенный выбор с django admin
  • Проблемы с администратором в django
  • разные поля для добавления и изменения страниц в admin
  •  lastname, firstname middlename 

    Для меня логичным местом для этого является модель, создавая вычисляемое поле как таковое:

     from django.db import models from django.contrib import admin class Employee(models.Model): lastname = models.CharField("Last", max_length=64) firstname = models.CharField("First", max_length=64) middlename = models.CharField("Middle", max_length=64) clocknumber = models.CharField(max_length=16) name = ''.join( [lastname.value_to_string(), ',', firstname.value_to_string(), ' ', middlename.value_to_string()]) class Meta: ordering = ['lastname','firstname', 'middlename'] class EmployeeAdmin(admin.ModelAdmin): list_display = ('clocknumber','name') fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), ] admin.site.register(Employee, EmployeeAdmin) 

    В конечном итоге то, что мне кажется нужным, – это получить значение полей имени в виде строк. Ошибка, которую я получаю, – value_to_string() takes exactly 2 arguments (1 given) . Значение в строке требует self, obj . Я не уверен, что означает obj .

    Должен быть простой способ сделать это, я уверен, что я не первый, кто захочет это сделать.

    Изменить: Это мой код, измененный для ответа Даниила. Ошибка, которую я получаю:

     django.core.exceptions.ImproperlyConfigured: EmployeeAdmin.list_display[1], 'name' is not a callable or an attribute of 'EmployeeAdmin' of found in the model 'Employee'. from django.db import models from django.contrib import admin class Employee(models.Model): lastname = models.CharField("Last", max_length=64) firstname = models.CharField("First", max_length=64) middlename = models.CharField("Middle", max_length=64) clocknumber = models.CharField(max_length=16) @property def name(self): return ''.join( [self.lastname,' ,', self.firstname, ' ', self.middlename]) class Meta: ordering = ['lastname','firstname', 'middlename'] class EmployeeAdmin(admin.ModelAdmin): list_display = ('clocknumber','name') fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), ] admin.site.register(Employee, EmployeeAdmin) 

  • Django Rest Framework и JSONField
  • добавление одного и того же объекта дважды в ManyToManyField
  • Как переопределить delete () на модели и работать с соответствующими удалениями
  • Django ORM-запрос GROUP BY несколькими столбцами, объединенными MAX
  • Есть ли умный способ получить предыдущий / следующий элемент с помощью Django ORM?
  • Как получить текущий экземпляр модели из inlineadmin в Django
  • 4 Solutions collect form web for “Как добавить вычисляемое поле в модель Django”

    Это не то, что вы делаете как поле. Даже если этот синтаксис работал, он будет давать значение только тогда, когда класс был определен, а не в момент его доступа. Вы должны сделать это как метод, и вы можете использовать декоратор @property чтобы он выглядел как обычный атрибут.

     @property def name(self): return ''.join( [self.lastname,' ,', self.firstname, ' ', self.middlename]) 

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

    Хорошо … Даниэль Роземан ответил, что это должно сработать. Как всегда, вы находите то, что ищете, после того как вы разместите вопрос .

    Из django 1.5 docs я нашел этот пример, который работал прямо из коробки. Спасибо всем за вашу помощь.

    Вот код, который сработал:

     from django.db import models from django.contrib import admin class Employee(models.Model): lastname = models.CharField("Last", max_length=64) firstname = models.CharField("First", max_length=64) middlename = models.CharField("Middle", max_length=64) clocknumber = models.CharField(max_length=16) def _get_full_name(self): "Returns the person's full name." return '%s, %s %s' % (self.lastname, self.firstname, self.middlename) full_name = property(_get_full_name) class Meta: ordering = ['lastname','firstname', 'middlename'] class EmployeeAdmin(admin.ModelAdmin): list_display = ('clocknumber','full_name') fieldsets = [("Name", {"fields":(("lastname", "firstname", "middlename"), "clocknumber")}), ] admin.site.register(Employee, EmployeeAdmin) 

    Решение Daniel Roseman делает вычисленное поле атрибутом Model , однако оно не делает его доступным с помощью методов QuerySet (например, all() , .values() ). Это связано с тем, что методы QuerySet напрямую ссылаются на базу данных , обходя Model django.

    Поскольку QuerySets напрямую обращаются к базе данных, решение должно переопределить метод .get_queryset() Manager , добавив ваше вычисленное поле. Вычисленное поле создается с помощью .annotate() . Наконец, вы устанавливаете диспетчер objects в своей Model новому Manager .

    Вот несколько примеров, демонстрирующих это:

    models.py

     from django.db.models.functions import Value, Concat from django.db import Model class InvoiceManager(models.Manager): """QuerySet manager for Invoice class to add non-database fields. A @property in the model cannot be used because QuerySets (eg. return value from .all()) are directly tied to the database Fields - this does not include @property attributes.""" def get_queryset(self): """Overrides the models.Manager method""" qs = super(InvoiceManager, self).get_queryset().annotate(link=Concat(Value("<a href='#'>"), 'id', Value('</a>'))) return qs class Invoice(models.Model): # fields # Overridden objects manager objects = InvoiceManager() 

    Теперь вы сможете вызвать .values() или .all() и получить доступ к новому вычисляемому атрибуту link указанному в Manager .

    Было бы также возможно использовать другие функции в .annotate() , такие как F() .

    Я считаю, что атрибут все равно не будет доступен в object._meta.get_fields() . Я считаю, вы можете добавить его здесь, но я не изучил, как – любые изменения / комментарии были бы полезными.

    В этом случае, если вы только собираетесь использовать поле для представления в админ-сайте и такие проблемы, вам лучше рассмотреть переопределение метода str () или unicode () класса, как это указано в документации django:

     class Employee(models.Model): # fields definitions def __str__(self): return self.lastname + ' ,' + self.firstname + ' ' + self.middlename 
    Python - лучший язык программирования в мире.