Generic Relations (?!): Unbestimmte Anzahl an Inhalten sollen hinzugefügt werden

Django, Flask, Bottle, WSGI, CGI…
Antworten
sagro
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2018, 20:50

Hallo,
mit Django (Version 2) möchte ich eine App erstellen um zu verschiedenen Kameramodellen verschiedenste Dokumente zu erfassen (Texte, Bilder, Dateien). Von Anfang an ist nicht klar, wieviele Texte, Bilder und Dateien je Kamera hinzugefügt werden sollen. Daher hatte ich überlegt das Ganze als Generic Relation zu implementieren.

Nun habe ich in der models.py eine Klasse für "Device", eine für "Text", "File" und "Image" als auch ein model als generic relations namens "Inhalt", die wie folgt aussieht:

Code: Alles auswählen

class Inhalt(models.Model):
    device = models.ForeignKey(Device, related_name='inhalte', on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    info = models.CharField(max_length=200, blank=True)
    # Generic Relations Fields:
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
                                     limit_choices_to={'model__in': ('text', 'image', 'file')})
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')
...
Nun kann ich ein "Objekt" vom Typ Device erstellen und dann auch verschiedene Inhalte in Form von Text, Image oder File. Wenn ich dann im (Admin Bereich) auf "Inhalte" gehe, kann ich zu meinem Device (im Beispiel "Mamiya RB 67") die verschiedenen Inhalte hinzufügen. Und jetzt zum Problem: Ich sehe zwar die "object_id" (vom Text, File oder Image) kann aber nicht ersehen, welches Objekt sich dahinter verbirgt:

Bild

Theoretisch kann ich auch eine object_id wählen, die "leer" ist, also die es noch nicht gibt. Es kommt keine Fehlermeldung, sondern es ist dann einfach nichts hinterlegt beim content_object (siehe obersten Eintrag):

Bild

Wie kann ich mir im Admin Bereich anzeigen lassen, was sich für ein Objekt hinter der objekt_id verbirgt?
Aus der Dokumentation werde ich nicht schlauer und im Netz suche ich schon seit Tagen... Tipps?

Oder gibt es eine andere Möglichkeit mein Ansinnen zu realisieren?

Grüße
sagro
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

also wenn ich das richtig verstehe, ist das doch ein normale one-to-many Beziehung. Jede Kamera gibt es 1x und jeder Kamera können n Dokumente zugeordnet sein.

Bzgl. der Anzeige: du muss in deiner Modell-Klasse noch die __str__-Methode definieren. Darin wird festgelegt, welcher Text (also welche Attribute) angezeigt werden.

Gruß, noisefloor
sagro
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2018, 20:50

Hallo,
Danke für die Antwort, und ja, ich habe in den Models i.d.R. die Methode eingebunden (bei Text, File, Image und Inhalt) so oder so ähnlich:

Code: Alles auswählen

    def __str__(self):
        return '{}##{}##{}##{}'.format(self.id, self.owner, self.title, self.file)
Aber das ändert nichts an meinem eigentlichen Problem, dass (wie oben im Beitrag im 1.Bild zu sehen) ich "nur" die object id sehe. Sprich, habe ich diverse Inhalte als Text, File oder Image erstellt, muss ich erst dort nachsehen, was sich hinter der ID verbirgt. Ansonsten "stochere" ich im Dunkeln.

Als weiteren Versuch habe ich Inhalt als GenericTabularInline in der admin.py angelegt und in Device als inline eingebunden. Aber dann fehlen sogar die Felder content_type und object_id (siehe Screenshot):

Bild

Tja, so wirklich weiter komme ich nicht... Zudem sind die meißten "Tutorials" zu Generic Relations eher um "Likes" zu vergeben oder zu Beiträgen "Up- oder Downvotes" zu vergeben...Anscheinend werden Generic Relations doch nicht so häufig genutzt - mir schwant langsam warum ;O)

Vielleicht gibt es auch eine andere Lösungsstrategie, um unterschiedlichste Inhalte in verschiedener Anzahl einzubinden?

Grüße
sagro
Benutzeravatar
noisefloor
User
Beiträge: 3854
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

zeigt mal bitte alle relevanten Models. Ich glaube, der DB-Entwurf ist nicht optimal...

Gruß, noisefloor
sagro
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2018, 20:50

Hallo,
hier die models:

Code: Alles auswählen

class Device(models.Model):
    owner = models.ForeignKey(User, on_delete=models.CASCADE)
    name = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    description = models.TextField(blank=True)


    def __str__(self):
        return self.name
        
 class Inhalt(models.Model):
    device = models.ForeignKey(Device, related_name='inhalte', on_delete=models.CASCADE)
    created = models.DateTimeField(auto_now_add=True)
    info = models.CharField(max_length=200, blank=True)
    # Generic Relations Fields:
    content_type = models.ForeignKey(ContentType, on_delete=models.CASCADE,
                                     limit_choices_to={'model__in': ('text', 'image', 'file')})
    object_id = models.PositiveIntegerField()
    content_object = GenericForeignKey('content_type', 'object_id')

    def __str__(self):
        return '{}##{}##{}##{}'.format(self.created, self.info, self.content_type, self.object_id)


class Text(models.Model):
    owner = models.ForeignKey(User, related_name='text_related', on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    info = models.TextField(blank=True)

    def __str__(self):
        return '{}##{}##{}##{}'.format(self.id, self.owner, self.title, self.info)


class File(models.Model):
    owner = models.ForeignKey(User, related_name='file_related', on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    file = models.FileField(upload_to='files/')

    def __str__(self):
        return '{}##{}##{}##{}'.format(self.id, self.owner, self.title, self.file)


class Image(models.Model):
    owner = models.ForeignKey(User, related_name='image_related', on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    created = models.DateTimeField(auto_now_add=True)
    updated = models.DateTimeField(auto_now=True)
    file = models.FileField(upload_to='image/')

    def __str__(self):
        return '{}##{}##{}##{}'.format(self.id, self.owner, self.title, self.file)
       
Grüße
sagro
sagro
User
Beiträge: 6
Registriert: Freitag 19. Oktober 2018, 20:50

So, weitere Recherche im Netz hat mich einer Lösung näher gebracht. Follgender Blogbeitrag ist genau das was ich suche:
http://blog.yawd.eu/2011/admin-site-wi ... s-django/

Weiter unten sieht man, wie es aussehen soll. Nun muss das Ganze nur noch umgeschrieben werden. Der Post ist aus 2011 und der Import in forms.py "from widgets import ContentTypeSelect" funktioniert nicht...

Grüße
sagro
Antworten