代码之家  ›  专栏  ›  技术社区  ›  Floris Kruger

Django如何在引用的模型实例不存在的情况下添加带有外键字段的模型实例

  •  0
  • Floris Kruger  · 技术社区  · 2 年前

    我正在使用连接到Django项目的AS400系统中的遗留数据库。我正在尝试以尽可能好的方式配置我的模型,并正确设置关系,但我遇到了一个问题,即将具有外键字段的模型的实例添加到另一个模型中,但该模型的实例可能还不存在。

    以下是一个示例,请考虑以下两个模型:

    class CLIENTPF(models.Model):
        id = models.BigAutoField(db_column='CLNTID', primary_key=True)
        fname = models.CharField(db_column='CLNTFNAME', max_length=30, unique=True, null=True)
        lname = models.CharField(db_column='CLNTLNAME', max_length=30)
        dob = models.CharField(db_column='CLNTDOB', max_length=10)
    
        class Meta:
            managed = False
            db_table = '"XPFLORIS"."CLIENTPF"'
    
    class MOVIEPF(models.Model):
        movie_name = models.CharField(db_column='MOVNAME', max_length=30, primary_key=True)
        star_fname = models.ForeignKey(CLIENTPF, to_field='fname', on_delete=models.PROTECT, db_column='STARACTF', max_length=30)
        star_lname = models.CharField(db_column='STARACTL', max_length=30)
        genere = models.CharField(db_column='GENERE', max_length=30)
        release_date = models.CharField(db_column='RELDATE', max_length=10)
    
        class Meta:
            managed = False
            db_table = '"XPFLORIS"."MOVIEPF"'
    

    MOVIEPF中的“star_name”字段是CLIENTPF中“fname”字段的外键。因此,如果我想用下面的ORM向views.py中的MOVIEPF表添加一个实例,我会收到一个错误,因为“Rowan”只是一个字符串,而不是CLIENTPF模型的实例。

     new_movie = MOVIEPF(movie_name="Johnny English", star_fname="Rowan", star_lname="Atkinson", genere="Comedy", release_date="02/12/2003")
        new_movie.save()
    

    相反,此代码将起作用:

    new_movie = MOVIEPF(movie_name="Johnny English", star_fname=CLIENTPF.objects.get(id=0), star_lname="Atkinson", genere="Comedy", release_date="02/12/2003")
    new_movie.save()
    

    然而,我的问题是,我想将一个“star_name”字段值为“Rowan”的实例添加到MOVIEPF,即使不存在具有此“fname”的CLIENTPF实例,但一旦将一个实例添加到具有“fname”字段中相应名称的CLIENTPF,它就应该识别它。

    有人知道这是否可能吗?有一种变通方法,但它不需要在我的模型中使用这些关系字段属性,比如ForeignKey,如果可能的话,我想利用它,因为这会使我的ORM查询更加高效。

    1 回复  |  直到 2 年前
        1
  •  1
  •   Ahtisham    2 年前

    但该模型的实例可能还不存在。

    如果您不确定 CLIENTPF 实例,它阻止您创建 MOVIEPF 实例,则可以设置 null=True star_fname 字段以允许null值,或者您需要创建 客户端 在填充之前 MOVIEPF :

    client = CLIENTPF.objects.filter(fname="Rowan").first()
    if client is None:
        client = CLIENTPF.objects.create(fname="Rowan", lname="David", dob="02/12/2003") 
        
    new_movie = MOVIEPF(movie_name="Johnny English", star_fname=client, star_lname="Atkinson", genere="Comedy", release_date="02/12/2003")
    new_movie.save()
    

    我不认为有任何其他方法来创建相关的模型,除了上面。

    编辑:

    你也可以试试 get_or_create 获取实例(如果存在)或创建实例。