[PYTHON] Teilen Sie Daten mit Django in projektähnliche Einheiten

Vorwort

Artikelinhalt

Was du machst

――Es ist ein Werkzeug, um den Probenplan des Stücks zu unterstützen. ――Die im Titel erwähnte "projektähnliche Einheit" ist hier "Leistung". ――Verwalten Sie für jede Aufführung den Trainingsplan, die Schauspieler, Charaktere, Szenen usw. ---> GitHub Repository (Python 3.8.1, Django 3.0.3)

Artikelkonzept

――Ich konnte keine Probe von dem finden, was ich im Internet tun wollte, also habe ich selbst darüber nachgedacht und es implementiert. Teilt es »Wenn Sie einen besseren Weg kennen, wäre ich Ihnen dankbar, wenn Sie es mir sagen könnten.

Grundlegende Teile

Erstellen Sie zunächst "Leistungen" und "Leistungsbenutzer" und listen Sie die Leistungen auf, an denen der angemeldete Benutzer beteiligt ist.

Leistungsmodell (Projekteinheit)

Das einzige Feld ist "Name".

production/models.py


from django.db import models

class Production(models.Model):
    name = models.CharField('Leistungsname', max_length=50)

    def __str__(self):
        return self.name

Leistungsbenutzermodell

Es ist ein Benutzer für jede Aufführung. Der "ForeignKey" bezieht sich auf Leistungen und Benutzer (von Django verwaltete Benutzer) und legt Felder für Berechtigungen fest. Siehe hier für AUTH_USER_MODEL. In diesem Beispiel wird beim Löschen einer Leistung oder eines Benutzers auch der Leistungsbenutzer gelöscht.

production/models.py


from django.conf import settings

class ProdUser(models.Model):
    '''Benutzer und Berechtigungen für jede Aufführung
    '''
    production = models.ForeignKey(Production, verbose_name='Performance',
        on_delete=models.CASCADE)
    user = models.ForeignKey(settings.AUTH_USER_MODEL,
        verbose_name='Nutzer', on_delete=models.CASCADE)
    is_owner = models.BooleanField('Eigentum', default=False)
    is_editor = models.BooleanField('Bearbeitungsrechte', default=False)

Ansicht der Leistungsliste

Dies ist eine Liste der Leistungen, an denen der angemeldete Benutzer beteiligt ist. Ruft einen "Leistungsbenutzer" ab, sodass das Feld "Benutzer" der angemeldete Benutzer ist. Sie können es auch erhalten, indem Sie von self.request.user zurückverweisen.

Da der Leistungsname und die "Leistungs-ID" indirekt verwendet werden können, wird die Liste der Leistungen angezeigt. Mit anderen Worten, wenn Sie über die Leistungsbenutzerdaten verfügen, müssen Sie die Leistung nicht selbst abrufen.

production/views.py


from django.views.generic import ListView
from django.contrib.auth.mixins import LoginRequiredMixin
from .models import ProdUser

class ProdList(LoginRequiredMixin, ListView):
    '''Produktionslistenansicht
    
Das Modell ist ProdUser, da nur die Leistungen des angemeldeten Benutzers angezeigt werden.
    '''
    model = ProdUser
    template_name = 'production/production_list.html'
    
    def get_queryset(self):
        '''Filtern Sie die in der Liste angezeigten Datensätze
        '''
        #Holen Sie sich Ihren eigenen ProdUser
        prod_users = ProdUser.objects.filter(user=self.request.user)
        return prod_users

Wenn Sie ein geeignetes URL-Muster und eine Vorlage schreiben, fügen Sie auf dem Admin-Bildschirm "Leistung" und "Leistungsbenutzer" hinzu und melden Sie sich an. Eine Liste der Leistungen, für die diese Person der Benutzer ist, wird angezeigt.

Leistungsliste.png

-> Vorlage sieht so aus

Machen Sie eine neue Leistung

