Frage

Lassen Sie uns sagen ich folgendes Django Modell haben:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)

Jedes Etikett hat eine ID-Nummer, um den Beschriftungstext und eine Abkürzung. Jetzt will ich diese Etiketten in andere Sprachen übersetzbar haben. Was ist der beste Weg, dies zu tun?

Wie ich es sehe, ich habe ein paar Optionen:

1: Fügen Sie die Übersetzungen als Felder auf dem Modell:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label_english = models.CharField(max_length=255)
    abbreviation_english = models.CharField(max_length=255)
    label_spanish = models.CharField(max_length=255)
    abbreviation_spanish = models.CharField(max_length=255)

Das ist offensichtlich nicht ideal ist -. Hinzufügen erfordert Sprachen das Modell bearbeiten, der richtige Feldname ist abhängig von der Sprache

2: Fügen Sie die Sprache als Fremdschlüssel:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')

Das ist viel besser, jetzt habe ich für alle Etiketten mit einer bestimmten Sprache fragen, und werfen sie in einen dict:

labels = StandardLabel.objects.filter(language=1)
labels = dict((x.pk, x) for x in labels)

Aber das Problem hier ist, dass die Etiketten dict gemeint ist, eine Nachschlagtabelle sein, etwa so:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].label

Welche funktioniert nicht, wenn es eine Zeile pro Etikett ist, möglicherweise mit mehreren Sprachen für ein einzelnes Etikett. Zu lösen, dass man, ich brauche ein anderes Feld:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    group_id = models.IntegerField(db_index=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')
    class Meta:
        unique_together=(("group_id", "language"),)
#and I need to group them differently:
labels = StandardLabel.objects.filter(language=1)
labels = dict((x.group_id, x) for x in labels)

3: Wurfbeschriftungstext heraus in ein neues Modell:

class StandardLabel(models.Model):
    id = models.AutoField(primary_key=True)
    text = models.ManyToManyField('LabelText')

class LabelText(models.Model):
    id = models.AutoField(primary_key=True)
    label = models.CharField(max_length=255)
    abbreviation = models.CharField(max_length=255)
    language = models.ForeignKey('languages.Language')

labels = StandardLabel.objects.filter(text__language=1)
labels = dict((x.pk, x) for x in labels)

Aber dann funktioniert das nicht, und verursacht eine Datenbank jedes Mal traf ich die Beschriftung des Text verweisen:

x = OtherObjectWithAReferenceToTheseLabels.object.get(pk=3)
thelabel = labels[x.labelIdNumber].text.get(language=1)

Ich habe implementiert Option 2, aber ich finde es sehr hässlich - Ich mag nicht das group_id Feld, und ich kann mich nichts, es besser zu nennen. Darüber hinaus StandardLabel wie ich verwende es ein abstraktes Modell, das ich Unterklasse auf unterschiedliche Etikettensätze für verschiedene Felder zu erhalten.

Ich nehme an, dass, wenn die Option 3 / did nicht / die Datenbank getroffen, es ist, was ich wählen würde. Ich glaube, dass das eigentliche Problem ist, dass die Filter text__language=1 nicht die LabelText Instanzen zwischenspeichert und so die DB getroffen wird, wenn ich text.get(language=1)

Was sind Ihre Gedanken dazu? Kann mir jemand eine sauberere Lösung empfehlen?

Bearbeiten :. Nur deutlich zu machen, werden diese Etiketten nicht bilden, so dass die Django Internationalisierung System hilft nicht

War es hilfreich?

Lösung

Ich würde viel lieber ein Feld pro Sprache als ein neues Modell Instanz pro Sprache hinzuzufügen. Es tut Schema Änderung erforderlich, wenn Sie eine neue Sprache hinzufügen, aber das ist nicht schwer, und wie oft wollen Sie Sprachen hinzufügen? In der Zwischenzeit wird es geben Sie eine bessere Datenbank-Performance (ohne Zusatz von beitritt oder Indizes) und Sie müssen Ihre Abfragelogik mit Übersetzung Sachen nicht verhunzen; halten sie alle in den Vorlagen, wo es hingehört.

Noch besser ist, verwenden Sie eine wiederverwendbare app wie django-transmeta oder django-modeltranslation , die diese dumme einfach macht und fast vollständig transparent sein.

Andere Tipps

Eine weitere Option, die Sie sich anschauen sollen, auf dem Anwendungsdesign natürlich abhängig, ist die Verwendung von Djangos Internationalisierung Funktionen zu machen. Der Ansatz verwendet sie ist durchaus üblich, auf den Ansatz in der Desktop-Software gefunden.

Ich sehe die Frage bearbeitet wurde eine Referenz hinzufügen Internationalisierung Django, so dass Sie darüber wissen, aber die intl Funktionen in Django zu viel mehr gelten als nur Forms; es touchs ziemlich viel, und braucht nur ein paar kleine Änderungen an Ihrem App-Design.

Ihre Dokumente sind hier: http: //docs.djangoproject .com / de / dev / Themen / i18n / # Themen-i18n

Die Idee ist, dass Sie Ihr Modell definieren, als ob es nur eine Sprache. Mit anderen Worten, macht überhaupt keinen Bezug auf Sprache, und nur setzen, sagen sie, Englisch im Modell.

So:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)

