Python Django Model Design

RegShoe

Cadet 3rd Year
Registriert
Aug. 2023
Beiträge
58
Ich bin grade an einem Django-Projekt dran mit dem ich alle unsere Produktdaten (techn. Daten, Dokumente, Chargen-Verwaltung.. halt alles was dazugehört) zusammenfassen möchte. Erstmal damit wir alle Daten zentral an einem Platz haben und später auch um verschiedene weitere Arbeitsabläufe zu erleichtern.

Grob haben wir 3 Produktgruppen: Leuchten, Sicherheitsbeleuchtung und Zubehör. In der Produktgruppe Leuchten kommt es recht oft vor, dass es von einem Produkt mehrere Varianten gibt, die sich z. B. nur in der Farbe unterscheiden oder noch eine zusätzliche Option dabei haben. Die sonstigen Produktdetails und leuchtenspezifischen Daten sind aber identisch.

Mein Problem jetzt...Wie mache ich die Verbindung zwischen ProductVariant, Lamp, EmergencyLighting

Eine Idee war Vererbung. Also etwas in der Art wie

Python:
class ProductVariant(models.Model):
    ...
    product = models.ForeignKey(Product)


class ProductDetails(models.Model)
    ...


class Product(models.Model):
    ...
    product_details = models.ForeignKey(ProductDetails)


class Lamp(Product):
    ...


class Emergencylighting(Product):
    ...
Nur lese ich (fast) überall nur, dass man Vererbung in Django eigentlich vermeiden soll..


Mein Model sieht jetzt grob vereinfacht so aus (Kommentare sind jetzt nur fürs Forum drin ;-))

Python:
# Daten die sich von Variante zu Variante ändern (können)
class ProductVariant(models.Model):
    item_id = models.Charfield()
    case_colour = models.ForeignKey(Colour)
    ...
    options = models.ManyToManyField('ProductVariant', through='OptionDetails', related_name='option_details')


#techn. Daten die bei allen Produkten benötigt werden
class ProductDetails(models.Model):
    length = models.IntegerField()
    width = models.IntegerField()
    height = models.IntegerField()
    diameter = models.IntegerField()
    weight = models.DecimalField()
    ...


#halt die Leuchtenpezifischen Daten ;-).
class Lamp(models.Model)
    driver_included = models.BooleanField()
    external_driver = models.BooleanField()
    changeable_driver = models.BooleanField()
    average_lifespan = models.IntegerField()
    ugr = models.IntegerField()
    cri = models.IntegerField()
    ...
    product_details = models.ForeignKey(ProductDetails)


# dto für Sicherheitsbeleuchtung
class EmergencyLighting(models.Model)
    lum_flux_on_wire = models.IntegerField()
    lum_flux_on_accu = models.IntegerField()
    autotest = models.BooleanField()
    ...
    product_details = models.ForeignKey(ProductDetails)

Wenn also jemand eine Idee hat.. Wäre das wirklich super :daumen:

Danke schonmal
 
Ich hab letzte Nacht (bevor ich das gepostet hab) einiges gelesen und sehr oft war der Tenor, dass es unter anderem zu viele 'unnötige' selects und joins bedeuten würde. Dazu soll es wohl auch nicht so gut wartbar/erweiterbar sein. Aufgrund der doch schon sehr fortgeschrittenen Uhrzeit hab ich dann auch nicht mehr soo genau weitergelesen ;-).
Allerdings hab ich jetzt heute Vormittag nochmal etwas weiter gelesen und werde es dann jetzt wohl doch mal damit versuchen. Dazu guck ich mir dann jetzt auch mal Django-Polymorphic etwas genauer an...
 
SO, das Thema passt eigentlich immernoch also mach ich hier mal weiter ;-).

Jetzt hat sich mitten im Entwickeln noch ein neues Thema aufgetan. Wir haben uns überlegt unsere Produktdaten demnächst als ETIM-BMECAT (Das erstellen einer validen XML-Datei ist soweit auch kein Problem.) an unsere Kunden weitergeben. Dazu werden die Produkte in Klassen eingeteilt und verschiedene Eigenschaften haben feste Feature-Codes. Beispiel. HIER fängt aber mein Problem an. Irgendwie muß ich jetzt den einzelnen Eigenschaften auch diese Feature Codes bzw. zusätzlich auch noch bei einigen die Value-Codes zuordnen.

Ich hab wo anders den Tip bekommen, dass ich die ganzen Eigenschaften "auslagere"...Was mir aber etwas zu hoch ist... Hab jetzt zwar eine Zeit "rumprobiert" aber das Ergebnis ist jetzt imho nicht so wirklich gut..

