Musik-Info-Modell

943
dassouki

Ich lerne Django während ich gehe. Ich weiß, dass diesem Modell Benutzerauthentifizierung, Registrierung, Kommentare / Kommentarthreading und Abstimmungen fehlen. Dies ist jedoch mein Startcode für mein Modell. Was kann ich verbessern, ändern, umschreiben usw.?

from django.contrib.auth.models import User
from django.db import models
from django.contrib import admin
from django.template.defaultfilters import escape
from django.utils.translation import ugettext as _
from django.utils.encoding import force_unicode
from django.http import HttpResponse, HttpResponseRedirect
from django.core.urlresolvers import reverse

class DateTime(models.Model):
  datetime = models.DateTimeField(auto_now_add=True)

  def __unicode__(self):
    return unicode(self.datetime.strftime("%b %d, %Y, %I:%M %p"))

class Country(models.Model):
  country = models.CharField(max_length=50)

  def __unicode__(self):
    return unicode(self.country)

class Artist(models.Model):
  artist = models.CharField(max_length=50)
  country = models.ForeignKey(Country, blank=True, null=True)
  user = models.ForeignKey(User, blank=True, null=True)
  created = models.ForeignKey(DateTime)
  notes = models.TextField()

  def __unicode__(self):
    return artist

class Song(models.Model):
  name = models.CharField(max_length=200)
  artist = models.ForeignKey(Artist, blank=True, null=True)
  # language = models.ForeignKey(Country, blank=True, null=True)
  user = models.ForeignKey(User, blank=True, null=True)
  created = models.ForeignKey(DateTime)
  notes = models.TextField()

  def __unicode__(self):
    return song

class FileType(models.Model):
  file_type = models.CharField(max_length=3)
  description = models.TextField()
  user = models.ForeignKey(User, blank=True, null=True)
  created = models.ForeignKey(DateTime)
  notes = models.TextField()

  def __unicode__(self):
    return file_type

class Level(models.Model):
  level = models.CharField(max_length=3)
  description = models.TextField()
  user = models.ForeignKey(User, blank=True, null=True)
  created = models.ForeignKey(DateTime)
  notes = models.TextField()

  def __unicode__(self):
    return level

class MusicSheet(models.Model):
  version = models.CharField(max_length=2)
  song = models.ForeignKey(Song, blank=True, null=True)
  artist = models.ForeignKey(Artist, blank=True, null=True)
  file_type = models.ForeignKey(FileType, blank=True, null=True)
  level = models.ForeignKey(Level, blank=True, null=True)
  user = models.ForeignKey(User, blank=True, null=True)
  created = models.ForeignKey(DateTime)
  text = models.TextField()
  notes = models.TextField()

#include votes

#include comments

#include registration code


########################################################################################################################
######################################## ADMIN STUFF ###################################################################
########################################################################################################################


class MusicSheetAdmin(admin.ModelAdmin):
  list_display = ["version", "song", "artist", "file_type", "level", "user", "created", "text", "notes"]
  search_fields = ["version"]

class MusicSheetInline(admin.TabularInline):
  model = MusicSheet

class DateAdmin(admin.ModelAdmin):
  list_display = ["datetime"]
  inlines = [MusicSheetInline]

  def response_add(self, request, obj, post_url_continue='../%s/'):
    """ Determines the HttpResponse for the add_view stage.  """
    opts = obj._meta
    pk_value = obj._get_pk_val()

    msg = "Song(s) were added successfully."
    # Here, we distinguish between different save types by checking for
    # the presence of keys in request.POST.
    if request.POST.has_key("_continue"):
      self.message_user(request, msg + ' ' + _("You may edit it again below."))
      if request.POST.has_key("_popup"):
        post_url_continue += "?_popup=1"
      return HttpResponseRedirect(post_url_continue % pk_value)

    if request.POST.has_key("_popup"):
      return HttpResponse(
          '<script type="text/javascript">opener.dismissAddAnotherPopup(window, "%s", "%s");'
          '</script>' % (escape(pk_value), escape(obj)))
    elif request.POST.has_key("_addanother"):
      self.message_user(request, msg + ' ' + (_("You may add another %s below.") %
                                              force_unicode(opts.verbose_name)))
      return HttpResponseRedirect(request.path)
    else:
      self.message_user(request, msg)

    for music_sheet in MusicSheet.objects.filter(created=obj):
      if not music_sheet.user:
        music_sheet.user = request.user
        music_sheet.save()

    return HttpResponseRedirect(reverse("admin:musicsheet_musicsheet_changelist"))


