implement base model, factories, nodes

This commit is contained in:
Pawel Kowalski 2018-08-08 11:41:39 +02:00
parent 2b9b77f4bb
commit e21ba0a232
15 changed files with 343 additions and 1 deletions

View File

@ -2,8 +2,10 @@ import graphene
from django.conf import settings from django.conf import settings
from graphene_django.debug import DjangoDebug from graphene_django.debug import DjangoDebug
from book.schema import ModulesQuery
class Query(graphene.ObjectType):
class Query(ModulesQuery, graphene.ObjectType):
# This class will inherit from multiple Queries # This class will inherit from multiple Queries
if settings.DEBUG: if settings.DEBUG:

0
server/book/__init__.py Normal file
View File

18
server/book/admin.py Normal file
View File

@ -0,0 +1,18 @@
from django.contrib import admin
from book.models import Book, Topic, Module
@admin.register(Book)
class BookAdmin(admin.ModelAdmin):
list_display = ('title', 'slug')
@admin.register(Topic)
class TopicAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'teaser', 'description')
@admin.register(Module)
class ModuleAdmin(admin.ModelAdmin):
list_display = ('title', 'slug', 'meta_title', 'teaser')

5
server/book/apps.py Normal file
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class BookConfig(AppConfig):
name = 'book'

14
server/book/blocks.py Normal file
View File

@ -0,0 +1,14 @@
from wagtail.core import blocks
from wagtail.documents.blocks import DocumentChooserBlock
DEFAULT_RICH_TEXT_FEATURES = ['bold', 'italic', 'link', 'ol', 'ul']
class LinkBlock(blocks.StructBlock):
url = blocks.URLBlock()
description = blocks.CharBlock()
class DocumentBlock(blocks.StructBlock):
document = DocumentChooserBlock()
description = blocks.CharBlock()

30
server/book/factories.py Normal file
View File

@ -0,0 +1,30 @@
import random
import factory
from book.models import Book, Topic, Module
from core.factories import BasePageFactory, fake, DummyImageFactory
class BookFactory(BasePageFactory):
class Meta:
model = Book
class TopicFactory(BasePageFactory):
class Meta:
model = Topic
teaser = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(8, 12)))
description = factory.LazyAttribute(lambda x: fake.text(max_nb_chars=200))
class ModuleFactory(BasePageFactory):
class Meta:
model = Module
meta_title = factory.LazyAttribute(lambda x: fake.text(max_nb_chars=20))
teaser = factory.LazyAttribute(lambda x: fake.sentence(nb_words=random.randint(8, 12)))
description = factory.LazyAttribute(lambda x: fake.text(max_nb_chars=200))
hero_image = factory.SubFactory(DummyImageFactory)

View File

@ -0,0 +1,57 @@
# Generated by Django 2.0.6 on 2018-08-08 09:26
from django.db import migrations, models
import django.db.models.deletion
import wagtail.core.fields
class Migration(migrations.Migration):
initial = True
dependencies = [
('wagtailimages', '0020_add-verbose-name'),
('wagtailcore', '0040_page_draft_title'),
]
operations = [
migrations.CreateModel(
name='Book',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
],
options={
'verbose_name': 'Buch',
'verbose_name_plural': 'Bücher',
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='Module',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
('meta_title', models.CharField(help_text="e.g. 'Intro' or 'Modul 1'", max_length=255)),
('teaser', models.TextField()),
('description', wagtail.core.fields.RichTextField()),
('hero_image', models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.SET_NULL, related_name='+', to='wagtailimages.Image')),
],
options={
'verbose_name': 'Modul',
'verbose_name_plural': 'Module',
},
bases=('wagtailcore.page',),
),
migrations.CreateModel(
name='Topic',
fields=[
('page_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='wagtailcore.Page')),
('teaser', models.TextField()),
('description', wagtail.core.fields.RichTextField()),
],
options={
'verbose_name': 'Thema',
'verbose_name_plural': 'Themen',
},
bases=('wagtailcore.page',),
),
]

View File

View File

@ -0,0 +1,3 @@
from .module import *
from .topic import *
from .book import *

View File

@ -0,0 +1,29 @@
import logging
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, ObjectList
from wagtail.core.models import Page
logger = logging.getLogger(__name__)
class Book(Page):
class Meta:
verbose_name = 'Buch'
verbose_name_plural = 'Bücher'
content_panels = [
FieldPanel('title', classname="full title")
]
settings_panels = [
FieldPanel('slug')
]
edit_handler = TabbedInterface([
ObjectList(content_panels, heading='Content'),
ObjectList(settings_panels, heading='Settings'),
])
template = 'generic_page.html'
subpage_types = ['book.Topic']

View File

