Ich wollte schon lange einen Artikel darüber schreiben, wie man auto populate field -Funktionalität für ein Django -Projekt schreibt. Dies ist eine sehr nützliche Funktion, mit der Sie den Inhalt anderer Modellfelder in Django ändern können, indem Sie einen Wert für ein Feld festlegen, das automatisch ausgefüllt wird.
Erstens, warum wird es benötigt? - Mit dieser Funktion können Sie die Größe des Codes an den Stellen reduzieren, an denen Sie andere Felder des Objekts neu schreiben müssen, wenn sie sich ändern. Das heißt, Sie müssen beispielsweise die Speichermethode nicht jedes Mal neu definieren, um ein Feld neu zu schreiben, falls sich andere Felder des Objekts ändern. Außerdem ist die Verwendung der automatischen Auffüllung im Grunde eine fortgeschrittenere und übersichtlichere Möglichkeit, Datenmodelle in Django zu verwalten.
Und auch ein ähnlicher Ansatz kann einige Probleme lösen und die Website verbessern.
Beschreibung der Vorgehensweise am Beispiel von Markdown-Feldern
Diesen Ansatz verwende ich beispielsweise auf dieser Seite zum Verfassen von Inhalten von Kommentaren und Artikeln und allgemein in allen Bereichen, in denen die Markdown -Syntax verwendet wird.
Wie es funktioniert?
- Alle Datenmodelle haben zwei Felder content und content_markdown . Das Feld content_markdown steuert den Inhalt des Felds content . Das heißt, in einer normalen Situation hat der Benutzer keinen Zugriff, um die Inhalte des Felds Inhalt zu bearbeiten, er bearbeitet immer nur das Feld Inhalt_Markdown .
- Der Benutzer bearbeitet beim Erstellen einer Nachricht das Feld content_markdown , das automatisch html -Code aus dem Markup markdown generiert und html in das Feld content schreibt .
Warum wird das benötigt?
Jeder entscheidet selbst, warum er Auto-Fill verwenden sollte. Beispielsweise können Sie automatisch ein Miniaturbild aus einem Quellbild generieren. Eine solche Funktionalität ist ideal für solche Aktionen.
Und speziell in meinem Fall stellte sich heraus, dass ich keine passende Funktionalität zum Generieren von HTML aus Markdown gefunden habe. Alles, was ich damals gefunden habe, waren Bibliotheken, die zur Laufzeit bei jedem Seitenaufruf mithilfe von Template-Tags HTML generierten. Und dieser Ansatz reduziert die Leistung der Website erheblich. Daher habe ich für mich entschieden, dass ich bereit bin, Speicherplatz für die Leistung der Website zu opfern. Denn eine Verzehnfachung der Seitenladegeschwindigkeit ist in manchen Fällen einer Verdopplung des belegten Speicherplatzes eindeutig vorzuziehen.
Implementierung
Ich werde einen vereinfachten MarkdownField -Code präsentieren, den Sie auf Ihrer Website verwenden könnten.
MarkdownField
MarkdownField erbt vom standardmäßigen TextField und nimmt als Argument den Namen des Felds, das für html -Inhalte verwendet werden soll. Dies ist das html_field -Argument.
Dieses Feld hat eine set_html -Methode, die dafür verantwortlich ist, html aus dem markdown -Markup zu generieren und auch den Wert im html -Feld des Inhalts festzulegen.
Der wichtige Punkt ist, die Methode set_html mit dem Signal pre_save in der Methode contribute_to_class zu verbinden. Eine frühere Version, die ich entwickelt habe, hatte den Nachteil, dass jedes Mal, wenn ein Objekt angefordert wurde, die html-generierende Methode aufgerufen wurde. Es war ein Fehler, den ich später entdeckt und auf ähnliche Weise korrigiert habe. Jetzt wird der Inhalt nur generiert, wenn das Objekt gespeichert wird.
# -*- coding: utf-8 -*- from django.db import models from django.db.models.signals import pre_save from .utils import MarkdownWorker class MarkdownField(models.TextField): """ This field save markdown text with auto-populate text to html field. This field must be used with second text field for html content. """ def set_html(self, instance=None, update_fields=None, **kwargs): value = getattr(instance, self.attname) if value and len(value) > 0: instance.__dict__[self.html_field] = MarkdownWorker(value).get_text() def contribute_to_class(self, cls, name, **kwargs): super().contribute_to_class(cls, name, **kwargs) pre_save.connect(self.set_html, sender=cls) def __init__(self, html_field=None, *args, **kwargs): self.html_field = html_field super().__init__(*args, **kwargs)
MarkdownWorker
Diese Klasse ist für das Generieren von HTML-Inhalten aus Markdown-Markup verantwortlich. In dieser Klasse können Sie beliebige zusätzliche Verarbeitungsarten aus HTML hinzufügen, um das gewünschte Endergebnis zu erhalten. Beispielsweise können Sie Links oder Bilder entfernen, von denen Sie glauben, dass der Benutzer sie nicht hinzufügen kann.
Beim Erstellen eines Objekts der Klasse MarkdownWorker wird der zu verarbeitende Text festgelegt und anschließend eine Methode aufgerufen, die den Text in html umwandelt.
Auch in meinem Fall werden Erweiterungen verwendet für:
- Tabellengenerierung
- Code-Unterstützung
- Transferzusätze
- Obere und untere Syntax
# -*- coding: utf-8 -*- import markdown class MarkdownWorker: """ Markdown converter. It will convert markdown text to html text """ def __init__(self, text): self.pre_markdown_text = text self.markdown_text = None self.make_html_from_markdown() def make_html_from_markdown(self): if self.pre_markdown_text: self.markdown_text = markdown.markdown( self.pre_markdown_text, extensions=['markdown.extensions.attr_list', 'markdown.extensions.tables', 'markdown.extensions.fenced_code', 'markdown.extensions.nl2br', 'superscript', 'subscript'], output_format='html5' ) def get_text(self): return self.markdown_text
Um all diese Funktionen zu unterstützen, müssen Sie die Bibliotheken installieren:
- Markdown
- MarkdownSubscript
- MarkdownHochgestellt
Vielleicht auch beautifulsoup4 , oder es wird in Abhängigkeiten installiert, aber ehrlich gesagt, ich erinnere mich nicht.
Anwendung
Und jetzt wenden wir dieses Feld im Datenmodell an.
Wir haben ein Post-Modell, das die Felder enthält:
- Benutzer - Fremdschlüssel pro Benutzer
- Inhalt - Feld, das HTML-Inhalt enthält
- content_markdown - das Feld, in dem der Markdown-Text mit anschließender Generierung von HTML-Text gespeichert wird. Dabei sieht man, dass ihm das Argument html_field='content' übergeben wird, das angibt, mit welchem Feld das MarkdownField arbeiten soll.
# -*- coding: utf-8 -*- from django.conf import settings from django.db import models from django.utils.translation import gettext_lazy as _ from .fields import MarkdownField class Post(models.Model): user = models.ForeignKey(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE) content = models.TextField(verbose_name=_('Description')) content_markdown = MarkdownField(verbose_name=_('Description - Markdown'), html_field='content')
Fazit
Auf diese Weise können Sie Ihrer Website Markdown-Felder hinzufügen, die automatisch HTML-Inhalte generieren.
Sie haben jetzt Unterstützung für ausgefallene Markdown-Syntax auf Ihrer Website, die automatisch HTML-Inhalte generiert.