Das Task-Management-Tool ist wie das Erstellen eines neuen Projekts.

Anzeigen, um Aufführungen hinzuzufügen

Wenn Sie sich die Vorlage "Leistungsliste" oben ansehen, sehen Sie einen Link mit dem Namen "Neu". Ich drücke darauf, um die folgende Ansicht aufzurufen. Keine Parameter erforderlich.

production/views.py


from django.views.generic.edit import CreateView
from .models import Production

class ProdCreate(LoginRequiredMixin, CreateView):
    '''Zusätzliche Ansicht der Produktion
    '''
    model = Production
    fields = ('name',) #Das einzige Bearbeitungselement ist der Name
    template_name_suffix = '_create'
    success_url = reverse_lazy('production:prod_list') #Gehen Sie nach dem Hinzufügen zur Liste
    
    def form_valid(self, form):
        '''Nach bestandener Validierung
        '''
        #Holen Sie sich den gespeicherten Datensatz
        new_prod = form.save(commit=True)
        
        #Fügen Sie sich dem Performance-Benutzer als Eigentümer hinzu
        prod_user = ProdUser(production=new_prod, user=self.request.user,
            is_owner=True)
        prod_user.save()
        
        messages.success(self.request, str(new_prod) + "geschaffen.")
        return super().form_valid(form)
    
    def form_invalid(self, form):
        '''Wenn das Hinzufügen fehlschlägt
        '''
        messages.warning(self.request, "Konnte nicht ... Erstellen.")
        return super().form_invalid(form)

Die Seite ist einfach, da das Feld nur "Name" (Leistungsname) ist, der ordnungsgemäß angemeldete Benutzer jedoch zum "Leistungsbenutzer" wird und auch den Besitz erhält.

Neue Leistung.png

-> Vorlage sieht so aus

Jetzt kann der angemeldete Benutzer seine eigene "Leistung" erstellen.

Draufsicht auf jede Aufführung

Klicken Sie auf jede Leistung in der Leistungsliste, um zur Draufsicht auf diese Leistung zu gelangen. Von hier aus wird jede Aufführung eine andere Welt sein.

In der obigen Leistungslistenvorlage ist der Leistungsname der Link, der die Draufsicht auf diese "Leistung" öffnet.

production/templates/production/production_list.html


    <tr>
        <td>
            <a href="{% url 'rehearsal:rhsl_top' prod_id=item.production.id %}">
                {{ item.production }}</a>
        </td>
        <td>{{ item.is_owner }}</td>
        <td>{{ item.is_editor }}</td>
    </tr>

Ich habe die Draufsicht in einer Anwendung namens "Probe" erstellt, daher sieht der Link so aus. Dieser Link erfordert eine "Leistungs-ID" als Parameter (der Parametername im Code lautet "prod_id"). Da das angezeigte "Element" ein "Leistungsbenutzer" ist, übergeben Sie "item.production.id" als "Leistungs-ID".

Die Ansicht ist ein einfacher Menübildschirm.

rehearsal/views/views.py


from django.views.generic import TemplateView
from django.core.exceptions import PermissionDenied
from .view_func import *

class RhslTop(LoginRequiredMixin, TemplateView):
    '''Probe Top-Seite
    '''
    template_name = 'rehearsal/top.html'
    
    def get(self, request, *args, **kwargs):
        '''Handler, der die Anforderung zum Zeitpunkt der Anzeige erhalten hat
        '''
        #Erhalten Sie Leistungsbenutzer von Zugriffsinformationen und überprüfen Sie die Zugriffsrechte
        prod_user = accessing_prod_user(self)
        if not prod_user:
            raise PermissionDenied
        
        #Produktion als Attribut der Sicht haben
        self.production = prod_user.production
        
        return super().get(request, *args, **kwargs)

Der Grund dafür, dass das Objekt "Produktion" ("Leistung") als Attribut der Ansicht verwendet wird, besteht darin, in der Vorlage darauf zu verweisen.

