簡體   English   中英

試圖了解 Django postgresql 的 JSONField

[英]Trying to understand JSONField for django postgresql

我正在閱讀有關 JSONField 的文檔,這是一種特殊的 postgresql 字段類型。 由於我打算創建一個子類化JSONField的自定義字段,並具有能夠轉換我的Lifts類的附加功能:

class Lifts(object):
    def __init__(self, series):
        for serie in series:
            if type(serie) != LiftSerie:
                raise TypeError("List passed to constructor should only contain LiftSerie objects")
        self.series = series

class AbstractSerie(object):

    def __init__(self, activity, amount):
        self.activity_name = activity.name
        self.amount = amount

    def pre_json(self):
        """A dict that can easily be turned into json."""
        pre_json = {
            self.activity_name:
                self.amount
        }
        return pre_json

    def __str__(self):
        return str(self.pre_json())

class LiftSerie(AbstractSerie):

    def __init__(self, lift, setlist):
        """ lift should be an instance of LiftActivity.
            setList is a list containing reps for each set
            that has been performed.
        """
        if not (isinstance(setlist, collections.Sequence) and not isinstance(setlist, str)):
            raise TypeError("setlist has to behave as a list and can not be a string.")
        super().__init__(lift, setlist)

我在這里讀到to_python()from_db_value()Field類上的兩個方法,它們涉及從數據庫加載值和反序列化它們。 此外,在Fieldto_python()方法的文檔字符串中,它說它應該被子類覆蓋。 所以,我查看了JSONField 你猜怎么着,它不會覆蓋它 此外, from_db_value()甚至沒有Field定義(也沒有在JOSNFieldJOSNField )。

那么這里發生了什么? 這使得很難理解 JSONField 如何獲取值並將它們轉換為 json 並將它們存儲在數據庫中,然后在我們查詢數據庫時相反。

我的問題總結:

  1. 為什么在JSONField沒有覆蓋to_python()
  2. 為什么在JSONField沒有覆蓋from_db_value()
  3. 為什么from_db_value()甚至沒有在Field定義?
  4. JSONField如何以 Python dict為例,將其轉換為 JSON 字符串,並將其存儲在數據庫中?
  5. 它如何做相反的事情?

很抱歉有很多問題,但我真的很想了解這一點,而且文檔有點缺乏 IMO。

對於 Django 數據庫字段,相同數據存在三種相關的狀態/表示:表單、python 和數據庫。 在示例HandField情況下,表單/數據庫表示是相同的字符串,python 表示是Hand對象實例。

JSONField之上的自定義字段的情況下,內部 python 可能是一個LiftSerie實例,表單表示一個 json 字符串,發送到數據庫的值是一個 json 字符串,從數據庫接收的值是由 psycopg2 轉換而來的 json 結構postgres 返回的字符串,如果有意義的話。

就你的問題而言:

  1. python 值沒有自定義,所以字段的python 數據類型與預期輸入相同。 HandField示例相反,其中輸入可以是字符串或Hand實例。 在后一種情況下,只返回輸入的基本Field.to_python()實現就足夠了。

  2. Psycopg2 已經將數據庫值轉換為 json,參見 5。對於其他類型(如 int/ IntegerField )也是如此。

  3. from_db_value沒有在基類Field定義,但如果存在,肯定會被考慮在內。 如果您查看from_db_value Field.get_db_converters()實現,如果Field具有這樣命名的屬性, from_db_valuefrom_db_value添加到其中。

  4. django.contrib.postgres.JSONField有一個可選的編碼器參數。 默認情況下,它使用沒有編碼器的json.dumps將 json 結構轉換為 JSON 字符串。

  5. psycopg2 自動從數據庫類型轉換為 python 類型。 這叫做適應 JSON 適配文檔解釋了它是如何工作的並且可以自定義。

請注意,在實現自定義字段時,我建議在開發期間為其編寫測試,尤其是在未完全理解機制的情況下。 您可以在例如django-localflavor 中獲得此類測試的靈感。

簡短的回答是, to_python 和 from_db_value 都返回應該序列化為 JSON 的 python 字符串,沒有編碼錯誤,所有事情都是平等的。

如果你對字符串沒問題,那很好,但我通常會覆蓋 Django 的 JSONFields 的 from_db_value 方法來返回一個 dict 或一個列表,而不是在我的代碼中使用的字符串。 我為此創建了一個自定義字段。

對我來說,Json 字段的全部意義在於能夠與它的值作為字典或列表進行交互。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM