Django objects.update_or_create [英] Django objects.update_or_create

查看:77
本文介绍了Django objects.update_or_create的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个在 celery 中运行的 period_task 查询最新的加密货币价格,但出于某种原因,每次想要显示数据时,我都没有得到更新的记录,我只是得到了新的记录,而由于某种原因,旧的记录会被保留.

tasks.py

@periodic_task(run_every=(crontab(minute='*/1')), name="Update Crypto rate(s)", ignore_result=True)def get_exchange_rate():api_url = "https://api.coinmarketcap.com/v1/ticker/"尝试:exchange_rates = requests.get(api_url).json()对于 exchange_rates 中的 exchange_rate:CryptoPrices.objects.update_or_create(key=exchange_rate['id'],符号=exchange_rate['符号'],market_cap_usd=round(float(exchange_rate['market_cap_usd']), 3),volume_usd_24h=round(float(exchange_rate['24h_volume_usd']), 3),defaults={'value': round(float(exchange_rate['price_usd']), 3)})logger.info("加密货币汇率更新成功.")除了作为 e 的例外:打印(e)

models.py

class CryptoPrices(models.Model):key = models.CharField(max_length=255)值=models.CharField(max_length=255)符号 = 模型.CharField(max_length=255)volume_usd_24h = models.CharField(max_length=255)market_cap_usd = models.CharField(max_length=255)

views.py

def crypto_ticker(request):list_prices = CryptoPrices.objects.get_queryset().order_by('pk')paginator = Paginator(list_prices, 100) # 每页显示 100 个价格page = request.GET.get('page')价格 = paginator.get_page(page)返回渲染(请求,'crypto_ticker.html',{'价格':价格})

template.html:

{% 扩展 'base.html' %}{% 加载阅读更多 %}{% 块面包屑 %}{{ block.super }} » <a href="{% url 'post_list' %}">帖子 </a>»<a href="{% url 'crypto_ticker' %}">加密货币行情</a>{% 结束块 %}{% 块内容 %}<!DOCTYPE html><头><title>加密代码</title><身体><h1 class="center">加密货币行情</h1><hr class="hr-style"><div class="center"><h4>{{价格}} 在这里您可以找到所有常见问题<br>如果您仍有任何问题,请联系<a href="#">support</a>.</h4>

<br><div class="paginator"><跨度>{% if price.has_previous %}<a href="?page=1">&laquo;首先<a>|</a></a><a href="?page={{ price.previous_page_number }}">Previous</a>{% 万一 %}{% if price.has_next %}<跨度>加密价格 - {{ price.paginator.num_pages }} 的第 {{ price.number }} 页.</span><a href="?page={{ price.next_page_number }}">Next<a>|</a></a><a href="?page={{ price.paginator.num_pages }}">最后&raquo;</a>{% 万一 %}</span>

<table class="table centercontentfloat class-three-box"><头><tr style="font-size: small"><第>排名</th><th>符号</th><th>姓名</th><th>价格</th><th>市值(美元)</th>第 24 小时.交易量(美元)</tr></thead>{% for price in price %}<tr style="font-size: small"><td>{{ price.id }}</td><td>{{ price.symbol }}</td><td>{{ price.key }}</td><td>{{ price.value }} $</td><td style="font-size: small">{{ price.market_cap_usd }} $</td><td style="font-size: small">{{ price.volume_usd_24h }} $</td></tr>{% 结束为 %}</tbody><div class="paginator"><跨度>{% if price.has_previous %}<a href="?page=1">&laquo;首先<a>|</a></a><a href="?page={{ price.previous_page_number }}">Previous</a>{% 万一 %}{% if price.has_next %}<跨度>加密价格 - {{ price.paginator.num_pages }} 的第 {{ price.number }} 页.</span><a href="?page={{ price.next_page_number }}">Next<a>|</a></a><a href="?page={{ price.paginator.num_pages }}">最后&raquo;</a>{% 万一 %}</span>

{% 结束块 %}

我从 coinmarketcap api 获取的记录被保存/显示两次有什么明显的原因吗?

如果我浏览页面,我会返回如下内容:

<块引用>

加密价格 - 第 1 页,共 21 页.下一页 |最后的 "排名符号名称价格市值(美元)24 小时.成交量(美元)1 BTC 比特币 3795.6465 $ 66594617840.0 $ 8296474984.64 $2 ETH 以太坊 143.9996 $ 15106822040.0 $ 5043716023.22 $

然后在第二页:

<块引用>

« 第一 |以前的加密价格 - 第 2 页,共 22 页.最后的 "排名符号名称价格市值(美元)24 小时.成交量(美元)101 BTC 比特币 3798.3016 $ 66641201438.0 $ 8304474934.43 $102 ETH 以太坊 144.0825 $ 15115524904.0 $ 5048205218.98 $

我没想到 BTC 也在第二页,第一页只有一次?!?

看起来如果我浏览页面,记录不会得到更新,它们会在每次 period_task 运行后一个接一个地保存

亲切的问候

解决方案

您正在将查询中的所有字段用于现有实例.你只需要在那里使用唯一的,其余的在 defaults 字典中.

