python - tutorial - queryset django




Cómo funcionan las propiedades en los campos del modelo django? (2)

Como se mencionó, una alternativa correcta para implementar su propia clase django.db.models.Field, se debe usar el argumento db_column y un atributo de clase personalizado (u oculto). Solo estoy reescribiendo el código en la edición de @Jiaaro siguiendo convenciones más estrictas para OOP en python (por ejemplo, si _foo debe estar realmente oculto):

class MyModel(models.Model):
    __foo = models.CharField(max_length = 20, db_column='foo')
    bar = models.CharField(max_length = 20)

    @property
    def foo(self):
        if self.bar:
            return self.bar
        else:
            return self.__foo

    @foo.setter
    def foo(self, value):
        self.__foo = value

__foo se resolverá en _MyModel__foo (como se ve por dir (..) ) así oculto ( private ). Tenga en cuenta que este formulario también permite el uso de @property decorator, que en última instancia sería una forma más agradable de escribir código legible.

De nuevo, django creará la tabla * _MyModel con dos campos foo y barra .

Creo que la mejor manera de hacer esta pregunta es con algún código ... ¿puedo hacer esto? ( editar : RESPUESTA: no)


    class MyModel(models.Model):
foo = models.CharField(max_length = 20)
bar = models.CharField(max_length = 20)
    def get_foo(self):  
        if self.bar:  
            return self.bar  
        else:  
            return self.foo  

    def set_foo(self, input):  
        self.foo = input  

    foo = property(get_foo, set_foo)  

o tengo que hacerlo así:

Sí, tienes que hacerlo así:

class MyModel(models.Model):
    _foo = models.CharField(max_length = 20, db_column='foo')
    bar = models.CharField(max_length = 20)

    def get_foo(self):
        if self.bar:
            return self.bar
        else:
            return self._foo

    def set_foo(self, input):
        self._foo = input

    foo = property(get_foo, set_foo)

nota : puede mantener el nombre de la columna como 'foo' en la base de datos al pasar una columna db al campo modelo. Esto es muy útil cuando trabajas en un sistema existente y no quieres tener que hacer migraciones de db sin ningún motivo


Las soluciones anteriores sufren porque @property causa problemas en el administrador y .filter (_foo).

Una mejor solución sería anular setattr, excepto que esto puede causar problemas al inicializar el objeto ORM desde el DB. Sin embargo, hay un truco para evitar esto, y es universal.

class MyModel(models.Model):
    foo = models.CharField(max_length = 20)
    bar = models.CharField(max_length = 20)

    def __setattr__(self, attrname, val):
        setter_func = 'setter_' + attrname
        if attrname in self.__dict__ and callable(getattr(self, setter_func, None)):
            super(MyModel, self).__setattr__(attrname, getattr(self, setter_func)(val))
        else:
            super(MyModel, self).__setattr__(attrname, val)

    def setter_foo(self, val):
        return val.upper()

El secreto es ' attrname en self .__ dict__ '. ¡Cuando el modelo se inicializa desde nuevo o hidratado desde el __dict__ !





models