python django django-models setattribute setattr

Diferencia entre setattr y manipulación de objetos en python/django



django-models setattribute (2)

Tengo el siguiente modelo:

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)

Hay dos formas de manipular el modelo:

primero

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

Segundo

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

Cuando estaba manipulando las cosas, en las vistas para la actualización del valor booleano, el primer método no funcionaba; sin embargo, el segundo método funcionó. ¿Cuál es la diferencia entre usar primero y segundo, y cuando deberían usarse?

¡Gracias!


Esta es más una pregunta de Python.

Python es un lenguaje muy dinámico. Puede codificar cosas (clases) con anticipación, o Python le permite crear clases completamente dinámicas en tiempo de ejecución. Considere el siguiente ejemplo de una clase vectorial simple. Puede crear / codificar la clase con anticipación como:

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

o puedes crear la clase dinámicamente haciendo:

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

La principal diferencia entre los métodos es que conoce los atributos de la clase con anticipación, mientras que para el segundo método como puede imaginar, puede crear programáticamente el diccionario de fields , por lo tanto, puede crear clases completamente dinámicas.

Entonces, cuando conozca los atributos de la clase con anticipación, puede establecer los atributos de clase usando la notación de objeto:

instance.attribute = value

Tenga en cuenta que eso es equivalente a:

instance.__setattr__(attribute, value)

Sin embargo, existen situaciones en las que no conoce los atributos de clase que deberá manipular con anticipación. Aquí es donde puedes usar la función __setattr__ . Sin embargo, no es una práctica recomendada. Por lo tanto, en su lugar, la recomendación es utilizar el método de setattr Python setattr que internamente llama al método __setattr__ :

setattr(instance, attribute, value)

Usando este enfoque puede establecer atributos que no conoce de antemano o incluso puede hacer un bucle de algunos dict y establecer valores de dict:

values = { ''title'': ''This is edit title'', ... } for k, v in values.items(): setattr(ticket, k, v)

No estoy seguro de por qué la notación regular no funcionó. Probablemente no tiene nada que ver con el método que utilizó para establecer los atributos.


Si conoce las propiedades de los objetos de antemano, probablemente debería utilizar el primer método. Simplemente asigne valores de propiedad directamente.

El segundo puede ser útil cuando necesita asignar dinámicamente un valor a una propiedad. Tal vez un usuario tiene la capacidad de cambiar los valores de una serie de atributos diferentes y no sabe cuál tendrá un valor de antemano, puede agregar valores dinámicamente

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])

El "no funciona" probablemente no dependa de la forma en que está configurando los valores, ¿está seguro de que guardó los cambios después?