czy właściwości działają na polach modelu django?

Myślę, że najlepszym sposobem na zadanie tego pytania jest użycie jakiegoś kodu... mogę to zrobić? (edit : odpowiedź: Nie)


    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)  

a może muszę to zrobić tak:

Tak, musisz to zrobić tak:

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)

Notatka: możesz zachować nazwę kolumny jako " foo " w bazie danych, przekazując db_column do pola Modelu. Jest to bardzo pomocne, gdy pracujesz na istniejącym systemie i nie chcesz mieć db migracje bez powodu

Author: Jiaaro, 2009-09-21

3 answers

Pole modelu jest już własnością, więc powiedziałbym, że musisz to zrobić w drugi sposób, aby uniknąć kolizji nazw.

Gdy zdefiniujesz Foo = property(..) faktycznie nadpisuje foo = models.. linii, tak aby to pole nie było już dostępne.

Będziesz musiał użyć innej nazwy dla właściwości i pola. W rzeczywistości, jeśli zrobisz to tak, jak w przykładzie #1, Otrzymasz nieskończoną pętlę, gdy spróbujesz uzyskać dostęp do właściwości, ponieważ teraz próbuje ona powrócić siebie.

EDIT: być może powinieneś również rozważyć Nie używanie _foo jako nazwy pola, ale raczej foo, a następnie zdefiniować inną nazwę dla swojej właściwości, ponieważ właściwości nie mogą być używane w QuerySet, więc będziesz musiał użyć rzeczywistych nazw pól, gdy wykonasz na przykład filtr.

 19
Author: Andre Miller,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-21 15:02:00

Jak wspomniano, poprawna alternatywa dla implementacji własnego django.db.modelki.Klasa pola, należy użyć argumentu - db_column oraz niestandardowego (lub ukrytego) atrybutu klasy. Po prostu przepisuję kod w edycji przez @ Jiaaro zgodnie z bardziej rygorystycznymi konwencjami dla OOP w Pythonie (np. jeśli _foo powinno być faktycznie Ukryte):

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 zostanie rozwiązane do _MyModel__foo (Jak widać przez dir(..) ) tak Ukryte (prywatne ). Zauważ, że ten formularz pozwala również na użycie @ property decorator, co byłoby ostatecznie ładniejszym sposobem napisania czytelnego kodu.

Ponownie, django utworzy tabelę * _MyModel z dwoma polami fooi bar.

 15
Author: Yauhen Yakimovich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-30 01:28:30

Poprzednie rozwiązania cierpią, ponieważ @ property powoduje problemy w adminie i .filter(_foo).

Lepszym rozwiązaniem byłoby nadpisanie setattr z tym wyjątkiem, że może to powodować problemy z inicjalizacją obiektu ORM z DB. Jest jednak sztuczka, aby to obejść i jest uniwersalna.

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

Sekretem jest ' attrname in self.__ dict _ _ ". Gdy model inicjalizuje się z new lub uwodniony z __dict _ _ !

 5
Author: Justin Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-24 17:16:12