pythondjangodjango-modelsforeign-keysdjango-model-field

How to use Reverse Relations in Model Django


Here I'm trying to create 4 Foriegn Keys of DeviceException Table in DeviceControlPolicy Table for individual Device.

This DeviceException table will consist 4 Type of Device Exceptions and i am creating individual Columns as foriegn key in the DeviceControlPolicy Table for the each Device, just to make it easy. [if any suggestion please let me know how can i use this] and how can i solve this error

DeviceControlPolicy.py

from django.db import models
from .src.models.Vendor import Vendor
from .src.models.DeviceException import DeviceException


class DeviceControlPolicy(models.Model):
    vendor_id = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    usb_storage_device = models.CharField(max_length=10, default="allow")
    usb_storage_except = models.ForeignKey(DeviceException, on_delete=models.CASCADE)
    cd_dvd = models.CharField(max_length=10, default="allow")
    portable = models.CharField(max_length=10, default="allow")
    portable_except = models.ForeignKey(DeviceException, on_delete=models.CASCADE)
    wifi = models.CharField(max_length=10, default="allow")
    bluetooth = models.CharField(max_length=10, default="allow")
    webcam = models.CharField(max_length=10, default="allow")
    webcam_except = models.ForeignKey(DeviceException, on_delete=models.CASCADE)
    serial_port = models.CharField(max_length=10, default="allow")
    serial_port_except = models.ForeignKey(DeviceException, on_delete=models.CASCADE)
    usb_port = models.CharField(max_length=10, default="allow")
    local_printer = models.CharField(max_length=10, default="allow")
    network_share = models.CharField(max_length=10, default="allow")
    card_reader = models.CharField(max_length=10, default="allow")
    unknown_device = models.CharField(max_length=10, default="allow")

    def __str__(self):
        return self.name

DeviceException.py

from django.db import models
from .src.models.Vendor import Vendor
from .src.models.DeviceClassification import DeviceClassification


class DeviceException(models.Model):
    vendor_id = models.ForeignKey(Vendor, on_delete=models.CASCADE)
    id = models.IntegerField(primary_key=True)
    name = models.CharField(max_length=100)
    description = models.CharField(max_length=1000)
    classification = models.ForeignKey(DeviceClassification, on_delete=models.DO_NOTHING)
    exception_type = models.CharField(max_length=50)
    action = models.CharField(default="allow", max_length=10)

    def __str__(self):
        return self.name

Error I'm Facing:

ERRORS: DeviceControlPolicy.portable_except: (fields.E304) Reverse accessor for 'DeviceControlPolicy.portable_except' clashes with reverse accessor for 'DeviceControlPolicy.usb_storage_except'. HINT: Add or change a related_name argument to the definition for 'DeviceControlPolicy.portable_except' or 'DeviceControlPolicy.usb_storage_except'. DeviceControlPolicy.usb_storage_except: (fields.E304) Reverse accessor for 'DeviceControlPolicy.usb_storage_except' clashes with reverse accessor for 'DeviceControlPolicy.portable_except'. HINT: Add or change a related_name argument to the definition for 'DeviceControlPolicy.usb_storage_except' or 'DeviceControlPolicy.portable_except'.


Solution

  • The error makes complete sense, you have to give some related_name whatever you want, you should add or change it, so that it will not clash with other ForeignKeys.

    If you don't specify a related_name, Django automatically creates it by using the ModelName as a prefix and _set as a suffix..

    Try this:

    Models.py:

    
    class DeviceControlPolicy(models.Model):
        id = models.IntegerField(primary_key=True)
        name = models.CharField(max_length=100)
        description = models.CharField(max_length=1000)
        usb_storage_device = models.CharField(max_length=10, default="allow")
        usb_storage_except = models.ForeignKey(
            DeviceException, on_delete=models.CASCADE, related_name='usb_storate')
        cd_dvd = models.CharField(max_length=10, default="allow")
        portable = models.CharField(max_length=10, default="allow")
        portable_except = models.ForeignKey(
            DeviceException, on_delete=models.CASCADE, related_name='portable_except')
        wifi = models.CharField(max_length=10, default="allow")
        bluetooth = models.CharField(max_length=10, default="allow")
        webcam = models.CharField(max_length=10, default="allow")
        webcam_except = models.ForeignKey(
            DeviceException, on_delete=models.CASCADE, related_name='webcam_except')
        serial_port = models.CharField(max_length=10, default="allow")
        serial_port_except = models.ForeignKey(
            DeviceException, on_delete=models.CASCADE, related_name='serial_port_except')
        usb_port = models.CharField(max_length=10, default="allow")
        local_printer = models.CharField(max_length=10, default="allow")
        network_share = models.CharField(max_length=10, default="allow")
        card_reader = models.CharField(max_length=10, default="allow")
        unknown_device = models.CharField(max_length=10, default="allow")
    
        def __str__(self):
            return self.name
    

    In the above example, I've added related_name to every column which associates with Foreignkey of DeviceException model.

    You can change related_name according to your wish.