accessing_prod_user () ist eine Funktion, die in einem anderen Modul namens view_func.py definiert und angemeldet ist. Wenn der Benutzer von der Benutzer der Leistung ist, wird das Objekt "Leistungsbenutzer" zurückgegeben.

rehearsal/views/view_func.py


from production.models import ProdUser

def accessing_prod_user(view, prod_id=None):
    '''Holen Sie sich den entsprechenden ProdUser aus den Zugriffsinformationen
    
    Parameters
    ----------
    view : View
Ansicht, von der Zugriffsinformationen abgerufen werden
    prod_id : int
Prod in URLconf_Geben Sie an, ob keine ID vorhanden ist
    '''
    if not prod_id:
        prod_id=view.kwargs['prod_id']
    prod_users = ProdUser.objects.filter(
        production__pk=prod_id, user=view.request.user)
    if len(prod_users) < 1:
        return None
    return prod_users[0]

Wenn der angemeldete Benutzer kein Leistungsbenutzer ist, gibt er "Keine" zurück, wodurch die Zugriffskontrolle ermöglicht wird.

Probe oben.png

-> Vorlagen sehen so aus

Es ist nur eine Liste von Links, aber jeder Link hat einen "prod_id" -Parameter.

Daten, die zur Leistung gehören

Nachdem wir die Grundlagen haben, um die Daten in Einheiten zu unterteilen, die als "Leistungen" bezeichnet werden, können wir die Daten verarbeiten, die zu jeder Leistung gehören.

Schauspieler Modell

Es sind die Daten der an der Aufführung beteiligten Akteure. Die zur Aufführung gehörenden Daten sollten einen "ForeignKey" namens "Produktion" haben, um zu entscheiden, zu welcher Aufführung sie gehören.

rehearsal/models.py


class Actor(models.Model):
    '''Darsteller
    '''
    production = models.ForeignKey(Production, verbose_name='Performance',
        on_delete=models.CASCADE)
    name = models.CharField('Name', max_length=50)
    short_name = models.CharField('Kurzbezeichnung', max_length=5, blank=True)
    
    class Meta:
        verbose_name = verbose_name_plural = 'Darsteller'
    
    def __str__(self):
        return self.name
    
    def get_short_name(self):
        return self.short_name or self.name[:3]

short_name (Kurzname) wird bei der Anzeige in Tabellenform verwendet.

Ansicht der Schauspielerliste

Diese Ansicht wechselt von der Draufsicht auf die Aufführung, indem Sie auf "Liste der Akteure" klicken. Natürlich werden nur die Akteure der Aufführung angezeigt, und es kann niemand anderes als der "Leistungsnutzer" der Aufführung gesehen werden.

Bevor wir uns die Liste der Schauspieler ansehen, werfen wir einen Blick auf den Link zur Liste der Schauspieler in der Draufsicht auf die Aufführung.

rehearsal/templates/rehearsal/top.html


<li><a href="{% url 'rehearsal:actr_list' prod_id=view.production.id %}">
Liste der Schauspieler</a></li>

Da wir das "Produktion" ("Leistungs" -Objekt) als Attribut der Ansicht hatten, können wir die "Leistungs-ID" in der Form "Ansicht.Produktion.ID" erhalten. Wenn Sie es an den Parameter "prod_id" übergeben, werden Sie zur Liste der Akteure für diese Aufführung weitergeleitet.

Schauen wir uns nun die Liste der Schauspieler an.

rehearsal/views/views.py


class ActrList(ProdBaseListView):
    '''Listenansicht des Schauspielers
    '''
    model = Actor
    
    def get_queryset(self):
        '''Filtern Sie die in der Liste angezeigten Datensätze
        '''
        prod_id=self.kwargs['prod_id']
        return Actor.objects.filter(production__pk=prod_id)\
            .order_by('name')

