Разница между setattr и манипуляцией объектами в python/django

у меня есть следующие модели:

class Ticket(models.Model):
    title = models.CharField()
    merged_to = models.ForeignKey("self", related_name='merger_ticket', null=True, blank=True)
    looser_ticket = models.BooleanField(default=False)

существует несколько способов манипулирования моделью:

первый

ticket = Ticket.objects.get(pk=1)
ticket.title = "This is edit title"
ticket.merged_to_id = 2
ticket.looser_ticket = True

второй

ticket = Ticket.objects.get(pk=1)
setattr(ticket, "title", "Edit Title")
setattr(ticket, "merged_to_id", 2)
setattr(ticket, "looser_ticket", True)

когда я манипулировал материалом, в представлениях для обновления логического значения первый метод не работал, однако второй метод работал. В чем разница между использованием первого и второго, и когда они должны быть использованы?

спасибо!

2 ответов


это больше вопрос Python.

Python - очень динамичный язык. Вы можете кодировать вещи (классы) раньше времени, или Python позволяет создавать классы полностью динамически во время выполнения. Рассмотрим следующий пример простого класса vector. Вы можете создать/закодировать класс заранее, например:

class MyVector(object):
    x = 0
    y = 0

или вы можете создать класс динамически, выполнив:

fields = {'x':0, 'y':0}
MyVector = type('MyVector', (object,), fields)

основное различие между методами заключается в том, что для одного ты знаешь атрибуты класса заранее, тогда как для второго метода, как вы можете себе представить, вы можете программно создать fields словарь, поэтому вы можете создать полностью динамически класс(ы).

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

instance.attribute = value

имейте в виду, что это эквивалентно:

instance.__setattr__(attribute, value)

однако есть сценарии, в которых вы не знаете класс атрибутами нужно будет манипулировать заранее. Здесь вы можете использовать


Если вы знаете свойства объектов перед рукой, вы, вероятно, должны использовать первый метод. Просто назначьте значения свойств напрямую.

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

possible_fields = ['title', 'looser_ticket']
ticket = Ticket.objects.get(pk=1)
for field in possible_fields:
  if request.GET.get(field):
     setattr(ticket, field, request.GET[field])

"не работает", вероятно, не зависит от как вы устанавливаете значения, вы уверены, что после сохранения изменений??