Python:
class ProductType(models.Model):
    type_text = models.CharField(verbose_name=_('Produkt-Kategorie'), null=False, max_length=100)
    main_type = models.ForeignKey('self', verbose_name=_('Hauptkategorie'), null=True, on_delete=models.PROTECT)
    etim_class = models.ForeignKey('ETIMClass', verbose_name=_('ETIM Klasse'), null=True, blank=True,
on_delete=models.PROTECT)
    product_properties = models.ManyToManyField('Property')

class PropertyType(models.Model):
    type = models.CharField(verbose_name=_('Feldtyp'), max_length=25)
    
    def __repr__(self):
        return self.type

class ETIMClass(models.Model):
    code = models.CharField(verbose_name=_('ETIM Class Code'), max_length=25)
    short_description = models.CharField(verbose_name=_('Kurzbeschreibung'), max_length=100, default='')
    version = models.IntegerField(verbose_name='Version')
    etim_feature_codes = models.ManyToManyField('ETIMCode', through='ETIMFeatureCodeAdditions', verbose_name=_('ETIM Codes'))

class ETIMFeatureCode(models.Model):
    feature_code = models.CharField(verbose_name=_('ETIM Feature Code'), max_length=20)
    value_codes = models.ManyToManyField('ETIMValueCode', verbose_name=_('ETIM Value Code'))

class ETIMValueCode(models.Model):
    value_code = models.CharField(verbose_name=_('ETIM Value Code'), max_length=20)

class Property(models.Model):
    text = models.CharField(verbose_name=_('Eigenschafts-Text'), max_length=150, null=True, blank=True)
    etim_code = models.ForeignKey(ETIMFeatureCode, verbose_name=_('ETIM Code'), null=True, blank=True, on_delete=models.PROTECT)
    type = models.ForeignKey(PropertyType, verbose_name=_('Feldtyp'), on_delete=models.PROTECT, null=False)

class ProductProperty(models.Model):
    property = models.ForeignKey(Property, verbose_name=_('Eigenschaft'), on_delete=models.PROTECT, null=False)
    char_value = models.CharField()
    int_value = models.IntegerField()
    datetime_value = models.DateTimeField()
    bool_value = models.BooleanField()
    decimal_value = models.DecimalField(max_digits=7, decimal_places=3)
    etim_value_code = models.ForeignKey(ETIMValueCode, verbose_name=_('ETIM Value Code'), on_delete=models.PROTECT, null=True, blank=True)
    @property
    def get_value(self):
        if self.product_property.type == 'char':
            return self.char_value

class Product(models.Model
    product_properties = models.ManyToManyField(ProductProperty, verbose_name=_('Eigenschaften'))
    product_type = models.ForeignKey(ProductType, verbose_name=_('Produktkategorie'), on_delete=models.PROTECT)

    manufacturer = models.ForeignKey('Manufacturer', verbose_name=_('Hersteller'), null=True, blank=True, default=None, on_delete=models.PROTECT)

    trademark = models.ForeignKey('Trademark', verbose_name=_('Market'), on_delete=models.PROTECT, null=True, blank=True)

    harmonised_standards = models.ManyToManyField('HarmonisedStandards', verbose_name=_('gültige Normen'))

    customs_tariff_number = models.ForeignKey(CustomsTariffNumber, verbose_name=_('Zolltarifnummer'), null=True,
on_delete=models.PROTECT)

    integrated_products = models.ManyToManyField('Product',
verbose_name=_('integriertes Produkt (falls vorhanden)'))

    options = models.ManyToManyField('Product', through='OptionDetails', related_name='option_details')

    catalogue_page = models.ManyToManyField('CataloguePage', verbose_name=_('Katalog-Seite'), related_name='products')

    created_time = models.DateTimeField(verbose_name=_('Erstellungsdatum'), auto_now_add=True)
    updated_at = models.DateTimeField(verbose_name=_('Änderungsdatum'), auto_now=True)

    on_market_start_date = models.DateField(verbose_name=_('Startdatum'), null=True, blank=True)
    on_market_end_date = models.DateField(verbose_name=_('Enddatum'), null=True, blank=True)
    ...

Die ETIM-Klassen und damit ja auch die Feature-Codes sind ja mit dem ProductType verknüpft. Wie aber kann ich die Eigenschaften die keiner ETIM-Klasse zugeordnet sind einem ProductType zuordnen? Mein erster Gedanke wäre, dass ich in Property noch ein ForeignKey-Feld packe was auf ProductType verweist.
Das sieht aber irgendwie "falsch" aus, weil ich dann ja eigentlich 2 Verweise von ProductType auf Property hab (einmal über die ETIM-Klasse und die Feature-Codes und einmal dann direkt).
Hierdurch könnte ich mir dann z. B. die ganze Vererbungssache sparen ;-).

Hat vielleicht jemand eine "bessere" Idee? Oder kann ich das wirklich so machen ohne, dass es mir bald auf die Füße fällt?

Danke schonmal
 
Zurück
Oben