Die geerbte "ProdBaseListView" ist eine abstrakte Klasse zum Anzeigen einer Liste von Daten, die zu einer Aufführung gehören. Da wir andere Ansichten wie diese erstellen werden, haben wir eine abstrakte Klasse für die Zugriffskontrolle usw. zusammengestellt. Mal sehen, auch das.

rehearsal/views/views.py


class ProdBaseListView(LoginRequiredMixin, ListView):
    '''ListView Basisklasse zum Überprüfen von Berechtigungen
    '''
    def get(self, request, *args, **kwargs):
        '''Handler, um die Anforderung zum Zeitpunkt der Anzeige zu erhalten
        '''
        #Erhalten Sie Leistungsbenutzer von Zugriffsinformationen und überprüfen Sie die Zugriffsrechte
        prod_user = accessing_prod_user(self)
        if not prod_user:
            raise PermissionDenied
        
        #Haben Sie den Zugriff auf ProdUser als Attribut der Ansicht
        #Festlegen, ob der Vorlage eine Schaltfläche hinzugefügt werden soll oder nicht
        self.prod_user = prod_user
        
        return super().get(request, *args, **kwargs)
    
    def get_context_data(self, **kwargs):
        '''Ändern Sie die an die Vorlage übergebenen Parameter
        '''
        context = super().get_context_data(**kwargs)
        
        #Zurück-Button,Prod für Add-Button_ID einstellen
        context['prod_id'] = self.kwargs['prod_id']
        
        return context

Die Leistungs-ID (prod_id) ist in context enthalten, damit sie leicht aus der Vorlage referenziert werden kann. Sie können darauf verweisen, indem Sie view.prod_user.production.id eingeben, ohne es in context zu setzen, aber es ist lang.

-> Die Vorlage sieht folgendermaßen aus

Fügen wir auf dem Admin-Bildschirm einige "Schauspieler" hinzu, um die Liste der Schauspieler anzuzeigen.

Liste der Schauspieler.png

Anzeigen, um Schauspieler hinzuzufügen

Wenn Sie sich die Vorlage "Schauspielerliste" oben ansehen, sehen Sie einen Link namens "Hinzufügen". Und es wird nur Benutzern angezeigt, die die Leistung besitzen oder bearbeiten. Natürlich können Benutzer, die den Link nicht sehen können, die URL direkt im Browser öffnen. Daher ist auch für die Ansicht, zu der der Akteur hinzugefügt wird, eine Zugriffssteuerung erforderlich.

Wieder erstellen wir eine abstrakte Klasse ähnlich der obigen "ProdBaseListView". Schauen wir uns zuerst die abstrakte Klasse an.

rehearsal/views/views.py


class ProdBaseCreateView(LoginRequiredMixin, CreateView):
    '''CreateView Base-Klasse zum Überprüfen von Berechtigungen
    '''
    def get(self, request, *args, **kwargs):
        '''Handler, um die Anforderung zum Zeitpunkt der Anzeige zu erhalten
        '''
        #Überprüfen Sie die Bearbeitungsrechte, um Zugriff auf Benutzer zu erhalten
        prod_user = test_edit_permission(self)
        
        #Produktion als Attribut der Sicht haben
        #Anzeige als festes Element in der Vorlage
        self.production = prod_user.production
        
        return super().get(request, *args, **kwargs)
    
    def post(self, request, *args, **kwargs):
        '''Handler, um die Anfrage beim Speichern zu erhalten
        '''
        #Überprüfen Sie die Bearbeitungsrechte, um Zugriff auf Benutzer zu erhalten
        prod_user = test_edit_permission(self)
        
        #Produktion als Attribut der Sicht haben
        #Zum Einstellen in der Instanz beim Speichern
        self.production = prod_user.production
        
        return super().post(request, *args, **kwargs)
    
    def form_valid(self, form):
        '''Nach bestandener Validierung
        '''
        #Legen Sie die Produktion des Datensatzes fest, den Sie hinzufügen möchten
        instance = form.save(commit=False)
        instance.production = self.production
        
        messages.success(self.request, str(instance) + "Hinzugefügt.")
        return super().form_valid(form)
    
    def form_invalid(self, form):
        '''Wenn das Hinzufügen fehlschlägt
        '''
        messages.warning(self.request, "Es konnte nicht hinzugefügt werden.")
        return super().form_invalid(form)