@ -0,0 +1,54 @@
import logging
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, \
ObjectList
from wagtail.core.fields import RichTextField
from wagtail.core.models import Page
from wagtail.images.edit_handlers import ImageChooserPanel
from book.blocks import DEFAULT_RICH_TEXT_FEATURES
logger = logging.getLogger(__name__)
class Module(Page):
class Meta:
verbose_name = 'Modul'
verbose_name_plural = 'Module'
meta_title = models.CharField(
max_length=255,
help_text='e.g. \'Intro\' or \'Modul 1\''
)
teaser = models.TextField()
description = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES)
hero_image = models.ForeignKey(
'wagtailimages.Image',
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name='+'
)
content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('meta_title', classname="full title"),
ImageChooserPanel('hero_image'),
FieldPanel('teaser'),
FieldPanel('description'),
]
settings_panels = [
FieldPanel('slug')
]
edit_handler = TabbedInterface([
ObjectList(content_panels, heading='Content'),
ObjectList(settings_panels, heading='Settings'),
])
template = 'generic_page.html'
parent_page_types = ['book.Topic']

View File

@ -0,0 +1,40 @@
import logging
from django.db import models
from wagtail.admin.edit_handlers import FieldPanel, TabbedInterface, \
ObjectList
from wagtail.core.fields import RichTextField
from wagtail.core.models import Page
from book.blocks import DEFAULT_RICH_TEXT_FEATURES
logger = logging.getLogger(__name__)
class Topic(Page):
class Meta:
verbose_name = 'Thema'
verbose_name_plural = 'Themen'
teaser = models.TextField()
description = RichTextField(features=DEFAULT_RICH_TEXT_FEATURES)
content_panels = [
FieldPanel('title', classname="full title"),
FieldPanel('teaser'),
FieldPanel('description'),
]
settings_panels = [
FieldPanel('slug')
]
edit_handler = TabbedInterface([
ObjectList(content_panels, heading='Content'),
ObjectList(settings_panels, heading='Settings'),
])
template = 'generic_page.html'
parent_page_types = ['book.Book']
subpage_types = ['book.Module']

81
server/book/schema.py Normal file
View File

@ -0,0 +1,81 @@
from graphene import relay
from graphene_django import DjangoObjectType
from graphene_django.filter import DjangoFilterConnectionField
import graphene
from .models import Book, Topic, Module
class ModuleNode(DjangoObjectType):
pk = graphene.Int()
hero_image = graphene.String()
class Meta:
model = Module
only_fields = [
'slug', 'title', 'meta_title', 'teaser', 'description',
]
filter_fields = {
'slug': ['exact', 'icontains', 'in'],
'title': ['exact', 'icontains', 'in'],
}
interfaces = (relay.Node,)
def resolve_pk(self, *args, **kwargs):
return self.id
def resolve_hero_image(self, *args, **kwargs):
if self.hero_image:
return self.hero_image.file.url
class TopicNode(DjangoObjectType):
pk = graphene.Int()
class Meta:
model = Topic
only_fields = [
'slug', 'title', 'meta_title', 'teaser', 'description',
]
filter_fields = {
'slug': ['exact', 'icontains', 'in'],
'title': ['exact', 'icontains', 'in'],
}
interfaces = (relay.Node,)
def resolve_pk(self, *args, **kwargs):
return self.id
class BookNode(DjangoObjectType):
pk = graphene.Int()
class Meta:
model = Book
only_fields = [
'slug', 'title',
]
filter_fields = {
'slug': ['exact', 'icontains', 'in'],
'title': ['exact', 'icontains', 'in'],
}
interfaces = (relay.Node,)
def resolve_pk(self, *args, **kwargs):
return self.id
class ModulesQuery(object):
books = DjangoFilterConnectionField(BookNode)
topics = DjangoFilterConnectionField(TopicNode)
modules = DjangoFilterConnectionField(ModuleNode)
def resolve_books(self, *args, **kwargs):
return Book.objects.filter(**kwargs).live()
def resolve_topics(self, *args, **kwargs):
return Topic.objects.filter(**kwargs).live()
def resolve_modules(self, *args, **kwargs):
return Module.objects.filter(**kwargs).live()

View File

@ -8,6 +8,7 @@ from django.core.management import BaseCommand
from django.db import connection from django.db import connection
from wagtail.core.models import Page from wagtail.core.models import Page
from book.factories import BookFactory, TopicFactory, ModuleFactory
from core.factories import UserFactory from core.factories import UserFactory
data = [ data = [
@ -46,3 +47,10 @@ class Command(BaseCommand):
for i in range(0, 4): for i in range(0, 4):
UserFactory(username='user{}'.format(i)) UserFactory(username='user{}'.format(i))
book = BookFactory.create(parent=site.root_page)
for idx_topic in range(0, 11):
topic = TopicFactory.create(parent=book)
for idc_module in range(0, 5):
module = ModuleFactory.create(parent=topic)

View File

@ -46,6 +46,7 @@ INSTALLED_APPS = [
'core', 'core',
'api', 'api',
'user', 'user',
'book',
'wagtail.contrib.forms', 'wagtail.contrib.forms',
'wagtail.contrib.redirects', 'wagtail.contrib.redirects',