在保存时跳过字段(Django模型,插入和更新)

2024-09-30 06:22:40 发布

您现在位置:Python中文网/ 问答频道 /正文

考虑到PostgreSQL 9.2.10、Django 1.8、Python2.7.5,以下模型:

class soapProdAPI(models.Model):
    soap_id = models.PositiveIntegerField(primary_key=True)
    soap_host = models.CharField(max_length=20)
    soap_ip = models.GenericIPAddressField(default='0.0.0.0')
    soap_asset = models.CharField(max_length=20)
    soap_state = models.CharField(max_length=20)

以及以下代码:

^{pr2}$

回答JosuéPadilla的问题:

@task
def saveSoapNullIP():
    missingIP = soapProdAPI.objects.filter(soap_ip='0.0.0.0')
    if missingIP:
        for record in missingIP:
            if str(record.soap_host).lower().startswith('1a'):
                fqdn = str(record.soap_host) + 'stringvaluehere'
            elif str(record.soap_host).lower().startswith('1b'):
                fqdn = str(record.soap_host) + 'stringvaluehere'
            elif str(record.soap_host).lower().startswith('1c'):
                fqdn = str(record.soap_host) + 'stringvaluehere'
            else:
                fqdn = str(record.soap_host) + 'stringvaluehere'
            try:
                hostIp = check_output('host %s' % fqdn, shell=True)
                hostIp = hostIp.split()[-1]
            except:
                hostIp = '0.0.0.0'
            record.soap_ip = hostIp
            record.save(update_fields=['soap_ip'])

我的soapProdQuery只返回这4个字段,其中模型中有第5个字段(soap_ip)。我知道这可能不是最好的方法,但我有一个单独的代码块,它在数据库中查询None值,soap_ip在这些值上运行一个子进程主机并将其与ip地址一起保存(每次通过时返回/更新的行数应该会变小,而不是将主机查找的逻辑放入请求/这个celry任务本身,它将运行每个API请求。我已经试过了,返回完整的数据要花很多时间)。我查询的soapapi没有提供IP,否则我显然会以这种方式获取它。用户可以在后台无缝运行芹菜任务。在

我遇到的问题是每次saveSoapProd()运行时,它都会用'0.0.0.0'覆盖前面的soap_ip字段,从而否定了我的另一个函数的工作。另一个问题是我不能force_insert或{},因为我需要这两个功能。我的问题是:有没有一种方法可以在每次运行saveSoapProd()时有选择地同时更新/插入并完全排除对soap_ip的任何操作?我们非常感谢任何帮助。提前谢谢你。在

**编辑1**

我可能在update_or_create或{a2}中找到了解决方案,也可能没有找到,但是我不确定确切的用法。医生让我有点困惑。在

**编辑2**

我猜你或你创建是一个半身像。第一次通过后,每次保存都会失败:

Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "<console>", line 8, in saveSoapProd
  File "/lib/python2.7/site-packages/django/db/models/base.py", line 690, in save
    % ', '.join(non_model_fields))
ValueError: The following fields do not exist in this model or are m2m fields: soap_id

代码如下:

@periodic_task(run_every=timedelta(minutes=2))
def saveSoapProd():
    tableProdSoap = soapProdQuery()
    if tableProdSoap != None:
        for item in tableProdSoap:
            obj, created = soapProdAPI.objects.get_or_create(soap_id=item[0], defaults={'soap_host': item[1], 'soap_asset': item[2], 'soap_state': item[3]})
            if created == False:
                commit = soapProdAPI(soap_id=item[0], soap_host=item[1], soap_asset=item[2], soap_state=item[3])
                commit.save(update_fields=['soap_id', 'soap_host', 'soap_asset', 'soap_state'])

老实说,我不太清楚是什么导致了这个错误。在


**编辑3/当前解决方案**

我可以通过修改模型和任务函数来解决自己的问题。该解决方案使用get_或_create,但是您可以很容易地从提供的解决方案中推断出如何使用update_或_create。参见下面选择的答案。在


**TLDR**

我想做一个.save(),它可能需要插入新记录或更新更改的记录,而不需要接触soap_ip字段(不insert_onlyupdate_only)。在


Tags: inipidhostfieldsmodelsupdateasset
2条回答

我不知道您是否已经知道这一点,但您可以重写模型的save()函数。在

class soapProdAPI(models.Model):
    soap_id = models.PositiveIntegerField(primary_key=True)
    soap_host = models.CharField(max_length=20)
    soap_ip = models.GenericIPAddressField(default='0.0.0.0')
    soap_asset = models.CharField(max_length=20)
    soap_state = models.CharField(max_length=20)

    # Override save
    def save(self, *args, **kwargs):
        if self.soap_ip != '0.0.0.0':
          self.soap_ip = your_ip # Here you can  get your old IP an save that instead of 0.0.0.0

编辑

你得到了

ValueError: The following fields do not exist in this model or are m2m fields: soap_id

因为您正在尝试更新soap_id,所以该字段被定义为模型的主键,因此在更新时它是不可变的。这就是为什么当你这样做的时候它会崩溃:

commit.save(update_fields=['soap_id', 'soap_host', 'soap_asset', 'soap_state'])

尝试从update_fields中删除soap_id。在

通过对模型进行以下更改,在不修改保存方法的情况下解决了我自己的问题:

class soapProdAPI(models.Model):
    soap_id = models.PositiveIntegerField(unique=True, null=False)
    soap_host = models.CharField(max_length=20)
    soap_ip = models.GenericIPAddressField(default='0.0.0.0')
    soap_asset = models.CharField(max_length=20)
    soap_state = models.CharField(max_length=20)

我的任务是:

^{pr2}$

编辑

只是注意到了JosuéPadilla的回答,这实际上是我用这个答案解决问题的一部分。感谢乔苏的帮助。在

相关问题 更多 >

    热门问题