Skip to content

Commit 3b6ddf1

Browse files
renzonrenzon
authored andcommitted
Created one to many from Section to Modules
related to #261
1 parent 4548b93 commit 3b6ddf1

7 files changed

Lines changed: 70 additions & 30 deletions

File tree

‎pythonpro/modules/facade.py‎

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from django.urls import reverse as _reverse
1+
from django.db.models import Prefetch
22

33
from pythonpro.modules.models import Section as _Section, Module as _Module
44

@@ -11,20 +11,16 @@ def get_all_modules():
1111
return tuple(_Module.objects.order_by('order'))
1212

1313

14-
def get_module_sections(module):
14+
def get_module_sections(slug):
1515
"""
16-
Search for all module's sections. Only Section's title and slug is returned
17-
:param module:
18-
:return:
16+
Search for a module with respective sections
17+
:param slug: module slugs
18+
:return: Module with respective section on attribute sections
1919
"""
2020

21-
def set_absolut_url(dct):
22-
dct['get_absolute_url'] = _reverse('sections:detail', kwargs={'slug': dct['slug']})
23-
return dct
24-
25-
mapped = map(
26-
set_absolut_url,
27-
_Section.objects.values('title', 'slug').filter(_module_slug=module.slug).order_by('order')
28-
)
29-
30-
return tuple(mapped)
21+
return _Module.objects.filter(slug=slug).prefetch_related(
22+
Prefetch(
23+
'section_set',
24+
queryset=_Section.objects.order_by('order'),
25+
to_attr='sections')
26+
).get()
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# Generated by Django 2.0.3 on 2018-03-14 20:45
2+
3+
import django.db.models.deletion
4+
from django.db import migrations, models
5+
6+
7+
def populate_foreign_key(apps, scheme_editor):
8+
"""Populate module foreign key attribute based on _module_slug"""
9+
Section = apps.get_model('modules', 'Section')
10+
Module = apps.get_model('modules', 'Module')
11+
for section in Section.objects.all():
12+
section.module = Module.objects.filter(slug=section._module_slug).get()
13+
section.save()
14+
15+
16+
def reverse_populate_foreign_key(apps, scheme_editor):
17+
"""No need to revert since column will be dropped. Function is present only to allow migration roll back"""
18+
19+
20+
class Migration(migrations.Migration):
21+
dependencies = [
22+
('modules', '0003_module'),
23+
]
24+
25+
operations = [
26+
migrations.AddField(
27+
model_name='section',
28+
name='module',
29+
field=models.ForeignKey(default=1, on_delete=django.db.models.deletion.CASCADE, to='modules.Module'),
30+
preserve_default=False,
31+
),
32+
migrations.RunPython(populate_foreign_key, reverse_populate_foreign_key)
33+
]

‎pythonpro/modules/models.py‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -185,6 +185,7 @@ def parent(self):
185185

186186
class Section(Content):
187187
_module_slug = models.SlugField(choices=((m.slug, m.title) for m in ALL.values()))
188+
module = models.ForeignKey('Module', on_delete=models.CASCADE)
188189
order_with_respect_to = '_module_slug'
189190

190191
class Meta:
@@ -194,4 +195,4 @@ def get_absolute_url(self):
194195
return reverse('sections:detail', kwargs={'slug': self.slug})
195196

196197
def parent(self):
197-
return ALL[self._module_slug]
198+
return self.module

‎pythonpro/modules/modules_views.py‎

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,16 +2,13 @@
22
from django.shortcuts import render
33

44
# Create your views here.
5-
from pythonpro.modules import models
65
from pythonpro.modules.facade import get_module_sections, get_all_modules
76

87

98
@login_required
109
def detail(request, slug):
11-
module = models.ALL[slug]
12-
module.sections = get_module_sections(module)
13-
ctx = dict(module=module)
14-
return render(request, 'modules/module_detail.html', context=ctx)
10+
module = get_module_sections(slug)
11+
return render(request, 'modules/module_detail.html', {'module': module})
1512

1613

1714
def index(request):

‎pythonpro/modules/tests/test_module_detail_view.py‎

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,26 @@
11
import pytest
2+
from django.core.management import call_command
23
from django.urls import reverse
34
from model_mommy import mommy
45

56
from pythonpro.django_assertions import dj_assert_contains
6-
from pythonpro.modules.models import Section, PYTHON_BIRDS
7+
from pythonpro.modules import facade
8+
from pythonpro.modules.models import Section, PYTHON_BIRDS, Module
79

810

911
def generate_resp(slug, client):
1012
return client.get(reverse('modules:detail', kwargs={'slug': slug}))
1113

1214

1315
@pytest.fixture
14-
def client_with_user(client, django_user_model):
16+
def modules(transactional_db):
17+
call_command('loaddata', 'pythonpro_modules.json')
18+
modules = facade.get_all_modules()
19+
return modules
20+
21+
22+
@pytest.fixture
23+
def client_with_user(client, django_user_model, modules):
1524
user = mommy.make(django_user_model)
1625
client.force_login(user)
1726
return client
@@ -62,7 +71,7 @@ def test_page_content_with_pre_requisite(content, client_with_user):
6271

6372
@pytest.fixture
6473
def sections(transactional_db):
65-
return mommy.make(Section, 2, _module_slug=PYTHON_BIRDS.slug)
74+
return mommy.make(Section, 2, module=Module.objects.filter(slug='python-birds').get())
6675

6776

6877
@pytest.fixture

‎pythonpro/modules/tests/test_module_index_view.py‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@
1111
def modules(transactional_db):
1212
call_command('loaddata', 'pythonpro_modules.json')
1313
modules = facade.get_all_modules()
14-
assert len(modules) > 0
1514
return modules
1615

1716

‎pythonpro/modules/tests/test_sections_view.py‎

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,17 @@
33
from model_mommy import mommy
44

55
from pythonpro.django_assertions import dj_assert_contains
6-
from pythonpro.modules.models import Section, PYTHON_BIRDS
6+
from pythonpro.modules.models import Section, Module
77

88

99
@pytest.fixture
10-
def section():
11-
return mommy.make(Section, slug='procedural', _module_slug=PYTHON_BIRDS.slug)
10+
def module():
11+
return mommy.make(Module)
12+
13+
14+
@pytest.fixture
15+
def section(module):
16+
return mommy.make(Section, slug='procedural', module=module)
1217

1318

1419
@pytest.fixture
@@ -27,10 +32,10 @@ def test_title(resp, section, property_name):
2732
dj_assert_contains(resp, getattr(section, property_name))
2833

2934

30-
def test_breadcrumb_parent(resp):
35+
def test_breadcrumb_parent(resp, module):
3136
dj_assert_contains(
3237
resp,
33-
'<li class="breadcrumb-item"><a href="/modulos/python-birds/">Python Birds</a></li>'
38+
f'<li class="breadcrumb-item"><a href="{module.get_absolute_url()}">{module.title}</a></li>'
3439
)
3540

3641

0 commit comments

Comments
 (0)