Ich weiß, das sieht aus wie Sie völlig die Sprache Problem geworfen haben, aber Sie haben es tatsächlich nur verlagert. Anstelle der Sprache in Ihrem Datenmodell zu sein, haben Sie es zu der Ansicht gedrückt wird.

Die django Internationalisierung Funktionen können Sie Text Übersetzungsdateien erzeugen, und bietet eine Reihe von Funktionen für Text aus dem System in Dateien ziehen. Das ist eigentlich ziemlich nützlich, weil es Ihnen erlaubt, einfache Dateien auf Ihren Übersetzer zu senden, die einfacher, ihre Arbeit macht. Hinzufügen eine neue Sprache ist so einfach wie die Datei in eine neue Sprache übersetzt zu bekommen.

Die Übersetzungsdateien definieren das Etikett aus der Datenbank und eine Übersetzung für diese Sprache. Es gibt Funktionen für den Umgang mit der sprachlichen Übersetzung dynamisch zur Laufzeit für die Modelle, admin Ansichten, JavaScript und Vorlagen.

Zum Beispiel in einer Vorlage, könnte man so etwas tun:

<b>Hello {% trans "Here's the string in english" %}</b>

oder im Hinblick auf Code, könnten Sie tun:

# See docs on setting language, or getting Django to auto-set language
s = StandardLabel.objects.get(id=1)
lang_specific_label = ugettext(s.label)

Natürlich, wenn Sie Ihre App alles über die Eingabe neuer Sprachen on the fly ist, dann kann dieser Ansatz nicht für Sie arbeiten. Noch einen Blick auf die Internationalisierung Projekt haben, wie Sie entweder in der Lage sein kann, es zu benutzen „wie er ist“, oder zu einer django-geeignete Lösung inspiriert werden, die Arbeit für Ihre Domain hat.

Ich würde die Dinge so einfach wie möglich. Das Nachschlagen wird schneller und der Code Reiniger mit etwas wie folgt aus:

class StandardLabel(models.Model):
    abbreviation = models.CharField(max_length=255)
    label = models.CharField(max_length=255)
    language = models.CharField(max_length=2)
    # or, alternately, specify language as a foreign key:
    #language = models.ForeignKey(Language)

    class Meta:
        unique_together = ('language', 'abbreviation')

Dann Abfrage basierend auf Abkürzung und Sprache:

l = StandardLabel.objects.get(language='en', abbreviation='suite')

Auch wenn ich mit Daniels Lösung gehen würde, hier ist eine Alternative von dem, was ich von Ihren Kommentaren verstanden habe:

Sie können eine XMLField oder JSONField zu speichern Sie Ihre Sprache / Übersetzungspaare. Dies würde es ermöglichen, Ihre Objekte Ihre Etiketten Referenzierung einen einzigen id für alle Übersetzungen zu verwenden. Und dann können Sie eine benutzerdefinierten Manager Methode eine spezifische Übersetzung zu nennen:

Label.objects.get_by_language('ru', **kwargs)

Oder eine etwas saubere und etwas kompliziertere Lösung, die gut mit admin spielt wäre die XMLField mit zum Label Modell Viele-zu-Eins-Beziehung zu einem anderen Modell denormalize. Gleiche API, sondern XML Parsen könnte es ähnliche Modelle abfragen.

Für beide Vorschläge gibt es ein einzelnes Objekt in dem Benutzer eines Etiketts an markierten Punkt.

Ich würde über die Anfragen nicht zu viele Sorgen, Django-Caches Abfragen und DBMS wahrscheinlich überlegen Caching haben würde auch dort.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top