test_edit_permission () ist eine Funktion, die vom angemeldeten Benutzer in view_func.py definiert wurde. Wenn Sie die Performance besitzen oder bearbeiten, wird der "Performance-Benutzer" zurückgegeben.

def test_edit_permission(view, prod_id=None):
    '''Überprüfen Sie die Bearbeitungsrechte
    
    Returns
    -------
    prod_user : ProdUser
Zugriff auf ProdUser mit Bearbeitungsrechten
    '''
    #Holen Sie sich Leistungsbenutzer aus Zugriffsinformationen
    prod_user = accessing_prod_user(view, prod_id=prod_id)
    if not prod_user:
        raise PermissionDenied
    
    #Verweigern Sie den Zugriff, wenn Sie keine Eigentums- oder Bearbeitungsrechte haben
    if not (prod_user.is_owner or prod_user.is_editor):
        raise PermissionDenied
    
    return prod_user

Die Berechtigungen werden sowohl beim Anzeigen der Ansicht (get -Methode) als auch beim Drücken der Schaltfläche" Hinzufügen "zur weiteren Verarbeitung ( post -Methode) überprüft.

Darüber hinaus implementiert diese abstrakte Klasse auch den allgemeinen Prozess "Wenn Sie Daten hinzufügen, die zu einer Leistung gehören, legen Sie die Leistung im Feld" Produktion "fest".

Schauen wir uns nun das Hinzufügen von Schauspielern an.

rehearsal/views/views.py


class ActrCreate(ProdBaseCreateView):
    '''Zusätzliche Ansicht des Schauspielers
    '''
    model = Actor
    fields = ('name', 'short_name')
    
    def get_success_url(self):
        '''Geben Sie das Übergangsziel dynamisch an, wenn das Hinzufügen erfolgreich ist
        '''
        prod_id = self.production.id
        url = reverse_lazy('rehearsal:actr_list', kwargs={'prod_id': prod_id})
        return url

Nach dem Hinzufügen kehren Sie zur Liste der Schauspieler "für diese Aufführung" zurück.

Schauspieler hinzufügen.png

-> Vorlage sieht so aus

Zusammenfassung

――Es ist ein Werkzeug, das den Probenplan des Stücks unterstützt, und ich habe mehrere "Aufführungen" gemacht und die Daten für jede Aufführung getrennt. ――Wir haben ein Modell namens "Performance User" erstellt, damit der Zugriff für jeden Benutzer (von Django verwalteter Benutzer) gesteuert werden kann.

Ich habe die Fortsetzung geschrieben

Recommended Posts

Teilen Sie Daten mit Django (3) in projektähnliche Einheiten.
Teilen Sie Daten mit Django in projektähnliche Einheiten
Teilen Sie Daten mit Django (2) in projektähnliche Einheiten.
Verwenden Sie Django, um Tweet-Daten zu speichern
Verwalten Sie Ihre Daten mit AWS RDS
Ihr eigener Twitter-Client mit Django
Teilen Sie Japanisch (Katakana) in Silben [Python]
Erstellen der ersten App mit Django Startprojekt
Generieren und veröffentlichen Sie Dummy-Bilddaten mit Django
Machen Sie Urlaubsdaten mit Pandas zu einem Datenrahmen
Trainieren Sie Stanford NER Tagger mit Ihren eigenen Daten
Internationalisierung mit Django
CRUD mit Django
Versuchen Sie, Twitter-Daten in SPAM und HAM zu unterteilen
Einmaliges Anmelden bei der Django-Anwendung mit AWS SSO
Teilen Sie den Datensatz (ndarray) mit NumPy in beliebige Proportionen