class CountryAdmin(admin.ModelAdmin):
  list_display = ["country"]
  search_fields = ["country"]

class CountryInline(admin.TabularInline):
  model = MusicSheet



class SongAdmin(admin.ModelAdmin):
  list_display = ["name", "artist", "user", "created", "notes"]
  search_fields = ["name", "artist"]

class SongInline(admin.TabularInline):
  model = MusicSheet



class ArtistAdmin(admin.ModelAdmin):
  list_display = ["artist", "country", "user", "created", "notes"]
  search_fields = ["artist", "country"]

class ArtistInline(admin.TabularInline):
  model = MusicSheet



class FileTypeAdmin(admin.ModelAdmin):
  list_display = ["file_type", "description", "user", "created", "notes"]
  search_fields = ["file_type"]

class FileTypeInline(admin.StackedInline):
  model = MusicSheet


class LevelAdmin(admin.ModelAdmin):
  list_display = ["level", "description", "user", "created", "notes"]
  search_fields = ["level"]

class LevelInline(admin.StackedInline):
  model = MusicSheet

admin.site.register(MusicSheet, MusicSheetAdmin)
admin.site.register(Country, CountryAdmin)
admin.site.register(Song, SongAdmin)
admin.site.register(Artist, ArtistAdmin)
admin.site.register(FileType, FileTypeAdmin)
admin.site.register(Level, LevelAdmin)
admin.site.register(DateTime, DateAdmin)
Antworten
24
Ich schlage vor, dass Sie Orte hervorheben, zu denen Sie Feedback benötigen. Abgesehen davon wird das Sortieren von Importen und (möglicherweise) Feldnamen Ihr Leben auf lange Sicht erleichtern. TryPyPy vor 9 Jahren 1
@TryPyPY - Meistens rund um das Modell selbst, Aufbau der Klassen, wie kann ich es effizienter gestalten? zunehmend besser? Wie kann ich diesen Code von Newb zu Pro bringen? dassouki vor 9 Jahren 0

3 Antworten auf die Frage

18
Bolo

Haftungsausschluss: Ich bin kein Django-Guru. Hier sind meine Gedanken, was es wert ist.

  • Gemeinsame Felder : user, created, und nodesin fast jeder Klasse auftreten. Ich würde in Betracht ziehen, eine abstrakte Basisklasse mit diesen drei Feldern zu erstellen .

  • Feldnamen : aus Gründen der Lesbarkeit, würde ich ändern Artist.artistzu Artist.name, und *.userzu *.creator.

  • Dateierweiterungen : gelegentlich mehr als 3 Buchstaben (zB: .jpeg, .java).

  • Indizierung : Ich würde db_index=Truedie nameFelder zumindest hinzufügen .

  • Redundanz : Da Sie MusicSheet.songund haben Song.artist, brauchen Sie nicht mehr MusicSheet.artist. Es wird Redundanz genannt und ist im Allgemeinen eine schlechte Sache.

  • Primärschlüssel, eindeutige Einschränkungen : Sie möchten wahrscheinlich nicht zwei FileTypes mit dem gleichen verwenden file_type, so dass dieses Feld ein guter Kandidat für Primärschlüssel ( primary_key=True) ist. Ich bin nicht sicher, was Levelmodelliert werden soll, aber ich schätze, dass leveles auch ein guter Kandidat für den Primärschlüssel ist. Fügen Sie unique=Truefür Country.country, oder fügen Sie einen Primärschlüssel mit Code Land .

  • DateTime : Ich sehe keinen Bedarf für diese Klasse. Ersetzen Sie einfach jedes Vorkommen von: created = models.ForeignKey(DateTime)mit models.DateTimeField(auto_now_add=True).

