Skip to main content
 首页 » 编程设计

python之在 Django 中保存不断增加的字典的数据

2024年08月12日30lonelyxmas

我正在尝试将 API 响应的数据保存在我的 Django 表中,但我面临的问题是 API 在一个包含多个词典的列表中进行响应,并且每次我调用 API 时词典的数量都会增加。

例子 第一次通话

A = [{foo:4, 
      bar:5}] 

第二次通话

A = [{foo:4, 
      bar:5}, {foo:8, bar:10}] 

第三次通话

A = [{foo:4, 
      bar:5}, {foo:8, bar:10}, {foo:12, bar:15}] 

等等

我的模型是这样的:

class Tracking(models.Model): 
 
    foo = models.CharField(max_length=255, default=0) 
    bar = models.CharField(max_length=255, default=0) 

我的观点.py

class trackapi(APIView): 
 
    def get(self, request, pk): 
 
       response = requests.request('GET', url, headers=headers, data=payload, auth=user_pass) 
 
       for i in response.text: 
           Tracking.objects.create(foo = i["foo"], bar = i["bar"] 

但是这会在表中创建很多多个条目,我应该怎么做才能不复制表中的数据?

我尝试过的:

    lr_id = LR.objects.filter(lr_quiz=pk)[0].id 
    invoice_id = Invoice.objects.filter(invoice_quiz=pk)[0].id 
 
    for i in track_response: 
 
        Tracking.objects.get_or_create(lr_no=lr_id,invoice_no=invoice_id, 
                                       tracking_id=i["_id"],trip_id = i["tripId"],telephone=i["tel"], 
                                       loc = i["loc"], address=i["address"],city=i["city"], 
                                       created_at=i["createdAt"]) 

API 数据:

[{"_id":"5dccedadff47e867a2833819","tel":"xxxxxxx","loc":[28.498692,77.095215],"tripId":"5dccedaaff47e867a28337ec","mode":"automated","osm_data":{"distance_remained":10791,"time_remained":1649.5},"distance_remained":10870,"time_remained":1173,"curr_ETA":"2019-11-14T06:43:19.664Z","address":"100, 
The National Media Centre, Sector 24, Gurugram, Haryana 122022, 
India","city":"Gurugram","createdAt":"2019-11-14T06:01:17.166Z"},{"_id":"5dccedacff47e867a2833801","tel":"xxxxxxx","loc":[28.498692,77.095215],"tripId":"5dccedaaff47e867a28337ec","mode":"automated","osm_data":{"distance_remained":10791,"time_remained":1649.5},"distance_remained":10870,"time_remained":1173,"curr_ETA":"2019-11-14T06:43:18.459Z","address":"100, 
The National Media Centre, Sector 24, Gurugram, Haryana 122022, 
India","city":"Gurugram","createdAt":"2019-11-14T06:01:16.163Z"}] 

请您参考如下方法:

虽然@drd 的回答可能有效,但我认为可能有更好的方法来利用 Django 的广泛工具。

对于非常简单的字典,例如您示例中使用的 foo 和 bar 字典,很难使用以下方法,但我怀疑您的数据是否那么简单。

因此,您可以使用美妙的get_or_create 方法!来自docs :

A convenience method for looking up an object with the given kwargs (may be empty if your model has defaults for all fields), creating one if necessary.

Returns a tuple of (object, created), where object is the retrieved or created object and created is a boolean specifying whether a new object was created.

This is meant to prevent duplicate objects from being created when requests are made in parallel, and as a shortcut to boilerplatish code.

但是,为了确保它正常工作,因为这是一个边缘案例,你需要对它有一点技巧。

假设 API 返回的数据集类似于堆栈结构,您可以设计一个处理程序,根据每个条目在 API 返回的数据集中出现的位置为每个条目分配一个 ID,即第一个字典是 1,第二个是2,等等。

模型.py

class Tracking(models.Model): 
    id = models.CharField("ID", max_length=255, primary_key=True) 
    ... 

views.py

def get(...):     
... 
# we also need to deserialize the response data into an iterable list 
data = json.loads(response.text) 
 
for i, entry in enumerate(data): 
    Tracking.objects.get_or_create(pk=i, **entry) 

这将在新对象出现时创建新对象,而不会因之前调用的重复内容而使您的数据库困惑。

编辑

如果从 API 获取的数据已经有某种唯一字段(在本例中为 _id),您可以只使用该值作为主键,如下所示:

views.py

def get(...): 
    ... 
    for entry in data: 
        pk = entry.pop("_id") 
        Tracking.objects.get_or_create(pk=pk, **entry)