'Symmetrical link between two objects in Django

I have a model with all the info of a plant and another model which consists of creating links between these plants. But when I create a link between two plants for example I create an ideal link between basil and garlic in the Django admin, I don't have the symmetrical link between garlic and basil. Should we add symmetrical = true in the model?

Here is Plant model :

from django.db import models

class Plant(models.Model):
    class LEVEL(models.TextChoices):
        NONE = None
        EASY = 'easy',
        MEDIUM = 'medium',
        HARD = 'hard'
    
    class SUNSHINE(models.TextChoices):
        NONE = None
        FULL_SUN = 'full_sun',
        SHADOW = 'shadow',
        SUNNY = 'sunny',
        MODERATE = 'moderate'

    class IRRIGATION(models.TextChoices):
        NONE = None
        WET = 'wet',
        WEAKLY = 'weakly',
        MOIST = 'keep_soil_moist',
        GENEROUSLY = 'generously',
        SLIGHTLY_DAMP = 'slightly_damp',
        COVERED_WITH_WATER = 'covered_with_water'
    
    class SOIL_N(models.TextChoices):
        NONE = None
        HUMUS = 'humus',
        LIGHT = 'light',
        CLAY = 'clay',
        DRAINED = 'drained',
        ALL_TYPE = 'all_types'

    class SOIL_T(models.TextChoices):
        NONE = None
        POOR = 'poor',
        MEDIUM_SOIL = 'medium_soil',
        RICH = 'rich',
        FERTILE = 'fertile',
        DRAINED = 'drained',
        ADD_PEBBLES = 'add_pebbles',
        ALL_TYPE = 'all_types'

    class HARDINESS(models.TextChoices):
        NONE = None
        VERY_FRAGILE = 'very_fragile',
        FRAGILE = 'fragile',
        RUSTIC = 'rustic',
        MEDIUM = 'medium',
        SUPPORT_FRESHNESS = 'support_freshness',
        # COLD_RESISTANT = 'cold_resistant'

    name = models.CharField(max_length=150, unique=True)
    family = models.ForeignKey('perma_families.Family', on_delete=models.CASCADE, default=3)
    category = models.ForeignKey('perma_plant_categories.PlantCategory', on_delete=models.CASCADE, default=1)
    facility_rate = models.CharField(max_length=50, choices=LEVEL.choices, default=LEVEL.NONE, blank=True, null=True)
    seedling_depth = models.CharField(max_length=50, blank=True, null=True)
    seedling_distance = models.CharField(max_length=50, blank=True, null=True)
    row_spacing = models.CharField(max_length=50, blank=True, null=True)
    sunshine_index = models.CharField(max_length=50, choices=SUNSHINE.choices, default=SUNSHINE.NONE, blank=True, null=True)
    irrigation_index = models.CharField(max_length=50, choices=IRRIGATION.choices, default=IRRIGATION.NONE, blank=True, null=True)
    soil_nature = models.CharField(max_length=50, choices=SOIL_N.choices, default=SOIL_N.NONE, blank=True, null=True)
    soil_type = models.CharField(max_length=50, choices=SOIL_T.choices, default=SOIL_T.NONE, blank=True, null=True)
    fertilizer_type = models.CharField(max_length=50, blank=True, null=True)
    acidity_index = models.CharField(max_length=50, blank=True, null=True)
    days_before_sprouting = models.CharField(max_length=50, blank=True, null=True)
    average_harvest_time = models.CharField(max_length=50, blank=True, null=True)
    soil_depth = models.CharField(max_length=50, blank=True, null=True)
    plant_height = models.CharField(max_length=50, blank=True, null=True)
    suitable_for_indoor_growing = models.BooleanField(default=True, null=True)
    suitable_for_outdoor_growing = models.BooleanField(default=True, null=True)
    suitable_for_pot_culture = models.BooleanField(default=True, null=True)
    hardiness_index = models.CharField(max_length=70, choices=HARDINESS.choices, default=HARDINESS.NONE, blank=True, null=True)
    no_of_plants_per_meter = models.CharField(max_length=50, blank=True, null=True)
    no_of_plants_per_square_meter = models.CharField(max_length=50, blank=True, null=True)
    min_temperature = models.CharField(max_length=20, blank=True, null=True)
    max_temperature = models.CharField(max_length=20, blank=True, null=True)
    time_to_transplant = models.CharField(max_length=50, blank=True, null=True)

    def __str__(self):
        return self.name

Here is Plant associated model :

from django.db import models
from apps.perma_plants.models import Plant

class LnkPlantPlant(models.Model):
    class MAGNET_CHOICES(models.TextChoices):
        NONE = None
        IDEAL = 'ideal',
        GOOD = 'good',
        MEDIOCRE = 'mediocre',
        BAD = 'bad'

    plant = models.ManyToManyField('perma_plants.Plant', related_name='%(class)s_plant')
    plant_associated = models.ManyToManyField('perma_plants.Plant', related_name='%(class)s_plant_associated')
    link = models.CharField(max_length=10, choices=MAGNET_CHOICES.choices, default=MAGNET_CHOICES.NONE, blank=True, null=True)
    description = models.CharField(max_length=255, blank=True, null=True)

Thanks



Solution 1:[1]

According to Jeff's answer, it can be done manually:

# using Model.object.create is a shortcut to instantiating, then calling save()
linkplt = LnkPlantPlant.objects.create(link='something', description='something')
garlic = Plant.objects.create(name='garlic')
basil = Plant.objects.create(name='basil')

linkplt.plant.add(garlic)
linkplt.plant_associated.add(basil)

linkplt.plant.add(basil)
linkplt.plant_associated.add(garlic)

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Siva Sankar