Search code examples
pythonsqldjangoormlegacy-database

Django how to add a model instance with a foreign key field if the referenced model instance does not exist


I am working with a legacy database within an AS400 system connected to my Django project. I am trying to configure my models in the best way possible and set up relationships correctly but I am running into an issue related to adding an instance of a model that has a foreign key field to another model but the instance of that model might not exist yet.

Here is an example, consider the following two models:

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"'

The "star_fname" field in MOVIEPF is a Foreign key to the "fname" field in CLIENTPF. So if I wanted to add an instance to the MOVIEPF table in my views.py with the following ORM I would get an error since "Rowan" is just a string and not an instance of the CLIENTPF model.

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

Instead this code would work:

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()

My problem however is that I want to add an instance to MOVIEPF with the "star_fname" field value to be "Rowan" even without there existing a CLIENTPF instance with this "fname" but it should recognize it once an instance is added to CLIENTPF with the corresponding name in the "fname" field.

Does anyone know if this is possible? There is a workaround but it requires not using these relational field attributes in my models like ForeignKey which I would like to take advantage of if possible since this would make my ORM queries a lot more efficient.


Solution

  • but the instance of that model might not exist yet.

    If you are unsure about the existence of CLIENTPF instance and it is blocking you from creating MOVIEPF instance then you can either set null=True to star_fname field to allow null values or you need to create a an instance of CLIENTPF before populating the 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()
    

    I don't think there is any other way to create related model except above.

    Edit:

    You can also try get_or_create to get the instance if existing or create it.