CryptoPrices.objects.update_or_create(key=exchange_rate['id'],符号=exchange_rate['符号'],默认值={"market_cap_usd": round(float(exchange_rate['market_cap_usd']), 3),"volume_usd_24h": round(float(exchange_rate['24h_volume_usd']), 3),价值":round(float(exchange_rate['price_usd']),3)})

i have a periodic_task running in celery that query for latest Cryptocurrency prices but for some reason, each time a want to display the data i dont get updated records i just get new ones and the old records are keep for some reason.

tasks.py

@periodic_task(run_every=(crontab(minute='*/1')), name="Update Crypto rate(s)", ignore_result=True)
def get_exchange_rate():
    api_url = "https://api.coinmarketcap.com/v1/ticker/"
    try:
        exchange_rates = requests.get(api_url).json()
        for exchange_rate in exchange_rates:
            CryptoPrices.objects.update_or_create(key=exchange_rate['id'],
                                                  symbol=exchange_rate['symbol'],
                                                  market_cap_usd=round(float(exchange_rate['market_cap_usd']), 3),
                                                  volume_usd_24h=round(float(exchange_rate['24h_volume_usd']), 3),
                                                  defaults={'value': round(float(exchange_rate['price_usd']), 3)}
                                                  )
        logger.info("Crypto exchange rate(s) updated successfully.")
    except Exception as e:
        print(e)

models.py

class CryptoPrices(models.Model):
    key = models.CharField(max_length=255)
    value = models.CharField(max_length=255)
    symbol = models.CharField(max_length=255)
    volume_usd_24h = models.CharField(max_length=255)
    market_cap_usd = models.CharField(max_length=255)

views.py

def crypto_ticker(request):
        list_prices = CryptoPrices.objects.get_queryset().order_by('pk')
        paginator = Paginator(list_prices, 100)  # Show 100 prices per page
        page = request.GET.get('page')
        price = paginator.get_page(page)
        return render(request, 'crypto_ticker.html', {'price': price})

template.html:

{% extends 'base.html' %}
{% load readmore %}

{% block breadcrumbs %}
    {{ block.super }} » <a href="{% url 'post_list' %}">Posts </a> »
    <a href="{% url 'crypto_ticker' %}">Crypto ticker</a>
{% endblock %}


{% block content %}

    <!DOCTYPE html>
    <html>
    <head>
        <title>Crypto ticker</title>
    </head>

    <body>
    <h1 class="center">Crypto ticker</h1>
    <hr class="hr-style">
    <div class="center">
        <h4>{{ prices }} Here you can find all frequently asked questions <br>
            if you still have still have any open points, please contact the <a href="#">support</a>.</h4>
    </div>
    <br>
    <div class="paginator">
        <span>
         {% if price.has_previous %}
            <a href="?page=1">&laquo; First <a> |</a></a>
            <a href="?page={{ price.previous_page_number }}">Previous</a>
        {% endif %}

        {% if price.has_next %}
            <span> Crypto prices - Page {{ price.number }} of {{ price.paginator.num_pages }}.</span>
            <a href="?page={{ price.next_page_number }}">Next<a> |</a></a>
            <a href="?page={{ price.paginator.num_pages }}">Last &raquo;</a>
        {% endif %}
       </span>
   </div>
    <table class="table centercontentfloat class-three-box">
        <thead>
            <tr style="font-size: small">
                <th>Ranking</th>
                <th>Symbol</th>
                <th>Name</th>
                <th>Price</th>
                <th>Market Cap (USD)</th>
                <th>24 hrs. Volume (USD)</th>
            </tr>
        </thead>
        <tbody>
        {% for price in price %}
            <tr style="font-size: small">
                <td>{{ price.id }}</td>
                <td>{{ price.symbol }}</td>
                <td>{{ price.key }}</td>
                <td>{{ price.value }} $</td>
                <td style="font-size: small">{{ price.market_cap_usd }} $</td>
                <td style="font-size: small">{{ price.volume_usd_24h }} $</td>
            </tr>
            {% endfor %}
        </tbody>
    </table>
    <div class="paginator">
        <span>
            {% if price.has_previous %}
            <a href="?page=1">&laquo; First <a> |</a></a>
            <a href="?page={{ price.previous_page_number }}">Previous</a>
        {% endif %}

        {% if price.has_next %}
            <span> Crypto prices - Page {{ price.number }} of {{ price.paginator.num_pages }}.</span>
            <a href="?page={{ price.next_page_number }}">Next<a> |</a></a>
            <a href="?page={{ price.paginator.num_pages }}">Last &raquo;</a>
        {% endif %}
       </span>
    </div>
{% endblock %}

Is there any notable reason why the records i grab from the coinmarketcap api is getting saved/ displayed twice?

if i go trough the pages i get back something like this:

Crypto prices - Page 1 of 21. Next | Last » Ranking Symbol Name Price Market Cap (USD) 24 hrs. Volume (USD) 1 BTC bitcoin 3795.6465 $ 66594617840.0 $ 8296474984.64 $ 2 ETH ethereum 143.9996 $ 15106822040.0 $ 5043716023.22 $

and on the second page:

« First | Previous Crypto prices - Page 2 of 22. Next | Last » Ranking Symbol Name Price Market Cap (USD) 24 hrs. Volume (USD) 101 BTC bitcoin 3798.3016 $ 66641201438.0 $ 8304474934.43 $ 102 ETH ethereum 144.0825 $ 15115524904.0 $ 5048205218.98 $

and i dont expect that BTC is also at the second page, only once at the first page?!?

It really seems if i go trough the pages, that the records dont get updated, they will get saved one after another after each periodic_task run

Kind regards

解决方案

You're using all the fields in the query for existing instances. You need to just use the unique ones there, and the rest in the defaults dict.

CryptoPrices.objects.update_or_create(
   key=exchange_rate['id'],
   symbol=exchange_rate['symbol'],
   defaults={             
       "market_cap_usd": round(float(exchange_rate['market_cap_usd']), 3),
       "volume_usd_24h": round(float(exchange_rate['24h_volume_usd']), 3),
       "value": round(float(exchange_rate['price_usd']), 3)
    })

这篇关于Django objects.update_or_create的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
Python最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