Search code examples
pythondjangopostgresqlforeign-keysforeign-key-relationship

Django: Foreign key from parent to child table


I want to have a foreign key link from Parent table to child table ; for a site which is mainly backend powered. Currently only admin part of site is active as that is the only part required to get our information team working.

App structure:

attraction:

|
|--- model
| |
| | --- _ _init__.py
| | --- imagemetadata.py
|
| --- models.py
| --- admin.py

(imagemetadata is under directory model)

file imagemetadata.py

from attraction.models import Attraction

class ImageMetadata(models.Model):
    image = models.ImageField(upload_to='', blank=True, null=True)
    upload_time = models.DateTimeField(null=True)

    attraction = models.ForeignKey(Attraction)

file models.py

from django.db import models

class Attraction(models.Model):
    name = models.CharField(max_length=100, null=False)
    description = models.CharField(max_length=500, null=True)
    url = models.URLField(max_length=200, null=True)

file admin.py

class ImageMetadataInline(admin.TabularInline):
    model = ImageMetadata
    extra = 2

class AttractionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None, {'fields': ['name', 'description', 'url']}),
    ]

    inlines = [ImageMetadataInline, PriceInline]

admin.site.register(Attraction, AttractionAdmin)

The problem i am facing is i cant get a foreign key from Attraction to Imagemetadata. If I try to make a two way foreign key import error occurs. ( Cyclic imports not allowed in Python). And because of the structure of admin , there cant be a foreign key just from Attraction to ImageMetadata, as Django doesnt allow that.

Is there a way to make the foreign key point from Attraction to ImageMetadata, without changing the structure of admin ?


Solution

  • You can define the class Meta as following:

    class ImageMetadata(models.Model):
        # ... your fields
    
        class Meta:
            app_label = 'attraction'
    

    Make a sub-directory models in your app directory. Split your models into different files. Then edit the __init__.py:

    from model_file1 import *
    from model_fiel2 import *
    # and so on
    

    Now you can make:

    from attraction.models import whatever
    

    I split in this way my tests. It should work for the models too.

    However I would suggest you first to rethink your design. In Python is absolutely all right to have many classes in one file. Python is neither PHP nor Java. 200 LOC per file is nothing. I would say it is absolutely okay if your models.py are up to 2k LOC. Just my personal opinion. Maybe some Python gurus here can correct me.

    Before you split your models.py consider if you can maybe split your project in smaller apps. Maybe ImageMetadata should belong to another app. You can't achieve granularity by splitting the models.py into many files. Just because you have many smaller files instead of one big file doesn't mean the project logic is split. You should break down your logic into few self-containing apps.