Narzędzia użytkownika

Narzędzia witryny


pl:python:dbaudiocd

Różnice

Różnice między wybraną wersją a wersją aktualną.

Odnośnik do tego porównania

Poprzednia rewizja po obu stronachPoprzednia wersja
Nowa wersja
Poprzednia wersja
pl:python:dbaudiocd [2023/11/27 14:28] – [Dodanie modelu MusicAlbum] sindappl:python:dbaudiocd [2024/01/05 13:22] (aktualna) – [Modyfikacja w pliku cdacd/cdacd/settings.py] sindap
Linia 76: Linia 76:
 LANGUAGE_CODE = 'pl-pl' LANGUAGE_CODE = 'pl-pl'
 TIME_ZONE = 'Europe/Warsaw'</code> TIME_ZONE = 'Europe/Warsaw'</code>
 +
 +Poniżej przykład struktury pliku ''apps.py'':
 +
 +<code python apps.py>
 +from django.apps import AppConfig
 +
 +
 +class DbcdappConfig(AppConfig):
 +    default_auto_field = 'django.db.models.BigAutoField'
 +    name = 'dbcdapp'
 +</code>
 +
 +W tym przykładzie ''dbcdapp.apps.DbcdappConfig'' składa się z wartości zmiennej ''name''. Następnie po kropce nazwa modułu bibliotece django czyli ''apps'' oraz nazwa klasy ''DbcdappConfig''.
 +
 +Warto wspomnieć, że w pliku można nadać bardziej ludzką nazwę aplikacji:
 +
 +<code python apps.py>
 +from django.apps import AppConfig
 +
 +
 +class DbcdappConfig(AppConfig):
 +    default_auto_field = 'django.db.models.BigAutoField'
 +    name = 'dbcdapp'
 +    verbose_name = 'Moja Aplikacja'
 +</code>
  
 ===== Pierwsze uruchomienie serwera ===== ===== Pierwsze uruchomienie serwera =====