6
UloPe

Ein paar Dinge fallen mir ein:

  • Verlieren Sie das DateTime-Modell und fügen Sie stattdessen ein DateTimeField direkt zu den Modellen hinzu, die es benötigen. Der ForeignKey kauft Ihnen nichts außer einen zusätzlichen Datenbank-Join, selbst für einfachste Operationen.
  • Sie haben dies wahrscheinlich nur getan, um diesen Code in einem Stück einzufügen, aber wenn nicht: Sie sollten Ihren Admin-Code in eine Datei namens admin.py in Ihrer Anwendung einfügen. Auf diese Weise können Sie die Funktion zur automatischen Erkennung des Administrators verwenden
  • In DateAdmin überschreiben Sie die response_add-Methode, um (soweit ich sehen kann) das Benutzer / Ersteller-Feld festzulegen. Dies kann durch das Überschreiben der save_model-Methode wesentlich einfacher abgeschlossen werden .
1
felixphew
  • Anstelle der (sehr langen) Liste der Admin-Klassen am Ende können Sie sie in das Modell integrieren.

    class MusicSheet(models.Model):
        version = models.CharField(max_length=2)
        song = models.ForeignKey(Song, blank=True, null=True)
        artist = models.ForeignKey(Artist, blank=True, null=True)
        file_type = models.ForeignKey(FileType, blank=True, null=True)
        level = models.ForeignKey(Level, blank=True, null=True)
        user = models.ForeignKey(User, blank=True, null=True)
        created = models.ForeignKey(DateTime)
        text = models.TextField()
        notes = models.TextField()
    
    class MusicSheetAdmin(admin.ModelAdmin):
        list_display = ["version", "song", "artist", "file_type", "level", "user", "created", "text", "notes"]
        search_fields = ["version"]
    
    class MusicSheetInline(admin.TabularInline):
        model = MusicSheet
    
    admin.site.register(MusicSheet, MusicSheetAdmin)
    

    kann vereinfacht (und nicht dargestellt) werden:

    class MusicSheet(models.Model):
        version = models.CharField(max_length=2)
        song = models.ForeignKey(Song, blank=True, null=True)
        artist = models.ForeignKey(Artist, blank=True, null=True)
        file_type = models.ForeignKey(FileType, blank=True, null=True)
        level = models.ForeignKey(Level, blank=True, null=True)
        user = models.ForeignKey(User, blank=True, null=True)
        created = models.ForeignKey(DateTime)
        text = models.TextField()
        notes = models.TextField()
    
        class Admin:
            list_display = ["version", "song", "artist", "file_type", "level", "user", "created", "text", "notes"]
            search_fields = ["version"]
    

    Stellen Sie sicher, dass class Administ innerhalb der Hauptklasse.

    Wenn Sie sie jedoch getrennt haben möchten, gehören die Verwaltungsklassen und Registrierungen zu einer separaten Datei admin.py. (Sie müssen die Modelle importieren from myapp.models import *)

  • Einige deiner ForeignKeys haben beides blank=Trueund null=True. Dies ist im Allgemeinen keine gute Idee. Möchten Sie zulassen, dass sie null (kein Wert) oder leer (leerer Wert) sind? Wenn Sie Ihren Code betrachten, würde ich sagen, Sie möchten, null=Trueaber ich bin mir nicht sicher. Versuchen Sie es mit einem und dann mit dem anderen und sehen Sie, wer was macht, was Sie wollen. Ich bezweifle stark, dass Sie beide brauchen. In der Regel verwende ich nur blank=Truefür CharFields. Daher können Sie anstelle eines leeren Datenbankfelds eine Nullzeichenfolge verwenden.

  • Ich kann nicht herausfinden, was DateAdminzu tun ist. Sie werden es wahrscheinlich nicht benötigen, wenn Sie wie oben empfohlen zu DateTimeField wechseln, aber ich möchte wissen, wozu er bestimmt ist, bevor ich einen Anruf tätige.