From 298255d2254e2dd9c80e3378493cd296e1d54ba1 Mon Sep 17 00:00:00 2001 From: =?utf8?q?J=C3=A9r=C3=B4me=20Benoit?= Date: Fri, 1 Nov 2013 02:35:59 +0100 Subject: [PATCH] A bunch of fixes : MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit * Correct the data models to make use of django user management. There's still some questions but I think the is_author will be useful to filter author from user quickly; * Finalize the comic data model, looks really cool now; * Work on the admin interface; Probably more ... I've forgot. Signed-off-by: Jérôme Benoit --- comicsporn/admin.py | 36 ++++++++++++++ comicsporn/models.py | 108 ++++++++++++++++++++++++++++++------------ comicsporn/models.pyc | Bin 1630 -> 4380 bytes settings.py | 2 +- urls.py | 4 +- 5 files changed, 118 insertions(+), 32 deletions(-) create mode 100644 comicsporn/admin.py diff --git a/comicsporn/admin.py b/comicsporn/admin.py new file mode 100644 index 0000000..9799d44 --- /dev/null +++ b/comicsporn/admin.py @@ -0,0 +1,36 @@ +from django.contrib import admin +from django.contrib.auth.admin import UserAdmin +from django.contrib.auth.models import User +from comicsporn.models import Style, UserProfile, Comic_block, Comic +from django.utils.translation import ugettext as _ + +admin.site.register(Style) + +class UserProfileInline(admin.StackedInline): + model = UserProfile + can_delete = False + verbose_name_plural = _('Users profiles') + +class UserAdmin(UserAdmin): + inlines = (UserProfileInline, ) + +admin.site.unregister(User) +admin.site.register(User, UserAdmin) + +class Comic_blockInline(admin.TabularInline): + model = Comic.blocks.through + extra = 10 + +class ComicAdmin(admin.ModelAdmin): + fieldsets = [ + ('Title', {'fields': ['title']}), + ('Online', {'fields': ['is_online']}), + ('Comic block', {'fields': ['blocks']}), + ] + inlines = [ + Comic_blockInline, + ] + +admin.site.register(Comic_block) + +admin.site.register(Comic) diff --git a/comicsporn/models.py b/comicsporn/models.py index 8ccfd9d..0cea8c9 100644 --- a/comicsporn/models.py +++ b/comicsporn/models.py @@ -1,38 +1,88 @@ from django.db import models - -# Create your models here. +from django.contrib.auth.models import User +from django.utils.translation import ugettext_lazy as _ # A very basic data model to begin with -# Create sensible default option, test the authentification framework, ensure -# pertinence of the comics building way : page by page, vignette by vignette, etc. offer -# multiple way as much as much possible, test upload to PDF file outisde the DB... - -class User(models.Model): - first_name = models.CharField(max_length=50) - last_name = models.CharField(max_length=50) - # Not sure about this two, django should offer login/pass and session - #login = models.CharField(max_length=15) - #password = models.CharField(max_length=15) - email = models.EmailField() +# TODO: +# - Create sensible default options with translation; +# - Test the authentification framework; +# - Ensure pertinence of the comics building way : block by block; +# - Test upload to images file outside the DB ...; +# - ... + +class Style(models.Model): + """ + TODO: The choice list should be in DB + """ + TAG_NAME_CHOICES = ( + (_('MG'), _('Manga')), + (_('HF'), _('Heroic Fantasy')), + ) + name = models.CharField(_('name'), max_length=30, choices=TAG_NAME_CHOICES) + def __unicode__(self): + return self.name + class Meta: + verbose_name = _('Style') + verbose_name_plural = _('Styles') + ordering = ('name',) + +class UserProfile(models.Model): + user = models.OneToOneField(User) headshot = models.ImageField(upload_to='user_headshots') is_author = models.BooleanField() - #num_awards = models.IntegerField() + """ + The main difference is that the author have is own ads publisher + The default behaviour of class inheritance is to create OnetoOne relationship between parent and child + TODO: Which fields are required to interact with the ads publisher ? + """ + ADS_PUBLISHER_CHOICES = ( + ('AS', 'Advert Stream'), + ('TJ', 'Traffic Junky'), + ) + ads_publisher = models.CharField(max_length=50, choices=ADS_PUBLISHER_CHOICES) + ads_publisher_login = models.CharField(max_length=50) + + class Meta: + verbose_name = _('User profile') + verbose_name_plural = _('Users profiles') + +# TODO: See how to handle a group of authors and the revenue sharing ... later +class Comic_block(models.Model): + """ + Let's view a comics as an images serie + """ + name = models.CharField(_('name'), max_length=50) # probably not useful, it's just simplier to assemble afterwards for author + number = models.IntegerField(_('number')) + content = models.ImageField(upload_to='block_contents') + # TODO: probably not useful + is_complete = models.BooleanField() + upload_datetime = models.DateTimeField(_('upload_datetime'), auto_now=True) + authors = models.ManyToManyField(UserProfile, verbose_name=_('authors')) + def __unicode__(self): + """ + This idea is to return a visual identifier to the author, self.content is surely bogus to get the image path + """ + return self.name + ' ' + self.content -class Comics_page(models.Model): - # Not sure about vignette by vignette view or page by page ... let's start page by page - page_number = models.IntegerField() - page_content = models.ImageField(upload_to='comics_pages') - upload_date = models.DateField() - page_authors = models.ManyToManyField(User) + class Meta: + verbose_name = _('Comic_block') + verbose_name_plural = _('Comic_blocks') + ordering = ('name',) -class Comics(Comics_page): - title = models.CharField(max_length=300) +class Comic(models.Model): + """ + A comic is build from N blocks, whatever they are + The ManytoMany relationship is not really required but it much more reflect really : authors can share block between comic + """ + title = models.CharField(max_length=50) rating = models.FloatField() - authors = models.ManyToManyField(User) - publication_date = models.DateField() - # Change the related name to a more appropriate name - fragment_comics = models.ManyToManyField(Comics_page, related_name="%(app_label)s_%(class)s_related") - full_comics = models.ImageField(upload_to='comics_full') - full_comics_upload_date = models.DateField() - #publisher = models.ForeignKey(User) + is_online = models.BooleanField() + publication_date = models.DateField(auto_now=True) + blocks = models.ManyToManyField(Comic_block) + styles = models.ManyToManyField(Style) + def __unicode__(self): + return self.title + + class Meta: + ordering = ('title',) diff --git a/comicsporn/models.pyc b/comicsporn/models.pyc index af24cbc13c062fc0c610ef08a808207fd401017b..1ad9b55f2b430574a88800a5177e4b904478bfab 100644 GIT binary patch literal 4380 zcmcInTXWk)6kgeh6T4{>Qrc2FFv|lFn34>)7l!GOCcT8|g;C5f_(daIYg?%-8SSbe z!0=Lj1iyj@hJVHnfbTo&$S!Rk=%uOFyJw}B9ZI!GpY_#i*j!HTU8)xc`Gb&kAhg)Z%T>20GZ3URQ7KTZYn9Tb164u{ZQ~DKe zu13Z=^P`Kh_@@)M49TH8$xLlFPq>cD{*1vWS_@-)4P}~i!J|MX4Nit$*gO?3&4iHm zVE?i@g0XmNnQ|DOtcaDotWJ} z9ZV+ik5OjwksGIPW9e2f_&3=B-FkZMVQ#tki&95$oOtz~j3LEypIeg+w;)k6*v~QB z85a|?Gc4oLC^I{@9PA`VP_j5K$_F2fQnxcGCh5RVi!$HwA>5vxxHEV%imE&vAgWPx z5lc%mRUjtZH7>40N4bRVJxqM)OoP#b`;nxaO8^m^1ZlfWFVhcU6N99Vq=KE>Vo%+) z#k6p%7@~-7iz0Dc6hYG}g|xIqDj?(VJV-tOHS(cbO*2YWXTL&%hC zW7r$V<;~P&iFhVtOypHBPjN|Zgd zgMEZB3k(rm#2Wxa_!)H-0CAM8l8JiY8zB%v75oA@mNh~;nEScu78rc;N`)Yz85qIu z!6Y8}O#$R-tOUl_iy|{|E{{rZQyayV8yBU!fHQXY52J6sy?*E5@b-h-i)9} z)2a`m9^+kPfyX3KR*cg8C4=Y^-trbMOEkBF^kjNPDE%sGk*s2X!LV zK>7nu`9wk%`GR*OWz4fC>OENVQ4pZMqpG2{qrxQuHu5XVH-vx(ge}1va0SU3!5grI z`B`~nMam)WKPRWH%hrZ6uMu556YwKX2ffW%QS63&>6$Kb5acXs%m{{Z2 z6}mL8Dsvd~Ftt^jaVvM}Fa>_G>(C7Nw_Sy0*>HQNEg!a3X|faDFGiJ|gpNn<7f0x6 z?8bPV6fEtb#oFzQzBk!dbk>YH;-9~UOTD;;!+hahdIpdE-=h64l_rlYB=s{(_X0T( z9CJzw3C+2cGJ642sn0&HCkikrV?l}6xx}SHGKQyFi2@HeK;Dhatm4uwA-l5hDhG{0 zY9iPOSw77S5|UK6kId{MGd*9C<+^2MLK-9qjE3-}TX6JbNU{hComWxL8JkaWN#3KJ z2Umg%;Gi}9UJ2SQ=};wXH48Oyx0G|>`zb60)PR3jgHhMPBxD%HijMhdMduuyG&%rs zPQd!@Ifp!>dY)%MK^w9J+boexNHX9YwBxOsTh5bPR;mA=7<8w->luaM>Q^b6?qOL> z^gS&^VXx}rF}#nGPMDqOxCGCzTc@|3_#9}?VwV=V9j8+slNS!MI0H^g^Fx)E2AzE6 zbn5h^8jSU%C=GUo=y>WIznCH3>H%oYqA4?81AGIxV`Fl!B{+_{`^JGE5QEeHoxgjy zp3%cgSX}Bd^9l%{%lDEGRq!|gP$`K#Tc%n4LAV->0q+k#!ypRTWz4*OOqT^Xy?hXV zhZl&ttyu>xh^30sL5KeVFm;rU;wBnE=P}40yhPCRkw-0iIH0!3votr-Q4q5pjUV%Q zGL!TS14)&L#U}g&!ce%5=lO)2f3R47yV_R)VZ!$Smxu6Di_HZ7HqlnB2kqv)Ei#o@ z;XmWHlfDp|V-GhIu_l#if18DB+kexA(uA?n&hDvPn%Qkv#<}$f2_@+Ch5wM{*Sr`U n3T4q1A(a!Vo)6DY+EUBE^dEB9sGc;+8v*`0mp3k7ynOLr|E`jV literal 1630 zcmb_c&2H2%5VrTfZTdr{g7$zoRSFVxB_wVLK?{|7D2Eh~SRq;7*qcpp;t+cUJ(q{z z@puOw0A|M7pOzzCHB--cY=8c~8Ml9LZ~prEHAz|XYs3Fn@VU=m6#Q{!7%Mm%bH-JR zY0fTNY|5ExvmcCIGxllRW~#F`(Oph-nCdazq4fST+GT3MF5(S1ApZlun8V2Tz!X+# z<9r8(ADpglfI5bt`v^ue#G+g563!)n*Nl$=z^zD^B0YpS?$da{-~xaf^EW86NwZrl zxrp&lzX_(0--Xd-=4bgcj3Lf>Wvo=fTfc)IU=uSfm77`b;s~<_V1y`Tp@pDrgn--3 z4Y&zRg>6n|vOdkVQIs*wYv*YRonhp{LlkcdnVXQ?1y`d>tIi6U=`ew3E?{^>acr&8 zvJA7tuM=|aXSR-EmaU9?4(@1X3q6|FGRuq}xjG%GOIc?2o2|b*&2m3VZIP$0vUNEM z${bZ!35taP9hx5B=lh)qtlt9ngcgVj5dN#(Ye-nv4s{8tK|w5agn9uT`=rZ&#-J3) z1O-SkwP2T|4Tdfp5YmA`hXlz=u$BVr$jVvib*3BQ5hmgj<-C~aIwA4UP%yQSTYA#t zjr0xAxTdK91wp?H{<$o#-dnW9HqkYHffwMYZl8!PH?at4bI-(dMxehj9wU?_ks<27!_GM&Rk(nD`#}xAaZ=5c87l_TjXuc%u0(FD`NZTYq}o!T#t8;VXzY&yYC;4k zpr}R(hmX`GGyrmQj?XGx dp01VPMt25_UcMLMt$T?CJ7j%tV;Bwle*q11Wb6O{ diff --git a/settings.py b/settings.py index cc21cbb..d408123 100644 --- a/settings.py +++ b/settings.py @@ -109,7 +109,7 @@ MIDDLEWARE_CLASSES = ( 'django.contrib.messages.middleware.MessageMiddleware', ) -ROOT_URLCONF = 'django.urls' +ROOT_URLCONF = 'urls' TEMPLATE_DIRS = ( # Put strings here, like "/home/html/django_templates" or "C:/www/django/templates". diff --git a/urls.py b/urls.py index 07576d3..658585a 100644 --- a/urls.py +++ b/urls.py @@ -1,8 +1,8 @@ from django.conf.urls.defaults import patterns, include, url # Uncomment the next two lines to enable the admin: -# from django.contrib import admin -# admin.autodiscover() +from django.contrib import admin +admin.autodiscover() urlpatterns = patterns('', # Examples: -- 2.34.1