Linia 886: Linia 911:
             raise ValidationError("Numer kolejny disku nie może być większy od całkowitej ilości dysków w albumie.")             raise ValidationError("Numer kolejny disku nie może być większy od całkowitej ilości dysków w albumie.")
 </code> </code>
 +
 +===== Dodanie MusicAlbum w panelu admina =====
 +
 +<code python admin.py>
 +from django.contrib import admin
 +from .models import Song, Artist, MusicAlbum
 +from django import forms
 +
 +class SongAdminForm(forms.ModelForm):
 +    class Meta:
 +        model = Song
 +        fields = ['song_title', 'release_year', 'duration']
 +
 +    def __init__(self, *args, **kwargs):
 +        super().__init__(*args, **kwargs)
 +
 +        # Dodaj placeholder do pola duration
 +        self.fields['duration'].widget.attrs['placeholder'] = 'HH:MM:SS'
 +
 +        # Dodaj placeholder do pola rok
 +        self.fields['release_year'].widget.attrs['placeholder'] = 'Wprowadź rok wydania'
 +
 +    def clean_release_year(self):
 +        release_year = self.cleaned_data['release_year']
 +
 +        # Sprawdź, czy rok wydania zawiera dokładnie cztery cyfry
 +        if release_year and (len(str(release_year)) != 4 or not str(release_year).isdigit()):
 +            raise forms.ValidationError('Rok wydania musi składać się z dokładnie czterech cyfr.')
 +
 +        # Sprawdź, czy rok wydania nie jest większy niż rok utworzenia
 +        if release_year:
 +            created_at_year = self.instance.created_at.year if self.instance and self.instance.created_at else timezone.now().year
 +            if int(release_year) > created_at_year:
 +                raise forms.ValidationError("Rok wydania nie może być większy niż rok utworzenia.")
 +
 +        return release_year
 +
 +    def clean_duration(self):
 +        duration = self.cleaned_data['duration']
 +
 +        # Sprawdzamy, czy duration ma poprawny format (HH:MM:SS)
 +        if duration.total_seconds() < 0:
 +            raise forms.ValidationError('Niewłaściwy format czasu. Użyj wartości nieujemnej.')
 +
 +        # Sprawdzamy, czy duration nie przekracza 01:59:59
 +        if duration.total_seconds() > 7199:
 +            raise forms.ValidationError('Maksymalna długość to 1 godzina, 59 minut i 59 sekund.')
 +
 +        return duration
 +
 +class ArtistInline(admin.TabularInline):
 +    model = Artist.songs.through  # To jest model pośredniczący w relacji wiele-do-wielu
 +    extra = 1
 +
 +@admin.register(Song)
 +class SongAdmin(admin.ModelAdmin):
 +    form = SongAdminForm
 +    list_display = ('song_title', 'release_year', 'duration', 'created_at', 'modified_at')
 +    list_filter = ('release_year',)
 +    search_fields = ('song_title',)
 +    readonly_fields = ['created_at', 'modified_at']
 +    inlines = [ArtistInline]
 +
 +@admin.register(Artist)
 +class ArtistAdmin(admin.ModelAdmin):
 +    list_display = ('artist_name',)
 +    search_fields = ['artist_name']
 +    filter_horizontal = ('songs',)
 +
 +@admin.register(MusicAlbum)
 +class MusicAlbumAdmin(admin.ModelAdmin):
 +    # form = MusicAlbumAdminForm
 +    list_display = ('album_title', 'disc_number', 'total_disc')
 +    search_fields = ['album_title']
 +    filter_horizontal = ('songs',)
 +</code>
 +
 +===== Zmiana typu pola release_year w modelu Song =====
 +Po przeanalizowaniu w przypadku modelu ''Song'' i pola ''release_year'' wydaje się bardziej uzasadnione użycie pola ''PositiveIntegerField''. Wprowadzamy więc stosowane modyfikacje. Uwzględniamy, że rok musi się składać z ''4'' cyfr i że rok wydania nie może być późniejszy od daty tworzenia wpisu. W zasadzie jeżeli wpiszemy minimalną dozwoloną wartość ''1000'' dla pola ''release_year'' walidacja czterech cyfr jest zbędna ale zostawiamy ją dla bajeru. Walidację też przenosimy z pliku ''admin.py'' do ''models.py''. Wynik będzie taki, że będzie ona działać dla panelu admin jak również na stronie użytkownika.\\
 +\\
 +Poniżej pliki po modyfikacji.
 +<code python models.py>
 +from django.db import models
 +from django.utils import timezone
 +from .verbose_names import verbose_names
 +from django.core.validators import MinValueValidator, MaxValueValidator, ValidationError
 +
 +# Funkcja walidacyjna dla pola release_year
 +def validate_release_year(value):
 +    current_year = timezone.now().year
 +    if not str(value).isdigit() or len(str(value)) != 4:
 +        raise ValidationError("Rok wydania musi się składać z czterech cyfr")
 +    if value > current_year:
 +        raise ValidationError("Rok wydania nie może być większy od roku tworzenia wpisu.")
 +
 +class Song(models.Model):
 +    song_title = models.CharField(max_length=200, verbose_name=verbose_names['song_title'])
 +    release_year = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1000),validate_release_year],verbose_name=verbose_names['release_year'])
 +    duration = models.DurationField(null=True, verbose_name=verbose_names['duration'])
 +    created_at = models.DateTimeField(default=timezone.now, verbose_name=verbose_names['created_at'], editable=False)
 +    modified_at = models.DateTimeField(auto_now=True, verbose_name='Data ostatniej modyfikacji')
 +
 +    class Meta:
 +        verbose_name = 'Song'
 +        verbose_name_plural = 'Songs'
 +        unique_together = ('song_title', 'release_year')
 +
 +    def __str__(self):
 +        return f"{self.song_title}, ({self.release_year})"
 +
 +class Artist(models.Model):
 +    artist_name = models.CharField(max_length=255, verbose_name=verbose_names['artist_name'])
 +    songs = models.ManyToManyField(Song)
 +
 +    class Meta:
 +        verbose_name = 'Artist'
 +        verbose_name_plural = 'Artists'
 +
 +    def __str__(self):
 +        return self.artist_name
 +
 +class MusicAlbum(models.Model):
 +    MEDIUM_TYPE = (
 +        ('audiocd', 'Audio CD'),
 +        ('audiocd_r', 'Audio CD-R'),
 +        ('sacd', 'Super Audio CD')
 +    )
 +    album_title = models.CharField(max_length=255, verbose_name=verbose_names['album_title'])
 +    medium_type = models.CharField(max_length=50, choices=MEDIUM_TYPE, verbose_name=verbose_names['medium_type'])
 +    disc_number = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1),
 +                    MaxValueValidator(50)],verbose_name=verbose_names['disk_number']
 +    )
 +    total_disc = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1),
 +                    MaxValueValidator(50)],verbose_name=verbose_names['total_disk']
 +    )
 +    songs = models.ManyToManyField(Song)
 +
 +    def __str__(self):
 +        return f"{self.album_title} - Album {self.disc_number}"
 +
 +    def clean(self):
 +        if self.disc_number and self.total_disc and self.disc_number > self.total_disc:
 +            raise ValidationError("Numer kolejny disku nie może być większy od całkowitej ilości dysków w albumie.")
 +</code>
 +<code python admin.py>
 +from django.contrib import admin
 +from .models import Song, Artist, MusicAlbum
 +from django import forms
 +
 +class SongAdminForm(forms.ModelForm):
 +    class Meta:
 +        model = Song
 +        fields = ['song_title', 'release_year', 'duration']
 +
 +    def __init__(self, *args, **kwargs):
 +        super().__init__(*args, **kwargs)
 +
 +        # Dodaj placeholder do pola duration
 +        self.fields['duration'].widget.attrs['placeholder'] = 'HH:MM:SS'
 +
 +        # Dodaj placeholder do pola rok
 +        self.fields['release_year'].widget.attrs['placeholder'] = 'Wprowadź rok wydania'
 +
 +
 +    def clean_duration(self):
 +        duration = self.cleaned_data['duration']
 +
 +        # Sprawdzamy, czy duration ma poprawny format (HH:MM:SS)
 +        if duration.total_seconds() < 0:
 +            raise forms.ValidationError('Niewłaściwy format czasu. Użyj wartości nieujemnej.')
 +
 +        # Sprawdzamy, czy duration nie przekracza 01:59:59
 +        if duration.total_seconds() > 7199:
 +            raise forms.ValidationError('Maksymalna długość to 1 godzina, 59 minut i 59 sekund.')
 +
 +        return duration
 +
 +class ArtistInline(admin.TabularInline):
 +    model = Artist.songs.through  # To jest model pośredniczący w relacji wiele-do-wielu
 +    extra = 1
 +
 +@admin.register(Song)
 +class SongAdmin(admin.ModelAdmin):
 +    form = SongAdminForm
 +    list_display = ('song_title', 'release_year', 'duration', 'created_at', 'modified_at')
 +    list_filter = ('release_year',)
 +    search_fields = ('song_title',)
 +    readonly_fields = ['created_at', 'modified_at']
 +    inlines = [ArtistInline]
 +
 +@admin.register(Artist)
 +class ArtistAdmin(admin.ModelAdmin):
 +    list_display = ('artist_name',)
 +    search_fields = ['artist_name']
 +    filter_horizontal = ('songs',)
 +
 +@admin.register(MusicAlbum)
 +class MusicAlbumAdmin(admin.ModelAdmin):
 +    # form = MusicAlbumAdminForm
 +    list_display = ('album_title', 'disc_number', 'total_disc')
 +    search_fields = ['album_title']
 +    filter_horizontal = ('songs',)
 +</code>
 +
 +===== Zmiana organizacji modeli =====
 +
 +Do tego momentu utwory były bezpośrednio dodawane do albumu. Skoro album może się składać z kilku nośników (płyt) dodajemy kolejny model 'StorageMedium' gdzie będziemy dodawać utwory a dopiero dane medium do albumu.
 +
 +===== Założenia w pliku modeli po modyfikacji =====
 +
 +<code python models.py>
 +from django.db import models
 +from django.utils import timezone
 +from .verbose_names import verbose_names
 +from django.core.validators import MinValueValidator, MaxValueValidator, ValidationError
 +
 +# Funkcja walidacyjna dla pola release_year
 +def validate_release_year(value):
 +    current_year = timezone.now().year
 +    if not str(value).isdigit() or len(str(value)) != 4:
 +        raise ValidationError("Rok wydania musi się składać z czterech cyfr")
 +    if value > current_year:
 +        raise ValidationError("Rok wydania nie może być większy od roku tworzenia wpisu.")
 +
 +class Song(models.Model):
 +    song_title = models.CharField(max_length=200, verbose_name=verbose_names['song_title'])
 +    release_year = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1000),validate_release_year],verbose_name=verbose_names['release_year'])
 +    duration = models.DurationField(null=True, verbose_name=verbose_names['duration'])
 +    created_at = models.DateTimeField(default=timezone.now, verbose_name=verbose_names['created_at'], editable=False)
 +    modified_at = models.DateTimeField(auto_now=True, verbose_name='Data ostatniej modyfikacji')
 +
 +    class Meta:
 +        verbose_name = 'Song'
 +        verbose_name_plural = 'Songs'
 +        unique_together = ('song_title', 'release_year')
 +
 +    def __str__(self):
 +        return f"{self.song_title}, ({self.release_year})"
 +
 +class Artist(models.Model):
 +    artist_name = models.CharField(max_length=255, verbose_name=verbose_names['artist_name'])
 +    songs = models.ManyToManyField(Song)
 +
 +    class Meta:
 +        verbose_name = 'Artist'
 +        verbose_name_plural = 'Artists'
 +
 +    def __str__(self):
 +        return self.artist_name
 +
 +class MusicAlbum(models.Model):
 +    album_title = models.CharField(max_length=255, verbose_name=verbose_names['album_title'])
 +    total_disc = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1),
 +                    MaxValueValidator(50)], verbose_name=verbose_names['total_disk']
 +    )
 +    def __str__(self):
 +        return f"{self.album_title}"
 +
 +class StorageMedium(models.Model):
 +    MEDIUM_TYPE = (
 +        ('audiocd', 'Audio CD'),
 +        ('audiocd_r', 'Audio CD-R'),
 +        ('sacd', 'Super Audio CD')
 +    )
 +    albums_title = models.ForeignKey('MusicAlbum', on_delete=models.PROTECT,
 +                                     verbose_name=verbose_names['albums_title'], related_name='musicalbum')
 +    disc_title = models.CharField(max_length=255, verbose_name=verbose_names['disc_title'])
 +    medium_type = models.CharField(max_length=50, choices=MEDIUM_TYPE, verbose_name=verbose_names['medium_type'])
 +    disc_number = models.PositiveIntegerField(
 +        validators=[MinValueValidator(1),
 +                    MaxValueValidator(50)], verbose_name=verbose_names['disk_number']
 +    )
 +    songs = models.ManyToManyField(Song, verbose_name=verbose_names['songs'])
 +
 +    class Meta:
 +        unique_together = ('albums_title', 'disc_number')
 +
 +    def clean(self):
 +        super().clean()
 +
 +        if self.disc_number > self.albums_title.total_disc:
 +            raise ValidationError({'disc_number':'Numer dysku nie może być większy niż ilość dysków w albumie.'})
 +
 +    def __str__(self):
 +        return f"W albumie \"{self.albums_title}\" płyta pt. \"{self.disc_title}\" nośnik nr {self.disc_number}"
 +</code>
 +
 +===== Założenia w pliku admin po modyfikacji =====
 +
 +<code python admin.py>
 +from django.contrib import admin
 +from .models import Song, Artist, MusicAlbum, StorageMedium
 +from django import forms
 +
 +class SongAdminForm(forms.ModelForm):
 +    class Meta:
 +        model = Song
 +        fields = ['song_title', 'release_year', 'duration']
 +
 +    def __init__(self, *args, **kwargs):
 +        super().__init__(*args, **kwargs)
 +
 +        # Dodaj placeholder do pola duration
 +        self.fields['duration'].widget.attrs['placeholder'] = 'HH:MM:SS'
 +
 +        # Dodaj placeholder do pola rok
 +        self.fields['release_year'].widget.attrs['placeholder'] = 'Wprowadź rok wydania'
 +
 +
 +    def clean_duration(self):
 +        duration = self.cleaned_data['duration']
 +
 +        # Sprawdzamy, czy duration ma poprawny format (HH:MM:SS)
 +        if duration.total_seconds() < 0:
 +            raise forms.ValidationError('Niewłaściwy format czasu. Użyj wartości nieujemnej.')
 +
 +        # Sprawdzamy, czy duration nie przekracza 01:59:59
 +        if duration.total_seconds() > 7199:
 +            raise forms.ValidationError('Maksymalna długość to 1 godzina, 59 minut i 59 sekund.')
 +
 +        return duration
 +
 +class ArtistInline(admin.TabularInline):
 +    model = Artist.songs.through  # To jest model pośredniczący w relacji wiele-do-wielu
 +    extra = 1
 +
 +@admin.register(Song)
 +class SongAdmin(admin.ModelAdmin):
 +    form = SongAdminForm
 +    list_display = ('song_title', 'release_year', 'duration', 'created_at', 'modified_at')
 +    list_filter = ('release_year',)
 +    search_fields = ('song_title',)
 +    readonly_fields = ['created_at', 'modified_at']
 +    inlines = [ArtistInline]
 +
 +@admin.register(Artist)
 +class ArtistAdmin(admin.ModelAdmin):
 +    list_display = ('artist_name',)
 +    search_fields = ['artist_name']
 +    filter_horizontal = ('songs',)
 +
 +class StorageMediumInline(admin.StackedInline):
 +    model = StorageMedium
 +    extra = 1
 +    filter_horizontal = ('songs',)
 +
 +@admin.register(MusicAlbum)
 +class MusicAlbumAdmin(admin.ModelAdmin):
 +    search_fields = ['album_title']
 +    inlines = [StorageMediumInline]
 +
 +@admin.register(StorageMedium)
 +class StorageMediumAdmin(admin.ModelAdmin):
 +    filter_horizontal = ('songs',)
 +    search_fields = ['disc_title']
 +    list_filter = ('albums_title',)
 +</code>
 + 
  
  
pl/python/dbaudiocd.1701091705.txt.gz · ostatnio zmienione: 2023/11/27 14:28 przez sindap

Donate Powered by PHP Valid HTML5 Valid CSS Driven by DokuWiki