Django 反序列化 - 我已经指定了一个自然密钥管理器,但它不会'反序列化

mik*_*kec 3 django serialization

首先,这是我用作将其组合在一起的指南的页面: https: //docs.djangoproject.com/en/dev/topics/serialization/

这是我的模型定义:

class LocationManager(models.Manager):
    def get_by_natural_key(self, zip_code):
        return self.get(zip_code=zip_code)

class Location(models.Model):
    city = models.CharField('City', blank=True, null=True, max_length=50)
    state = models.CharField('State', blank=True, null=True, max_length=2, choices=STATE_CHOICES)
    zip_code = models.CharField('Zip Code', blank=False, null=False, max_length=9, unique=True)
    date_added = models.DateField('Date Added')

    objects = LocationManager()

    def natural_key(self):
        return self.zip_code
Run Code Online (Sandbox Code Playgroud)

这是我试图反序列化的序列化项目:

    {
        "pk": 10259, 
        "model": "news.news", 
        "fields": {
            "content": "some content", 
            "created_on": "2012-07-24T16:10:44.570", 
            "location": "99801", 
            "title": "Some title"
        }
    }
Run Code Online (Sandbox Code Playgroud)

我试图用以下代码反序列化 json:

    for news_obj in serializers.deserialize('json', news_json):
        news_obj.save()
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:

IntegrityError: insert or update on table "news" violates foreign key constraint "news_location_id_fkey"
DETAIL:  Key (location_id)=(99801) is not present in table "location".
Run Code Online (Sandbox Code Playgroud)

因此,它似乎试图将 zip_code 解析为自然键,而不是尝试使用我定义的自然键检查该项目是否存在于数据库中。我究竟做错了什么?

mik*_*kec 5

我找到了一个适合我的解决方案。看起来自然键需要一个列表而不是单个字段,猜测他们只计划自然键是字段值的组合。我通过返回列表中的邮政编码解决了这个问题。

def natural_key(self):
    return [self.zip_code]
Run Code Online (Sandbox Code Playgroud)

完成此操作后,反序列化就像我想要的那样工作。

执行此操作后得到的编码 JSON 如下所示:

{
    "pk": 10661, 
    "model": "news.news", 
    "fields": {
        "content": "", 
        "created_on": "2012-07-25T10:19:56.627", 
        "location": [
            "36101"
        ], 
        "article_date": "2012-07-25T10:05:56", 
        "title": ""
    }
}
Run Code Online (Sandbox Code Playgroud)