diff options
author | luxagraf <sng@luxagraf.net> | 2020-08-15 11:58:34 -0400 |
---|---|---|
committer | luxagraf <sng@luxagraf.net> | 2020-08-15 11:58:34 -0400 |
commit | b66d000ee469539ce7aea557b612c0444177e36d (patch) | |
tree | 273547921dc6f9ded2a5681b82514c68e28ba448 /app/unused_apps | |
parent | d3e57c1bd17ad3e71810235a672d4782136901a5 (diff) |
archived old unused apps and migrated fieldnotes to posts
Diffstat (limited to 'app/unused_apps')
63 files changed, 2742 insertions, 0 deletions
diff --git a/app/unused_apps/expenses/__init__.py b/app/unused_apps/expenses/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/expenses/__init__.py diff --git a/app/unused_apps/expenses/admin.py b/app/unused_apps/expenses/admin.py new file mode 100644 index 0000000..a754883 --- /dev/null +++ b/app/unused_apps/expenses/admin.py @@ -0,0 +1,25 @@ +from django.contrib import admin + +from .models import LuxExpense, Trip, Expense, Month + + +@admin.register(Trip) +class TripAdmin(admin.ModelAdmin): + list_display = ('name', 'start') + + +@admin.register(Expense) +class ExpenseAdmin(admin.ModelAdmin): + list_display = ('name', 'category', 'amount', 'date_month') + list_filter = ('date', 'category') + + +@admin.register(LuxExpense) +class LuxExpenseAdmin(admin.ModelAdmin): + list_display = ('category', 'amount', 'month') + list_filter = ('month', 'category') + + +@admin.register(Month) +class MonthAdmin(admin.ModelAdmin): + pass diff --git a/app/unused_apps/expenses/build.py b/app/unused_apps/expenses/build.py new file mode 100644 index 0000000..7241a70 --- /dev/null +++ b/app/unused_apps/expenses/build.py @@ -0,0 +1,34 @@ +import os +from django.core.urlresolvers import reverse +from builder.base import BuildNew + + +class BuildExpenses(BuildNew): + + def build(self): + self.build_detail_view() + self.build_list_view( + base_path=reverse("expenses:list_trip"), + paginate_by=24 + ) + + def get_model_queryset(self): + return self.model.objects.all() + + def build_detail_view(self): + ''' + write out all the expenses for each trip + ''' + for obj in self.get_model_queryset(): + url = obj.get_absolute_url() + path, slug = os.path.split(url) + path = '%s/' % path + # write html + response = self.client.get(url) + print(path, slug) + self.write_file(path, response.content, filename=slug) + + +def builder(): + j = BuildExpenses("expenses", "trip") + j.build() diff --git a/app/unused_apps/expenses/migrations/0001_initial.py b/app/unused_apps/expenses/migrations/0001_initial.py new file mode 100644 index 0000000..5ff70cd --- /dev/null +++ b/app/unused_apps/expenses/migrations/0001_initial.py @@ -0,0 +1,48 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-04-28 22:47 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Expense', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('amount', models.DecimalField(decimal_places=2, max_digits=8)), + ('date', models.DateTimeField(default=django.utils.timezone.now)), + ('notes', models.TextField(blank=True, null=True)), + ('category', models.CharField(choices=[('1', 'Groceries'), ('2', 'Restaurants'), ('3', 'Camping'), ('4', 'Petrol'), ('5', 'Bus'), ('6', 'Misc')], default=1, max_length=2)), + ], + options={ + 'ordering': ('-date',), + }, + ), + migrations.CreateModel( + name='Trip', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('slug', models.SlugField()), + ('start', models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True)), + ('end', models.DateTimeField(blank=True, default=django.utils.timezone.now, null=True)), + ('dek', models.TextField(blank=True, null=True)), + ], + ), + migrations.AddField( + model_name='expense', + name='trip', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='expenses.Trip'), + ), + ] diff --git a/app/unused_apps/expenses/migrations/0002_luxexpense.py b/app/unused_apps/expenses/migrations/0002_luxexpense.py new file mode 100644 index 0000000..9edfdb4 --- /dev/null +++ b/app/unused_apps/expenses/migrations/0002_luxexpense.py @@ -0,0 +1,26 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-04-28 22:48 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('expenses', '0001_initial'), + ] + + operations = [ + migrations.CreateModel( + name='LuxExpense', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('category', models.CharField(choices=[('1', 'Groceries'), ('2', 'Restaurants'), ('3', 'Camping'), ('4', 'Petrol'), ('5', 'Bus'), ('6', 'Misc')], default=1, max_length=2)), + ('amount', models.DecimalField(decimal_places=2, max_digits=8)), + ('date', models.DateTimeField(default=django.utils.timezone.now)), + ('notes', models.TextField(blank=True, null=True)), + ], + ), + ] diff --git a/app/unused_apps/expenses/migrations/0003_auto_20170429_0748.py b/app/unused_apps/expenses/migrations/0003_auto_20170429_0748.py new file mode 100644 index 0000000..69f14ec --- /dev/null +++ b/app/unused_apps/expenses/migrations/0003_auto_20170429_0748.py @@ -0,0 +1,40 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2017-04-29 07:48 +from __future__ import unicode_literals + +from django.db import migrations, models +import django.db.models.deletion +import django.utils.timezone + + +class Migration(migrations.Migration): + + dependencies = [ + ('expenses', '0002_luxexpense'), + ] + + operations = [ + migrations.CreateModel( + name='Month', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('year', models.IntegerField()), + ('date', models.DateTimeField(default=django.utils.timezone.now)), + ('notes', models.TextField(blank=True, null=True)), + ], + ), + migrations.RemoveField( + model_name='luxexpense', + name='date', + ), + migrations.RemoveField( + model_name='luxexpense', + name='notes', + ), + migrations.AddField( + model_name='luxexpense', + name='month', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='expenses.Month'), + ), + ] diff --git a/app/unused_apps/expenses/migrations/__init__.py b/app/unused_apps/expenses/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/expenses/migrations/__init__.py diff --git a/app/unused_apps/expenses/models.py b/app/unused_apps/expenses/models.py new file mode 100644 index 0000000..fbcdd7a --- /dev/null +++ b/app/unused_apps/expenses/models.py @@ -0,0 +1,62 @@ +from django.db import models +from django.urls import reverse +from django.utils import timezone + +CATS = ( + ('1', "Groceries"), + ('2', "Restaurants"), + ('3', "Camping"), + ('4', "Petrol"), + ('5', "Bus"), + ('6', "Misc"), +) + + +class Trip(models.Model): + name = models.CharField(max_length=200) + slug = models.SlugField() + start = models.DateTimeField(default=timezone.now, blank=True, null=True) + end = models.DateTimeField(default=timezone.now, blank=True, null=True) + dek = models.TextField(null=True, blank=True) + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse("expenses:list_expense", kwargs={"slug": self.slug}) + +class Month(models.Model): + name = models.CharField(max_length=200) + year = models.IntegerField() + date = models.DateTimeField(default=timezone.now) + notes = models.TextField(null=True, blank=True) + + def __str__(self): + return "%s %s" %(self.name, self.year) + +class LuxExpense(models.Model): + category = models.CharField(max_length=2, choices=CATS, default=1) + amount = models.DecimalField(max_digits=8, decimal_places=2) + month = models.ForeignKey(Month, on_delete=models.CASCADE, null=True) + + def __str__(self): + return '%s-%s' %(self.month, self.get_category_display()) + + + +class Expense(models.Model): + name = models.CharField(max_length=200) + amount = models.DecimalField(max_digits=8, decimal_places=2) + date = models.DateTimeField(default=timezone.now) + notes = models.TextField(null=True, blank=True) + category = models.CharField(max_length=2, choices=CATS, default=1) + trip = models.ForeignKey(Trip, on_delete=models.CASCADE, null=True) + + class Meta: + ordering = ('-date',) + + def __str__(self): + return self.name + + def date_month(self): + return self.date.strftime("%b %Y") diff --git a/app/unused_apps/expenses/urls.py b/app/unused_apps/expenses/urls.py new file mode 100644 index 0000000..6ad732e --- /dev/null +++ b/app/unused_apps/expenses/urls.py @@ -0,0 +1,22 @@ +from django.conf.urls import url +from . import views + +app_name = "expenses" + +urlpatterns = [ + #url( + # r'(?P<slug>[-\w]+)$', + # views.ExpenseListView.as_view(), + # name='list_expense' + #), + url( + r'(?P<slug>[-\w]+)$', + views.LuxExpenseListView.as_view(), + name='list_expense' + ), + url( + r'^$', + views.TripListView.as_view(), + name='list_trip' + ) +] diff --git a/app/unused_apps/expenses/views.py b/app/unused_apps/expenses/views.py new file mode 100644 index 0000000..98a4c70 --- /dev/null +++ b/app/unused_apps/expenses/views.py @@ -0,0 +1,38 @@ +from django.views.generic import ListView + +from .models import LuxExpense, Expense, Trip, CATS + +class ExpenseListView(ListView): + model = Expense + context_object_name = 'object_list' + template_name = 'details/expenses.html' + + def get_queryset(self): + return Expense.objects.filter( + trip__slug=self.kwargs['slug'] + ) + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(ExpenseListView, self).get_context_data(**kwargs) + context['categories'] = CATS + return context + +class LuxExpenseListView(ListView): + model = LuxExpense + context_object_name = 'object_list' + template_name = 'details/expenses.html' + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(LuxExpenseListView, self).get_context_data(**kwargs) + context['categories'] = CATS + return context + +class TripListView(ListView): + model = Trip + context_object_name = 'object_list' + template_name = 'archives/expenses.html' + + def get_queryset(self): + return Trip.objects.all() diff --git a/app/unused_apps/garden/admin.py b/app/unused_apps/garden/admin.py new file mode 100644 index 0000000..0f9c8d0 --- /dev/null +++ b/app/unused_apps/garden/admin.py @@ -0,0 +1,38 @@ +from django.contrib import admin +from django.contrib.contenttypes.admin import GenericStackedInline + +from utils.widgets import AdminImageWidget, LGEntryForm +from .models import Plant, Planting, Seed + + +@admin.register(Plant) +class PlantAdmin(admin.ModelAdmin): + form = LGEntryForm + + list_display = ('name', 'family', 'growth_time') + list_filter = ('family', 'edible', 'conditions', 'heirloom') + + class Media: + js = ('image-loader.js', 'next-prev-links.js') + css = { + "all": ("my_styles.css",) + } + + +@admin.register(Planting) +class PlantingAdmin(admin.ModelAdmin): + form = LGEntryForm + + list_display = ('plant', 'family', 'number_of_plants', 'date_seed_started', 'date_seed_sprouted', 'date_hardened_off', 'date_planted', 'seed_start_area','garden_area', 'outcome') + list_filter = ('plant__family', 'date_seed_started', 'garden_area', 'seed_start_area', 'outcome') + + class Media: + js = ('image-loader.js', 'next-prev-links.js') + css = { + "all": ("my_styles.css",) + } + + +@admin.register(Seed) +class PlantAdmin(admin.ModelAdmin): + form = LGEntryForm diff --git a/app/unused_apps/garden/migrations/0001_initial.py b/app/unused_apps/garden/migrations/0001_initial.py new file mode 100644 index 0000000..d73d80d --- /dev/null +++ b/app/unused_apps/garden/migrations/0001_initial.py @@ -0,0 +1,91 @@ +# Generated by Django 2.1.2 on 2020-07-05 16:18 + +import datetime +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Guild', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(blank=True, max_length=200)), + ('seperation', models.PositiveIntegerField()), + ('notes', models.TextField(blank=True, null=True)), + ], + ), + migrations.CreateModel( + name='Plant', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=200)), + ('scientific_name', models.CharField(max_length=200)), + ('edible', models.BooleanField(default=False)), + ('date_created', models.DateTimeField(default=datetime.datetime.now)), + ('growth_time', models.PositiveIntegerField()), + ('germination_time', models.PositiveIntegerField()), + ('seperation', models.PositiveIntegerField()), + ('notes', models.TextField(blank=True, null=True)), + ('conditions', models.IntegerField(choices=[(0, 'Direct Sun'), (1, 'Part Sun'), (2, 'Shade')], default=0)), + ('organic', models.BooleanField(default=True)), + ('heirloom', models.BooleanField(default=True)), + ], + options={ + 'ordering': ('-date_created',), + 'get_latest_by': 'date_created', + }, + ), + migrations.CreateModel( + name='Planting', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('seed_start_area', models.IntegerField(choices=[(0, 'Indoors'), (1, 'Direct Sow'), (2, 'Greenhouse')], default=0)), + ('date_seed_started', models.DateField(verbose_name='Date published')), + ('date_seed_sprouted', models.DateField(verbose_name='Date published')), + ('date_hardened_off', models.DateField(verbose_name='Date published')), + ('date_planted', models.DateField(verbose_name='Date published')), + ('garden_area', models.IntegerField(choices=[(0, 'Far Plot Mound'), (1, 'Far Plot ground'), (2, 'Herb Plot half mound')], default=0)), + ('notes', models.TextField(blank=True, null=True)), + ('plant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='garden.Plant')), + ], + options={ + 'ordering': ('-date_seed_started',), + 'get_latest_by': 'date_seed_started', + }, + ), + migrations.CreateModel( + name='Seed', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('brand', models.CharField(max_length=200)), + ('date_created', models.DateTimeField(default=datetime.datetime.now)), + ('estimated_growth_time', models.PositiveIntegerField()), + ('estimated_germination_time', models.PositiveIntegerField()), + ('organic', models.BooleanField(default=True)), + ('notes', models.TextField(blank=True, null=True)), + ('plant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='garden.Plant')), + ], + options={ + 'ordering': ('-date_created',), + 'get_latest_by': 'date_created', + }, + ), + migrations.AddField( + model_name='planting', + name='seed', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='garden.Seed'), + ), + migrations.AddField( + model_name='guild', + name='plant', + field=models.ManyToManyField(to='garden.Plant'), + ), + ] diff --git a/app/unused_apps/garden/migrations/0002_plant_family.py b/app/unused_apps/garden/migrations/0002_plant_family.py new file mode 100644 index 0000000..db81791 --- /dev/null +++ b/app/unused_apps/garden/migrations/0002_plant_family.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2020-07-05 16:27 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0001_initial'), + ] + + operations = [ + migrations.AddField( + model_name='plant', + name='family', + field=models.IntegerField(choices=[(0, 'Tomatoes'), (1, 'Cucumbers'), (2, 'Watermelons'), (3, 'Pumkins'), (4, 'Basil')], default=0), + ), + ] diff --git a/app/unused_apps/garden/migrations/0003_auto_20200705_1629.py b/app/unused_apps/garden/migrations/0003_auto_20200705_1629.py new file mode 100644 index 0000000..ed0eb01 --- /dev/null +++ b/app/unused_apps/garden/migrations/0003_auto_20200705_1629.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2020-07-05 16:29 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0002_plant_family'), + ] + + operations = [ + migrations.AlterField( + model_name='plant', + name='scientific_name', + field=models.CharField(max_length=200, null=True), + ), + ] diff --git a/app/unused_apps/garden/migrations/0004_auto_20200705_1650.py b/app/unused_apps/garden/migrations/0004_auto_20200705_1650.py new file mode 100644 index 0000000..6e9ea63 --- /dev/null +++ b/app/unused_apps/garden/migrations/0004_auto_20200705_1650.py @@ -0,0 +1,59 @@ +# Generated by Django 2.1.2 on 2020-07-05 16:50 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0003_auto_20200705_1629'), + ] + + operations = [ + migrations.AddField( + model_name='planting', + name='number_of_plants', + field=models.PositiveIntegerField(default=1), + preserve_default=False, + ), + migrations.AddField( + model_name='planting', + name='outcome', + field=models.IntegerField(choices=[(0, 'Far Plot Mound'), (1, 'Far Plot ground'), (2, 'Herb Plot ground'), (2, 'Herb Plot bed')], default=0), + ), + migrations.AlterField( + model_name='plant', + name='scientific_name', + field=models.CharField(blank=True, max_length=200, null=True), + ), + migrations.AlterField( + model_name='planting', + name='date_hardened_off', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='planting', + name='date_planted', + field=models.DateField(), + ), + migrations.AlterField( + model_name='planting', + name='date_seed_sprouted', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='planting', + name='date_seed_started', + field=models.DateField(blank=True, null=True), + ), + migrations.AlterField( + model_name='planting', + name='garden_area', + field=models.IntegerField(choices=[(0, 'Far Plot Mound'), (1, 'Far Plot ground'), (2, 'Herb Plot ground'), (2, 'Herb Plot bed')], default=0), + ), + migrations.AlterField( + model_name='planting', + name='seed_start_area', + field=models.IntegerField(choices=[(0, 'Indoors'), (1, 'Direct Sow'), (2, 'Greenhouse'), (2, 'Purchased Seedling')], default=0), + ), + ] diff --git a/app/unused_apps/garden/migrations/0005_auto_20200705_1652.py b/app/unused_apps/garden/migrations/0005_auto_20200705_1652.py new file mode 100644 index 0000000..22bebaf --- /dev/null +++ b/app/unused_apps/garden/migrations/0005_auto_20200705_1652.py @@ -0,0 +1,24 @@ +# Generated by Django 2.1.2 on 2020-07-05 16:52 + +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0004_auto_20200705_1650'), + ] + + operations = [ + migrations.AlterField( + model_name='planting', + name='outcome', + field=models.IntegerField(choices=[(0, 'Unknown'), (1, 'Success'), (2, 'Moderate Success'), (3, 'Fail')], default=0), + ), + migrations.AlterField( + model_name='planting', + name='seed', + field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='garden.Seed'), + ), + ] diff --git a/app/unused_apps/garden/migrations/0006_auto_20200706_0854.py b/app/unused_apps/garden/migrations/0006_auto_20200706_0854.py new file mode 100644 index 0000000..a036635 --- /dev/null +++ b/app/unused_apps/garden/migrations/0006_auto_20200706_0854.py @@ -0,0 +1,23 @@ +# Generated by Django 2.1.2 on 2020-07-06 08:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0005_auto_20200705_1652'), + ] + + operations = [ + migrations.AddField( + model_name='plant', + name='annual', + field=models.BooleanField(default=True), + ), + migrations.AlterField( + model_name='plant', + name='family', + field=models.IntegerField(choices=[(0, 'Tomatoes'), (1, 'Cucumbers'), (2, 'Watermelons'), (3, 'Pumkins'), (4, 'Cantelope'), (5, 'Kale'), (6, 'Okra'), (7, 'Collards'), (8, 'Arugula'), (9, 'Butter Lettuce'), (10, 'Basil'), (11, 'Lemongrass'), (12, 'Thyme'), (13, 'Mint')], default=0), + ), + ] diff --git a/app/unused_apps/garden/migrations/0007_auto_20200706_0854.py b/app/unused_apps/garden/migrations/0007_auto_20200706_0854.py new file mode 100644 index 0000000..94f85e7 --- /dev/null +++ b/app/unused_apps/garden/migrations/0007_auto_20200706_0854.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2020-07-06 08:54 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('garden', '0006_auto_20200706_0854'), + ] + + operations = [ + migrations.AlterField( + model_name='plant', + name='conditions', + field=models.IntegerField(choices=[(0, 'Vegetable'), (1, 'Herb'), (2, 'Berry'), (3, 'Nut')], default=0), + ), + ] diff --git a/app/unused_apps/garden/migrations/__init__.py b/app/unused_apps/garden/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/garden/migrations/__init__.py diff --git a/app/unused_apps/garden/models.py b/app/unused_apps/garden/models.py new file mode 100644 index 0000000..56e8c30 --- /dev/null +++ b/app/unused_apps/garden/models.py @@ -0,0 +1,153 @@ +import datetime + +from django.contrib.gis.db import models + +from utils.util import render_images, markdown_to_html + + +PLANT_FAMILY = ( + (0, 'Tomatoes'), + (1, 'Cucumbers'), + (2, 'Watermelons'), + (3, 'Pumkins'), + (4, 'Cantelope'), + (5, 'Kale'), + (6, 'Okra'), + (7, 'Collards'), + (8, 'Arugula'), + (9, 'Butter Lettuce'), + (10, 'Basil'), + (11, 'Lemongrass'), + (12, 'Thyme'), + (13, 'Mint'), +) + + +class Plant(models.Model): + """ + Model to hold Plant Definitions + """ + name = models.CharField(max_length=200) + family = models.IntegerField(choices=PLANT_FAMILY, default=0) + scientific_name = models.CharField(max_length=200, null=True, blank=True) + edible = models.BooleanField(default=False) + date_created = models.DateTimeField(default=datetime.datetime.now) + growth_time = models.PositiveIntegerField() + germination_time = models.PositiveIntegerField() + seperation = models.PositiveIntegerField() + notes = models.TextField(null=True, blank=True) + CONDITIONS = ( + (0, 'Direct Sun'), + (1, 'Part Sun'), + (2, 'Shade'), + ) + conditions = models.IntegerField(choices=CONDITIONS, default=0) + PLANT_TYPE= ( + (0, 'Vegetable'), + (1, 'Herb'), + (2, 'Berry'), + (3, 'Nut'), + ) + conditions = models.IntegerField(choices=PLANT_TYPE, default=0) + organic = models.BooleanField(default=True) + heirloom = models.BooleanField(default=True) + annual = models.BooleanField(default=True) + + class Meta: + ordering = ('-date_created',) + get_latest_by = 'date_created' + + def __str__(self): + return self.name + + +class Seed(models.Model): + plant = models.ForeignKey(Plant, on_delete=models.CASCADE) + brand = models.CharField(max_length=200) + date_created = models.DateTimeField(default=datetime.datetime.now) + estimated_growth_time = models.PositiveIntegerField() + estimated_germination_time = models.PositiveIntegerField() + organic = models.BooleanField(default=True) + notes = models.TextField(null=True, blank=True) + + class Meta: + ordering = ('-date_created',) + get_latest_by = 'date_created' + + def __str__(self): + return self.plant.name + + +class Planting(models.Model): + plant = models.ForeignKey(Plant, on_delete=models.CASCADE) + number_of_plants = models.PositiveIntegerField() + seed = models.ForeignKey(Seed, on_delete=models.CASCADE, null=True, blank=True) + START_AREA = ( + (0, 'Indoors'), + (1, 'Direct Sow'), + (2, 'Greenhouse'), + (2, 'Purchased Seedling'), + ) + seed_start_area = models.IntegerField(choices=START_AREA, default=0) + date_seed_started = models.DateField(null=True, blank=True) + date_seed_sprouted = models.DateField(null=True, blank=True) + date_hardened_off = models.DateField(null=True, blank=True) + date_planted = models.DateField() + GARDEN_PLOT = ( + (0, 'Far Plot Mound'), + (1, 'Far Plot ground'), + (2, 'Herb Plot ground'), + (2, 'Herb Plot bed'), + ) + garden_area = models.IntegerField(choices=GARDEN_PLOT, default=0) + OUTCOME = ( + (0, 'Unknown'), + (1, 'Success'), + (2, 'Moderate Success'), + (3, 'Fail'), + ) + outcome = models.IntegerField(choices=OUTCOME, default=0) + notes = models.TextField(null=True, blank=True) + + class Meta: + ordering = ('-date_seed_started',) + get_latest_by = 'date_seed_started' + + def __str__(self): + return self.plant.name + + @property + def get_previous_admin_url(self): + n = self.get_previous_by_pub_date() + return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[n.id] ) + + @property + def get_next_admin_url(self): + model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name) + try: + return reverse('admin:%s_%s_change' %(self._meta.app_label, self._meta.model_name), args=[self.get_next_by_pub_date().pk] ) + except model.DoesNotExist: + return '' + + + @property + def family(self): + return self.plant.get_family_display() + + + def save(self, *args, **kwargs): + created = self.pk is None + if not created: + md = render_images(self.notes) + self.body_html = markdown_to_html(md) + super(Planting, self).save(*args, **kwargs) + + +class Guild(models.Model): + name = models.CharField(max_length=200, blank=True) + plant = models.ManyToManyField(Plant) + seperation = models.PositiveIntegerField() + notes = models.TextField(null=True, blank=True) + + def __str__(self): + return self.name diff --git a/app/unused_apps/notes/__init__.py b/app/unused_apps/notes/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/notes/__init__.py diff --git a/app/unused_apps/notes/admin.py b/app/unused_apps/notes/admin.py new file mode 100644 index 0000000..eafd0dc --- /dev/null +++ b/app/unused_apps/notes/admin.py @@ -0,0 +1,28 @@ +from django.contrib import admin +from notes.models import Note +from utils.widgets import LGEntryForm, OLAdminBase + + +@admin.register(Note) +class NoteAdmin(OLAdminBase): + form = LGEntryForm + prepopulated_fields = {"slug": ('title',)} + list_display = ('slug', 'pub_date') + fieldsets = ( + ('Note', { + 'fields': ( + ('title', 'slug'), + 'body_markdown', + 'pub_date', + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ) + + class Media: + js = ('image-loader.js', 'next-prev-links.js') diff --git a/app/unused_apps/notes/build.py b/app/unused_apps/notes/build.py new file mode 100644 index 0000000..dc0654e --- /dev/null +++ b/app/unused_apps/notes/build.py @@ -0,0 +1,36 @@ +import os +from django.urls import reverse +from builder.base import BuildNew + + +class BuildNotes(BuildNew): + + def build(self): + self.build_detail_view() + self.build_list_view( + base_path=reverse("notes:live_redirect"), + paginate_by=24 + ) + self.build_year_view("notes:list_year") + self.build_month_view("notes:list_month") + + def get_model_queryset(self): + return self.model.objects.all() + + def build_detail_view(self): + ''' + write out all the expenses for each trip + ''' + for obj in self.get_model_queryset(): + url = obj.get_absolute_url() + path, slug = os.path.split(url) + path = '%s/' % path + # write html + response = self.client.get(url) + print(path, slug) + self.write_file(path, response.content, filename=slug) + + +def builder(): + j = BuildNotes("notes", "luxnote") + j.build() diff --git a/app/unused_apps/notes/migrations/0001_initial.py b/app/unused_apps/notes/migrations/0001_initial.py new file mode 100644 index 0000000..ea67ad1 --- /dev/null +++ b/app/unused_apps/notes/migrations/0001_initial.py @@ -0,0 +1,26 @@ +# Generated by Django 2.0.1 on 2018-05-09 09:35 + +from django.db import migrations, models +import django.utils.timezone + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Note', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(blank=True, max_length=250, null=True)), + ('slug', models.SlugField(blank=True, unique_for_date='pub_date')), + ('pub_date', models.DateTimeField(default=django.utils.timezone.now)), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField(verbose_name='Note')), + ], + ), + ] diff --git a/app/unused_apps/notes/migrations/__init__.py b/app/unused_apps/notes/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/notes/migrations/__init__.py diff --git a/app/unused_apps/notes/models.py b/app/unused_apps/notes/models.py new file mode 100644 index 0000000..8735056 --- /dev/null +++ b/app/unused_apps/notes/models.py @@ -0,0 +1,50 @@ +from django import forms +from django.contrib.gis.db import models +from django.utils import timezone +from django.conf import settings +from django.urls import reverse +from locations.models import Location + +from locations.models import CheckIn +from utils.util import markdown_to_html, render_images + + +class Note(models.Model): + title = models.CharField(max_length=250, null=True, blank=True) + slug = models.SlugField(unique_for_date='pub_date', blank=True) + pub_date = models.DateTimeField(default=timezone.now) + body_html = models.TextField(blank=True) + body_markdown = models.TextField('Note') + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("notes:detail", kwargs={"year": self.pub_date.year, "month": self.pub_date.strftime("%m"), "slug": self.slug}) + + @property + def region(self): + return self.location.state.country.lux_region + + @property + def longitude(self): + '''Get the site's longitude.''' + return round(self.point.x, 2) + + @property + def latitude(self): + '''Get the site's latitude.''' + return round(self.point.y, 2) + + @property + def get_previous_published(self): + return self.get_previous_by_pub_date() + + @property + def get_next_published(self): + return self.get_next_by_pub_date() + + def save(self, *args, **kwargs): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(Note, self).save() diff --git a/app/unused_apps/notes/urls.py b/app/unused_apps/notes/urls.py new file mode 100644 index 0000000..3c47c3d --- /dev/null +++ b/app/unused_apps/notes/urls.py @@ -0,0 +1,55 @@ +from django.conf.urls import url +from django.views.generic.base import RedirectView + +from . import views + +app_name = "notes" + +urlpatterns = [ + url( + r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+).txt$', + views.NoteDetailViewTXT.as_view(), + name="detail-txt" + ), + url( + r'(?P<year>\d{4})/(?P<month>\d{2})/(?P<slug>[-\w]+)$', + views.NoteDetailView.as_view(), + name="detail" + ), + url( + r'^(?P<year>[0-9]{4})/(?P<month>[0-9]{2})/$', + views.NoteMonthArchiveView.as_view(month_format='%m'), + name="list_month" + ), + url( + r'(?P<year>\d{4})/$', + views.NoteYearArchiveView.as_view(), + name="list_year" + ), + url( + r'(?P<year>\d{4})/(?P<month>\d{2})/$', + views.date_list, + name="notes_by_month" + ), + url( + r'(?P<year>\d{4})/$', + views.date_list, + name="notes_by_year" + ), + url( + r'(?P<page>\d+)/$', + views.NoteList.as_view(), + name="list" + ), + # redirect / to /1/ for live server + url( + r'', + RedirectView.as_view(url="/field-notes/1/", permanent=False), + name="live_redirect" + ), + url( + r'^$', + views.entry_list, + name="notes_archive" + ), +] diff --git a/app/unused_apps/notes/views.py b/app/unused_apps/notes/views.py new file mode 100644 index 0000000..05fe18e --- /dev/null +++ b/app/unused_apps/notes/views.py @@ -0,0 +1,39 @@ +from django.views.generic.dates import YearArchiveView, MonthArchiveView +from django.views.generic.detail import DetailView + +from utils.views import PaginatedListView + +from notes.models import Note + + +class NoteList(PaginatedListView): + """ + Return a list of Notes in reverse chronological order + """ + queryset = Note.objects.all().order_by('-pub_date') + template_name = "archives/notes.html" + + +class NoteDetailView(DetailView): + model = Note + template_name = "details/note.html" + slug_field = "slug" + + +class NoteDetailViewTXT(NoteDetailView): + template_name = "details/entry.txt" + + +class NoteYearArchiveView(YearArchiveView): + queryset = Note.objects.all() + date_field = "pub_date" + make_object_list = True + allow_future = True + template_name = "archives/notes_date.html" + + +class NoteMonthArchiveView(MonthArchiveView): + queryset = Note.objects.all() + date_field = "pub_date" + allow_future = True + template_name = "archives/notes_date.html" diff --git a/app/unused_apps/projects/__init__.py b/app/unused_apps/projects/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/projects/__init__.py diff --git a/app/unused_apps/projects/admin.py b/app/unused_apps/projects/admin.py new file mode 100644 index 0000000..040b867 --- /dev/null +++ b/app/unused_apps/projects/admin.py @@ -0,0 +1,135 @@ +from django.contrib import admin +from django.contrib.gis.admin import OSMGeoAdmin + +from projects.models.base import Project +from projects.models.fiveby import FiveBy +from projects.models.natparks import NationalParks +from projects.models.gifs import AnimatedGif +from projects.models.self_experiments import Experiment + + +class ProjectAdmin(OSMGeoAdmin): + list_display = ('title', 'pub_date', 'status',) + search_fields = ['title', 'body_markdown'] + prepopulated_fields = {"slug": ('title',)} + list_filter = ('pub_date', 'status') + fieldsets = ( + ('Project', { + 'fields': ( + 'title', + 'subtitle', + 'lede', + 'pub_date', + 'model_name', + ('status', 'image'), + 'slug', + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), + ) + + class Media: + js = ['/media/admin/custom/model.js'] + + +class FiveByAdmin(OSMGeoAdmin): + list_display = ('title', 'pub_date', 'status',) + search_fields = ['title'] + prepopulated_fields = {"slug": ('title',)} + list_filter = ('pub_date', 'status') + fieldsets = ( + ('Project', {'fields': ('title', 'lede', 'pub_date', 'status', ('image', 'videoh264', 'videoogg'), 'slug', ('vimeo_link', 'youtube_link'), ('point', 'location', 'region')), 'classes': ('show', 'extrapretty', 'wide')}), + ) + + # options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 + default_zoom = 6 + units = True + scrollable = False + map_width = 700 + map_height = 425 + map_template = 'gis/admin/osm.html' + + +class NationalParksAdmin(OSMGeoAdmin): + list_display = ('unit_name', 'type', 'state', 'name', 'visited', 'size') + list_filter = ('state', 'type') + search_fields = ['name'] + fieldsets = ( + ('Project', { + 'fields': ( + 'name', + 'tag_line', + ('state', 'visited'), + 'dek', + 'date_visited_begin', + 'date_visited_end', + 'mpoly', + 'image', + ('post', 'gallery'), + ('url', 'size', 'fee', 'camping_fee', 'date_park_created'), + 'zoom' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + }), + ) + + # options for OSM map Using custom ESRI topo map + default_lon = -9285175 + default_lat = 4025046 + default_zoom = 6 + units = True + scrollable = False + map_width = 700 + map_height = 425 + map_template = 'gis/admin/osm.html' + + +class AnimatedGifAdmin(admin.ModelAdmin): + list_display = ('title', 'date_created') + search_fields = ['title'] + fieldsets = ( + (None, { + 'fields': ( + 'title', + 'gif', + 'date_created', + 'slug', + 'music_ogg', + 'music_mp3' + ) + }), + ) + + +class ExperimentAdmin(admin.ModelAdmin): + list_display = ('title', 'date_start', 'date_end_projected', 'days_remaining') + search_fields = ['title'] + fieldsets = ( + (None, { + 'fields': ( + 'title', + 'slug', + 'body_markdown', + ('date_start', 'duration', 'date_end_projected'), + 'date_end_actual', + 'status' + ) + }), + ) + + +admin.site.register(Experiment, ExperimentAdmin) +admin.site.register(AnimatedGif, AnimatedGifAdmin) +admin.site.register(Project, ProjectAdmin) +admin.site.register(FiveBy, FiveByAdmin) +admin.site.register(NationalParks, NationalParksAdmin) diff --git a/app/unused_apps/projects/models/__init__.py b/app/unused_apps/projects/models/__init__.py new file mode 100644 index 0000000..3230ff4 --- /dev/null +++ b/app/unused_apps/projects/models/__init__.py @@ -0,0 +1,5 @@ +from .base import Project +from .fiveby import FiveBy +from .natparks import NationalParks +from .gifs import AnimatedGif +from .self_experiments import Experiment diff --git a/app/unused_apps/projects/models/base.py b/app/unused_apps/projects/models/base.py new file mode 100644 index 0000000..aa795d2 --- /dev/null +++ b/app/unused_apps/projects/models/base.py @@ -0,0 +1,67 @@ +import datetime +from django.contrib.gis.db import models +from django.contrib.sitemaps import Sitemap +from django.conf import settings + + +def get_upload_path(self, filename): + return "images/project-thumbs/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + +class Project(models.Model): + title = models.CharField(max_length=200) + subtitle = models.CharField(max_length=200, null=True, blank=True) + slug = models.CharField(max_length=50) + lede = models.TextField(blank=True) + pub_date = models.DateTimeField('Date published') + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + image = models.FileField(upload_to=get_upload_path, null=True, blank=True) + model_name = models.CharField(max_length=200, null=True) + + @property + def longitude(self): + '''Get the site's longitude.''' + return self.point.x + + @property + def latitude(self): + '''Get the site's latitude.''' + return self.point.y + + @property + def get_project_image(self): + return "%s%s" % (settings.IMAGES_URL, self.image.name[7:]) + + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + app_label = 'projects' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return "/%s/" % (self.slug) + + def get_previous_published(self): + return self.get_previous_by_pub_date(status__exact=1) + + def get_next_published(self): + return self.get_next_by_pub_date(status__exact=1) + + +class ProjectSitemap(Sitemap): + changefreq = "monthly" + priority = 0.5 + protocol = "https" + + def items(self): + return Project.objects.filter(status=1) + + def lastmod(self, obj): + return obj.pub_date diff --git a/app/unused_apps/projects/models/fiveby.py b/app/unused_apps/projects/models/fiveby.py new file mode 100644 index 0000000..473c095 --- /dev/null +++ b/app/unused_apps/projects/models/fiveby.py @@ -0,0 +1,53 @@ +import datetime +from django.contrib.gis.db import models +from locations.models import Location, Region + + +def get_upload_path(self, filename): + return "images/projects/videos/5x5/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + +def get_image_upload_path(self, filename): + return "images/projects/5x5/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + +class FiveBy(models.Model): + title = models.CharField(max_length=200) + slug = models.SlugField(unique_for_date='pub_date') + lede = models.TextField(blank=True) + image = models.FileField(upload_to=get_image_upload_path, null=True, blank=True) + videoh264 = models.FileField(upload_to=get_upload_path, null=True, blank=True) + videoogg = models.FileField(upload_to=get_upload_path, null=True, blank=True) + vimeo_link = models.CharField(max_length=200) + youtube_link = models.CharField(max_length=200) + pub_date = models.DateTimeField('Date published') + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + point = models.PointField(null=True) + location = models.ForeignKey(Location, on_delete=models.CASCADE, null=True) + region = models.ForeignKey(Region, on_delete=models.CASCADE, null=True) + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + app_label = 'projects' + verbose_name_plural = '5x5' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return "/%s/%s/%s/" % ('projects', '5x5', self.slug) + + @property + def longitude(self): + '''Get the site's longitude.''' + return self.point.x + + @property + def latitude(self): + '''Get the site's latitude.''' + return self.point.y diff --git a/app/unused_apps/projects/models/gifs.py b/app/unused_apps/projects/models/gifs.py new file mode 100644 index 0000000..25b8734 --- /dev/null +++ b/app/unused_apps/projects/models/gifs.py @@ -0,0 +1,26 @@ +import datetime +from django.db import models + + +def get_upload_path(self, filename): + return "images/projects/gifs/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + +class AnimatedGif(models.Model): + title = models.CharField(max_length=254) + gif = models.ImageField(upload_to=get_upload_path) + slug = models.SlugField() + date_created = models.DateField('Date Created') + music_ogg = models.FileField(upload_to=get_upload_path, blank=True, null=True) + music_mp3 = models.FileField(upload_to=get_upload_path, blank=True, null=True) + + class Meta: + verbose_name_plural = "Animated Gifs" + app_label = 'projects' + ordering = ('-date_created',) + + def __str__(self): + return self.slug + + def get_absolute_url(self): + return '/projects/gifs/%s/' % (self.slug) diff --git a/app/unused_apps/projects/models/natparks.py b/app/unused_apps/projects/models/natparks.py new file mode 100644 index 0000000..980d9fa --- /dev/null +++ b/app/unused_apps/projects/models/natparks.py @@ -0,0 +1,55 @@ +import datetime +from PIL import Image +from django.contrib.gis.db import models +from django.conf import settings +from jrnl.models import Entry +from photos.models import PhotoGallery +from locations.models import State + + +def get_upload_path(self, filename): + return "images/projects/np/%s/%s" % (datetime.datetime.today().strftime("%Y"), filename) + + +class NationalParks(models.Model): + type = models.CharField(max_length=50) + name = models.CharField(max_length=254) + state = models.ForeignKey(State, on_delete=models.CASCADE, null=True) + size = models.CharField(max_length=10, null=True) + fee = models.CharField(max_length=5, null=True) + camping_fee = models.CharField(max_length=10, null=True) + url = models.CharField(max_length=250, null=True) + code = models.CharField(max_length=16) + unit_name = models.CharField(max_length=254) + date_visited_begin = models.DateField('Date Visited', null=True) + date_visited_end = models.DateField('Date Visited', null=True) + date_park_created = models.DateField('Date Park Created', null=True) + zoom = models.IntegerField(null=True) + mpoly = models.MultiPolygonField(null=True) + visited = models.BooleanField(default=False) + dek = models.TextField(null=True, blank=True) + tag_line = models.CharField(max_length=254, null=True) + post = models.ForeignKey(Entry, on_delete=models.CASCADE, null=True) + gallery = models.ForeignKey(PhotoGallery, on_delete=models.CASCADE, blank=True, null=True, verbose_name='photo set') + image = models.FileField(upload_to=get_upload_path, null=True, blank=True, + help_text="width: 980px, height: > 450px") + image_height = models.CharField(max_length=20, null=True, blank=True) + image_width = models.CharField(max_length=20, null=True, blank=True) + + class Meta: + verbose_name_plural = "National Parks" + app_label = 'projects' + ordering = ('-visited', 'unit_name',) + + def __str__(self): + return self.unit_name + + @property + def get_image_url(self): + return "%s%s" % (settings.IMAGES_URL, self.image.name[7:]) + + def save(self): + #get image dimensions + img = Image.open(self.image) + self.image_width, self.image_height = img.size + super(NationalParks, self).save() diff --git a/app/unused_apps/projects/models/self_experiments.py b/app/unused_apps/projects/models/self_experiments.py new file mode 100644 index 0000000..be9d0b7 --- /dev/null +++ b/app/unused_apps/projects/models/self_experiments.py @@ -0,0 +1,56 @@ +import datetime +from django.db import models + +import markdown + +PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), +) + + +def markdown_processor(md): + return markdown.markdown(md, ['footnotes'], safe_mode=False) + + +class Experiment(models.Model): + title = models.CharField(max_length=254) + slug = models.SlugField() + date_created = models.DateField(auto_now_add=True) + date_start = models.DateField() + date_end_actual = models.DateField(blank=True, null=True) + date_end_projected = models.DateField(blank=True) + duration = models.PositiveSmallIntegerField(default=30) + status = models.IntegerField(choices=PUB_STATUS, default=0) + body_html = models.TextField(blank=True) + body_markdown = models.TextField() + + class Meta: + app_label = 'projects' + ordering = ('-date_start',) + + # Returns the string representation of the model. + def __str__(self): + return self.title + + def get_absolute_url(self): + return "/projects/experiments/%s/%s/" % (self.pub_date.strftime("%Y").lower(), self.slug) + + def days_remaining(self): + return self.date_end_projected - datetime.date.today() + + @property + def get_previous_published(self): + return self.get_previous_by_pub_date(status__exact=1) + + @property + def get_next_published(self): + return self.get_next_by_pub_date(status__exact=1) + + def comment_period_open(self): + return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date + + def save(self): + self.body_html = markdown_processor(self.body_markdown) + self.date_end_projected = self.date_start + datetime.timedelta(self.duration) + super(Experiment, self).save() diff --git a/app/unused_apps/projects/natparks.js b/app/unused_apps/projects/natparks.js new file mode 100644 index 0000000..8481408 --- /dev/null +++ b/app/unused_apps/projects/natparks.js @@ -0,0 +1,94 @@ +//Utility functions for map info window +function mapit(lat,lon,zoom,id) { + map = L.map(document.getElementById("map-wrapper-"+id)); + centerCoord = new L.LatLng(lat, lon); + zoom = zoom; + L.tileLayer.provider('Esri.WorldTopoMap', {maxZoom: 18, attribution: 'Map data © <a href="http://openstreetmap.org">OpenStreetMap</a> contributors, <a href="http://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Tiles © Esri and the GIS User Community'}).addTo(map); + map.setView(centerCoord, zoom); + ////get the geojson for this map + $.ajax({ + url: "/projects/data/natparks/"+id+".json", + dataType: "json", + success: function(data, text, request) { draw_poly(data, map); } + //complete: function(xhr, status) {console.log(status); return false; }, + }); + //draw the polygon + function draw_poly(data, map) { + var myStyle = { + "color": "#201a11", + "weight": 2, + "opacity": 0.65 + }; + L.geoJson(data, { + style: myStyle + }).addTo(map); + } +} + +// utility functions to create/remove map container +function create_map(obj) { + var lat = parseFloat(obj.attr('data-latitude')); + var lon = parseFloat(obj.attr('data-longitude')); + var zoom= parseInt(obj.attr('data-zoom')); + var id= obj.attr('data-id'); + + //create container divs + $(obj).parents().eq(3).append('<div class="map-container" id="map-container-'+id+'">'); + $('#map-container-'+id).append('<div class="map-wrapper" id="map-wrapper-'+id+'">'); + mapit(lat,lon,zoom,id); +} +function remove_map(id) { + $(id).remove(); +} + +//functions to handle the "more" link +// utility functions to create/remove camera info container +function get_exif(obj,id) { + //$(obj).parents().eq(2).append('<div id="exif-container">'); + $(obj).parents().eq(3).append('<div class="more-container" id="'+id+'">'); $(obj).parents().eq(2).children('.meta').clone().appendTo('#'+id).css('visibility', 'visible'); + + + + //deal with the variable height of div.legend + $('#exif-container').css({ + bottom: function(index, value) { + return parseFloat($(obj).parent().parent().css("height"))-14; + } + }); +} +function remove_exif(id) { + $('#'+id).remove(); +} +$(document).ready(function(){ +//set up click events for map button + $('.map-link').click( function() { + var more_id = 'more-container-'+$(this).parent().next().children('.more-link').attr('id').split('-')[1]; + var id = '#map-container-'+$(this).attr('data-id'); + if ($('#'+more_id).is(":visible")){ + remove_exif(more_id); + } + if ($(id).is(":visible")) { + remove_map(id); + } else { + create_map($(this)); + } + return false; + + }); + + //set up click events for more info button + $('.more-link').click( function() { + var map_id = '#map-container-'+$(this).parent().prev().children('.map-link').attr('data-id'); + var id = 'more-container-'+this.id.split('-')[1]; + if ($(map_id).is(":visible")){ + remove_map(map_id); + } + if ($('#'+id).is(":visible")) { + remove_exif(id); + } else { + get_exif(this, id); + } + return false; + }); + +}); diff --git a/app/unused_apps/projects/shortcuts.py b/app/unused_apps/projects/shortcuts.py new file mode 100644 index 0000000..90b1bb6 --- /dev/null +++ b/app/unused_apps/projects/shortcuts.py @@ -0,0 +1,235 @@ +from django.contrib.gis.db.models.fields import GeometryField
+#from django.contrib.gis.gdal import Envelope
+from django.contrib.gis.geos import Polygon
+import json
+from django.http import HttpResponse
+#from django.db.models.fields.related import ManyRelatedManager
+
+# also need to check out:
+# http://code.google.com/p/dojango/source/browse/trunk/dojango/util/__init__.py#82
+
+
+# example usages:
+
+"""
+
+def a_shapes(request):
+ ids = request.GET.get('ids').split(',')
+ mimetype = 'text/plain' #'application/javascript; charset=utf8'
+ pretty_print = True
+ if ids:
+ qs = WorldBorders.objects.filter(affiliates__in=ids).annotate(num_a=Count('affiliates')).filter(num_a__gt=0)
+ else:
+ qs = WorldBorders.objects.none()
+ return render_to_geojson(qs,
+ extra_attributes=['num_a','affiliates_set'],
+ geom_attribute='point',
+ included_fields=['id','name'],
+ mimetype=mimetype,
+ proj_transform=900913,
+ pretty_print=pretty_print
+ )
+
+def responses(qs,type_='countries',pretty_print=True,mimetype='text/plain'):
+ if type_ == 'locations':
+ qs = qs.geolocations()
+ return render_to_geojson(qs,
+ excluded_fields=['json'],
+ geom_field='point',
+ proj_transform=900913,
+ mimetype=mimetype,
+ pretty_print=pretty_print
+ )
+ elif type_ == 'affiliates':
+ qs = qs.exclude(geokeywords='').attach_locations()
+ return render_to_geojson(qs,
+ included_fields=['id','_geokeywords_cache'],
+ geom_attribute='point',
+ extra_attributes=['name'],
+ proj_transform=900913,
+ mimetype=mimetype,
+ pretty_print=pretty_print
+ )
+ elif type_ == 'countries':
+ qs2 = W.objects.filter(affiliates__in=qs).annotate(num_a=Count('affiliates')).filter(num_a__gt=0)
+ return render_to_geojson(qs2,
+ extra_attributes=['num_a'],
+ #geom_attribute='point',
+ mimetype=mimetype,
+ pretty_print=pretty_print
+ )
+ else:# type_ == 'countries' or type is None:
+ if len(qs) > 10:
+ # this is a limit, weird huh?
+ # requires another all() otherwise it
+ # returns a list!
+ qs = qs.all()[:10]
+ return render_to_geojson(qs,
+ included_fields=['id','_geokeywords_cache'],
+ geom_attribute='countries.unionagg',
+ extra_attributes=['name'],
+ mimetype=mimetype,
+ pretty_print=pretty_print
+ )
+"""
+
+
+
+def render_to_geojson(query_set, geom_field=None, geom_attribute=None, extra_attributes=[],mimetype='text/plain', pretty_print=False, excluded_fields=[],included_fields=[],proj_transform=None):
+ '''
+
+ Shortcut to render a GeoJson FeatureCollection from a Django QuerySet.
+ Currently computes a bbox and adds a crs member as a sr.org link
+
+ '''
+ excluded_fields.append('_state')
+ collection = {}
+ if hasattr(query_set,'_meta'): # its a model instance
+ fields = query_set._meta.fields
+ query_set = [query_set]
+ else:
+ fields = query_set.model._meta.fields
+
+ if geom_attribute:
+ geometry_name = geom_attribute
+ geo_field = None
+ if '.' in geom_attribute:
+ prop, meth = geom_attribute.split('.')
+ if len(query_set):
+ p = getattr(query_set[0],prop)
+ geo_field = getattr(p,meth)
+ if callable(geo_field):
+ geo_field = geo_field()
+ else:
+ if len(query_set):
+ geo_field = getattr(query_set[0],geom_attribute)
+ if callable(geo_field):
+ geo_field = geo_field()
+ if not geo_field:
+ srid = 4326
+ else:
+ srid = geo_field.srid
+
+ else:
+ geo_fields = [f for f in fields if isinstance(f, GeometryField)]
+
+ #attempt to assign geom_field that was passed in
+ if geom_field:
+ #import pdb;pdb.set_trace()
+ geo_fieldnames = [x.name for x in geo_fields]
+ try:
+ geo_field = geo_fields[geo_fieldnames.index(geom_field)]
+ except:
+ raise Exception('%s is not a valid geometry on this model' % geom_field)
+ else:
+ if not len(geo_fields):
+ raise Exception('There appears to be no valid geometry on this model')
+ geo_field = geo_fields[0] # no support yet for multiple geometry fields
+
+
+ #remove other geom fields from showing up in attributes
+ if len(geo_fields) > 1:
+ for field in geo_fields:
+ if field.name not in excluded_fields:
+ excluded_fields.append(field.name)
+
+ geometry_name = geo_field.name
+
+
+ srid = geo_field.srid
+
+ if proj_transform:
+ to_srid = proj_transform
+ else:
+ to_srid = srid
+ # Gather the projection information
+ crs = {}
+ crs['type'] = "link"
+ crs_properties = {}
+ crs_properties['href'] = 'http://spatialreference.org/ref/epsg/%s/' % to_srid
+ crs_properties['type'] = 'proj4'
+ crs['properties'] = crs_properties
+ collection['crs'] = crs
+ collection['srid'] = to_srid
+
+ # Build list of features
+ features = []
+ if query_set.distinct():
+ for item in query_set:
+ feat = {}
+ feat['type'] = 'Feature'
+ if included_fields:
+ d = {}
+ for f in included_fields:
+ if hasattr(item,f):
+ d[f] = getattr(item,f)
+ else:
+ d = item.__dict__.copy()
+ for field in excluded_fields:
+ if field in d.keys():
+ d.pop(field)
+ if geometry_name in d:
+ d.pop(geometry_name)
+
+ for attr in extra_attributes:
+ a = getattr(item,attr)
+ # crappy way of trying to figure out it this is a
+ # m2m, aka 'ManyRelatedManager'
+ if hasattr(a,'values_list'):
+ a = list(a.values_list('id',flat=True))
+ if callable(a):
+ d[attr] = a()
+ else:
+ d[attr] = a
+ if '.' in geometry_name:
+ prop, meth = geometry_name.split('.')
+ a = getattr(item,prop)
+ g = getattr(a,meth)
+ if callable(g):
+ g = g()
+ else:
+ g = getattr(item,geometry_name)
+ if g:
+ if proj_transform:
+ g.transform(proj_transform)
+ feat['geometry'] = json.loads(g.geojson)
+ feat['properties'] = d
+ features.append(feat)
+ else:
+ pass #features.append({'type':'Feature','geometry': {},'properties':{}})
+
+ # Label as FeatureCollection and add Features
+ collection['type'] = "FeatureCollection"
+ collection['features'] = features
+
+ # Attach extent of all features
+ if query_set:
+ ex = None
+ query_set.query.distinct = False
+ if hasattr(query_set,'agg_extent'):
+ ex = [x for x in query_set.agg_extent.tuple]
+ elif '.' in geometry_name:
+ prop, meth = geometry_name.split('.')
+ a = getattr(item,prop)
+ if a:
+ ex = [x for x in a.extent()]
+ else:
+ # make sure qs does not have .distinct() in it...
+ ex = [x for x in query_set.extent()]
+ if ex:
+ if proj_transform:
+ poly = Polygon.from_bbox(ex)
+ poly.srid = srid
+ poly.transform(proj_transform)
+ ex = poly.extent
+ collection['bbox'] = ex
+
+ # Return response
+ response = HttpResponse()
+ if pretty_print:
+ response.write('%s' % json.dumps(collection, indent=1))
+ else:
+ response.write('%s' % json.dumps(collection))
+ response['Content-length'] = str(len(response.content))
+ response['Content-Type'] = mimetype
+ return response
diff --git a/app/unused_apps/projects/urls.py b/app/unused_apps/projects/urls.py new file mode 100644 index 0000000..8e56b16 --- /dev/null +++ b/app/unused_apps/projects/urls.py @@ -0,0 +1,29 @@ +from django.conf.urls import url +from django.views.generic import ListView +from projects.models.base import Project + +from . import views + +app_name = "project" + +urlpatterns = [ + url( + r'data/(?P<id>\d+)/$', + views.data_json + ), + url( + r'gifs/(?P<slug>[-\w]+)/$', + views.gif_detail + ), + url( + r'(?P<slug>[-\w]+)/$', + views.detail + ), + url( + r'^$', + ListView.as_view( + queryset=Project.objects.filter(status__exact=1).order_by('-pub_date'), + template_name="archives/projects.html", + ) + ), +] diff --git a/app/unused_apps/projects/views.py b/app/unused_apps/projects/views.py new file mode 100644 index 0000000..ad5f167 --- /dev/null +++ b/app/unused_apps/projects/views.py @@ -0,0 +1,45 @@ +from django.shortcuts import render, get_object_or_404 +from django.template import RequestContext +from django.apps import apps + +from projects.shortcuts import render_to_geojson +from projects.models.natparks import NationalParks +from projects.models.gifs import AnimatedGif + +projects = { + '5x5': 'FiveBy', + '6x6': 'SixBy', + 'national-parks': 'NationalParks', + 'code': 'Code' +} + + +def detail(request, slug): + """Projects by slug""" + name = projects[slug] + model = apps.get_model('projects', name) + if slug == 'national-parks': + qs = model.objects.filter(visited__exact=True).order_by("-date_visited_begin") + else: + qs = model.objects.filter(status__exact=1) + context = { + "object_list": qs, + } + template = 'details/%s.html' % (slug) + return render(request, template, context) + + +def gif_detail(request, slug): + obj = get_object_or_404(AnimatedGif, slug__exact=slug) + return render(request, 'details/gifs.html', {'object': obj}) + + +def data_json(request, id): + qs = NationalParks.objects.filter(pk=id) + return render_to_geojson( + qs, + included_fields=['id'], + geom_attribute='mpoly', + mimetype='application/json', + pretty_print=True + ) diff --git a/app/unused_apps/prompts/__init__.py b/app/unused_apps/prompts/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/prompts/__init__.py diff --git a/app/unused_apps/prompts/admin.py b/app/unused_apps/prompts/admin.py new file mode 100644 index 0000000..f12c904 --- /dev/null +++ b/app/unused_apps/prompts/admin.py @@ -0,0 +1,30 @@ +from django.contrib import admin + +from utils.widgets import LGEntryForm +from .models import Prompt + + +@admin.register(Prompt) +class PromptAdmin(admin.ModelAdmin): + form = LGEntryForm + prepopulated_fields = {"slug": ('title',)} + list_display = ('title', 'source', 'prompt_type') + list_filter = ('source', 'prompt_type') + fieldsets = ( + ('Prompt', { + 'fields': ( + 'title', + 'subtitle', + 'body_markdown', + ('pub_date', 'prompt_type'), + ('slug','source'), + 'meta_description' + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ) diff --git a/app/unused_apps/prompts/migrations/0001_initial.py b/app/unused_apps/prompts/migrations/0001_initial.py new file mode 100644 index 0000000..c5a24ec --- /dev/null +++ b/app/unused_apps/prompts/migrations/0001_initial.py @@ -0,0 +1,32 @@ +# Generated by Django 2.1.5 on 2019-02-20 22:52 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Prompt', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('subtitle', models.CharField(max_length=200)), + ('slug', models.SlugField(unique_for_date='pub_date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField()), + ('pub_date', models.DateTimeField(verbose_name='Date published')), + ('meta_description', models.CharField(blank=True, max_length=256, null=True)), + ('source', models.CharField(max_length=350)), + ], + options={ + 'ordering': ('-pub_date',), + 'get_latest_by': 'pub_date', + }, + ), + ] diff --git a/app/unused_apps/prompts/migrations/0002_auto_20190228_0941.py b/app/unused_apps/prompts/migrations/0002_auto_20190228_0941.py new file mode 100644 index 0000000..5b66a99 --- /dev/null +++ b/app/unused_apps/prompts/migrations/0002_auto_20190228_0941.py @@ -0,0 +1,34 @@ +# Generated by Django 2.1.7 on 2019-02-28 09:41 + +import datetime +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('prompts', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='prompt', + name='pub_date', + field=models.DateTimeField(default=datetime.datetime.now), + ), + migrations.AlterField( + model_name='prompt', + name='slug', + field=models.SlugField(blank=True, unique_for_date='pub_date'), + ), + migrations.AlterField( + model_name='prompt', + name='source', + field=models.CharField(blank=True, max_length=350), + ), + migrations.AlterField( + model_name='prompt', + name='subtitle', + field=models.CharField(blank=True, max_length=200), + ), + ] diff --git a/app/unused_apps/prompts/migrations/0003_prompt_prompt_type.py b/app/unused_apps/prompts/migrations/0003_prompt_prompt_type.py new file mode 100644 index 0000000..d027c6e --- /dev/null +++ b/app/unused_apps/prompts/migrations/0003_prompt_prompt_type.py @@ -0,0 +1,18 @@ +# Generated by Django 2.1.2 on 2020-07-05 22:04 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('prompts', '0002_auto_20190228_0941'), + ] + + operations = [ + migrations.AddField( + model_name='prompt', + name='prompt_type', + field=models.IntegerField(choices=[(0, 'Meditation'), (1, 'Writing'), (2, 'Kids Writing')], default=0), + ), + ] diff --git a/app/unused_apps/prompts/migrations/__init__.py b/app/unused_apps/prompts/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/prompts/migrations/__init__.py diff --git a/app/unused_apps/prompts/models.py b/app/unused_apps/prompts/models.py new file mode 100644 index 0000000..7b5dc71 --- /dev/null +++ b/app/unused_apps/prompts/models.py @@ -0,0 +1,94 @@ +import datetime +from django.contrib.gis.db import models +from django.urls import reverse +from django.apps import apps + +from utils.util import render_images, markdown_to_html + + +class Source(models.Model): + name = models.CharField(max_length=200) + link = models.CharField(max_length=400) + SOURCE_TYPE = ( + (0, 'Book'), + (1, 'Website'), + (2, 'Other'), + ) + source_type = models.IntegerField(choices=SOURCE_TYPE, default=0) + + class Meta: + ordering = ('name',) + + def __str__(self): + return self.name + + +class Prompt(models.Model): + title = models.CharField(max_length=200) + subtitle = models.CharField(max_length=200, blank=True) + meta_description = models.CharField(max_length=256, null=True, blank=True) + slug = models.SlugField(unique_for_date='pub_date', blank=True) + body_markdown = models.TextField() + body_html = models.TextField(blank=True) + pub_date = models.DateTimeField(default=datetime.datetime.now) + source = models.CharField(max_length=350, blank=True) + PROMPT_TYPE = ( + (0, 'Meditation'), + (1, 'Writing'), + (2, 'Kids Writing'), + ) + prompt_type = models.IntegerField(choices=PROMPT_TYPE, default=0) + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse("prompt:detail", kwargs={"slug": self.slug}) + + @property + def get_previous_published(self): + return self.get_previous_by_pub_date(status__exact=1) + + @property + def get_previous_admin_url(self): + n = self.get_previous_by_pub_date() + return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[n.id]) + + @property + def get_next_published(self): + return self.get_next_by_pub_date(status__exact=1) + + @property + def get_next_admin_url(self): + model = apps.get_model(app_label=self._meta.app_label, model_name=self._meta.model_name) + try: + return reverse('admin:%s_%s_change' % (self._meta.app_label, self._meta.model_name), args=[self.get_next_by_pub_date().pk]) + except model.DoesNotExist: + return '' + + def save(self, *args, **kwargs): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(Prompt, self).save(*args, **kwargs) + + + +class Source(models.Model): + name = models.CharField(max_length=200) + link = models.CharField(max_length=400) + SOURCE_TYPE = ( + (0, 'Book'), + (1, 'Website'), + (2, 'Other'), + ) + source_type = models.IntegerField(choices=SOURCE_TYPE, default=0) + + class Meta: + ordering = ('name',) + + def __str__(self): + return self.name diff --git a/app/unused_apps/prompts/urls.py b/app/unused_apps/prompts/urls.py new file mode 100644 index 0000000..7cbe09a --- /dev/null +++ b/app/unused_apps/prompts/urls.py @@ -0,0 +1,13 @@ +from django.urls import path + +from . import views + +app_name = "prompts" + +urlpatterns = [ + path( + r'', + views.RandomList.as_view(), + name="random-prompt" + ), +] diff --git a/app/unused_apps/prompts/views.py b/app/unused_apps/prompts/views.py new file mode 100644 index 0000000..4744299 --- /dev/null +++ b/app/unused_apps/prompts/views.py @@ -0,0 +1,11 @@ +from django.views.generic.detail import DetailView + +from .models import Prompt + + +class PromptList(DetailView): + model = Prompt + + def get_object(self, queryset): + """ This might be faster: random.choice(Prompt.objects.all())""" + return Prompt.objects.order_by('?').first() diff --git a/app/unused_apps/src/__init__.py b/app/unused_apps/src/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/src/__init__.py diff --git a/app/unused_apps/src/admin.py b/app/unused_apps/src/admin.py new file mode 100644 index 0000000..f354b15 --- /dev/null +++ b/app/unused_apps/src/admin.py @@ -0,0 +1,62 @@ +from django.contrib import admin +from .models import Topic, SrcPost, Book +from utils.widgets import LGEntryForm + + +@admin.register(Topic) +class TopicAdmin(admin.ModelAdmin): + prepopulated_fields = {"slug": ('name',), "pluralized_name": ('name',)} + + +@admin.register(Book) +class BookAdmin(admin.ModelAdmin): + prepopulated_fields = {"slug": ('title', )} + list_display = ('title', 'pub_date', 'status') + fieldsets = ( + ('Entry', { + 'fields': ( + 'title', + 'body_markdown', + 'image', + ('pub_date', 'status'), + ('price', 'price_sale'), + 'meta_description', + ('slug', 'template_name', 'pages'), + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ) + + +@admin.register(SrcPost) +class PostAdmin(admin.ModelAdmin): + form = LGEntryForm + list_display = ('title', 'pub_date', 'enable_comments', 'status') + list_filter = ('pub_date', 'enable_comments', 'status') + prepopulated_fields = {"slug": ('title',)} + fieldsets = ( + ('Entry', { + 'fields': ( + 'title', + 'body_markdown', + ('pub_date', 'status'), + 'topics', + 'meta_description', + ('slug', 'enable_comments', 'has_code', 'template_name'), + ), + 'classes': ( + 'show', + 'extrapretty', + 'wide' + ) + } + ), + ) + + class Media: + js = ('image-loader.js', 'next-prev-links.js') diff --git a/app/unused_apps/src/build.py b/app/unused_apps/src/build.py new file mode 100644 index 0000000..a16bdaf --- /dev/null +++ b/app/unused_apps/src/build.py @@ -0,0 +1,62 @@ +import os +from builder.base import BuildNew +from django.urls import reverse +from . import models + + +class BuildSrc(BuildNew): + + def build(self): + self.build_list_view( + base_path=reverse("src:list"), + paginate_by=99999 + ) + self.build_list_view( + base_path=reverse("src:list_books"), + paginate_by=99999 + ) + self.build_detail_view() + # These are the unique classes for this model: + # self.build_books_view() + self.build_topic_view() + self.build_feed("src:feed") + + def build_topic_view(self): + for topic in models.Topic.objects.all(): + ctype = ContentType.objects.get(app_label='posts', model='post') + for cat in Category.objects.all(): + + url = reverse("src:list_topics", kwargs={'slug': topic.slug, }) + path, slug = os.path.split(url) + response = self.client.get(url, HTTP_HOST='127.0.0.1') + self.write_file('%s/' % path, response.content, filename=slug) + + def build_books_view(self): + for obj in models.Book.objects.all(): + url = reverse("src:detail_book", kwargs={'slug': obj.slug, }) + path, slug = os.path.split(url) + response = self.client.get(url, HTTP_HOST='127.0.0.1') + self.write_file('%s/' % path, response.content, filename=slug) + + +def builder(): + j = BuildSrc("src", "srcpost") + j.build() + + +""" + + + + + def build_books(self): + path = 'src/books/' + c = Context({ + 'object_list': Book.objects.filter(status__exact=1), + 'MEDIA_URL': settings.BAKED_MEDIA_URL, + 'IMAGES_URL': settings.BAKED_IMAGES_URL + }) + t = render_to_string('archives/src_books.html', c).encode('utf-8') + self.write_file(path, t) + +""" diff --git a/app/unused_apps/src/migrations/0001_initial.py b/app/unused_apps/src/migrations/0001_initial.py new file mode 100644 index 0000000..1f672ee --- /dev/null +++ b/app/unused_apps/src/migrations/0001_initial.py @@ -0,0 +1,76 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-03-29 21:06 +from __future__ import unicode_literals + +from django.db import migrations, models +import src.models + + +class Migration(migrations.Migration): + + initial = True + + dependencies = [ + ] + + operations = [ + migrations.CreateModel( + name='Book', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('image', models.FileField(blank=True, null=True, upload_to=src.models.get_upload_path)), + ('slug', models.SlugField(unique_for_date='pub_date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField()), + ('pub_date', models.DateTimeField(verbose_name='Date published')), + ('last_updated', models.DateTimeField(auto_now=True)), + ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Published')], default=0)), + ('price', models.FloatField()), + ('price_sale', models.FloatField()), + ('meta_description', models.CharField(blank=True, max_length=256, null=True)), + ('pages', models.DecimalField(blank=True, decimal_places=0, max_digits=3, null=True)), + ('template_name', models.CharField(choices=[('details/src_book.html', 'Default'), ('details/src_book_2.html', 'Book Two')], default='details/src_book.html', max_length=200)), + ], + options={ + 'get_latest_by': 'pub_date', + 'ordering': ('-pub_date',), + }, + ), + migrations.CreateModel( + name='Entry', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('title', models.CharField(max_length=200)), + ('slug', models.SlugField(unique_for_date='pub_date')), + ('body_html', models.TextField(blank=True)), + ('body_markdown', models.TextField()), + ('pub_date', models.DateTimeField(verbose_name='Date published')), + ('last_updated', models.DateTimeField(auto_now=True)), + ('enable_comments', models.BooleanField(default=False)), + ('has_code', models.BooleanField(default=False)), + ('status', models.IntegerField(choices=[(0, 'Draft'), (1, 'Published')], default=0)), + ('meta_description', models.CharField(blank=True, max_length=256, null=True)), + ('template_name', models.IntegerField(choices=[(0, 'default')], default=0)), + ], + options={ + 'get_latest_by': 'pub_date', + 'ordering': ('-pub_date',), + 'verbose_name_plural': 'entries', + }, + ), + migrations.CreateModel( + name='Topic', + fields=[ + ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('name', models.CharField(max_length=60)), + ('slug', models.SlugField()), + ('pluralized_name', models.CharField(max_length=60)), + ], + ), + migrations.AddField( + model_name='entry', + name='topics', + field=models.ManyToManyField(blank=True, to='src.Topic'), + ), + ] diff --git a/app/unused_apps/src/migrations/0002_auto_20160329_2107.py b/app/unused_apps/src/migrations/0002_auto_20160329_2107.py new file mode 100644 index 0000000..25f5e4e --- /dev/null +++ b/app/unused_apps/src/migrations/0002_auto_20160329_2107.py @@ -0,0 +1,19 @@ +# -*- coding: utf-8 -*- +# Generated by Django 1.9 on 2016-03-29 21:07 +from __future__ import unicode_literals + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('src', '0001_initial'), + ] + + operations = [ + migrations.RenameModel( + old_name='Entry', + new_name='Post', + ), + ] diff --git a/app/unused_apps/src/migrations/0003_auto_20180707_0958.py b/app/unused_apps/src/migrations/0003_auto_20180707_0958.py new file mode 100644 index 0000000..f619888 --- /dev/null +++ b/app/unused_apps/src/migrations/0003_auto_20180707_0958.py @@ -0,0 +1,17 @@ +# Generated by Django 2.0.1 on 2018-07-07 09:58 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('src', '0002_auto_20160329_2107'), + ] + + operations = [ + migrations.AlterModelOptions( + name='post', + options={'get_latest_by': 'pub_date', 'ordering': ('-pub_date',), 'verbose_name_plural': 'posts'}, + ), + ] diff --git a/app/unused_apps/src/migrations/0004_auto_20191007_0905.py b/app/unused_apps/src/migrations/0004_auto_20191007_0905.py new file mode 100644 index 0000000..6c223a0 --- /dev/null +++ b/app/unused_apps/src/migrations/0004_auto_20191007_0905.py @@ -0,0 +1,17 @@ +# Generated by Django 2.2.6 on 2019-10-07 09:05 + +from django.db import migrations + + +class Migration(migrations.Migration): + + dependencies = [ + ('src', '0003_auto_20180707_0958'), + ] + + operations = [ + migrations.RenameModel( + old_name='Post', + new_name='SrcPost', + ), + ] diff --git a/app/unused_apps/src/migrations/__init__.py b/app/unused_apps/src/migrations/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/app/unused_apps/src/migrations/__init__.py diff --git a/app/unused_apps/src/models.py b/app/unused_apps/src/models.py new file mode 100644 index 0000000..69d85a5 --- /dev/null +++ b/app/unused_apps/src/models.py @@ -0,0 +1,171 @@ +import re +from django.db import models +from django.urls import reverse +from django.contrib.sitemaps import Sitemap +from django.conf import settings +import datetime +from itertools import chain + +from utils.util import parse_image, markdown_to_html + + +def render_images(s): + s = re.sub('<img(.*)/>', parse_image, s) + return s + + +class Topic(models.Model): + name = models.CharField(max_length=60) + slug = models.SlugField() + pluralized_name = models.CharField(max_length=60) + + def __str__(self): + return self.name + + def get_absolute_url(self): + return reverse('src:list_topics', kwargs={"slug": self.slug}) + + @property + def pub_date(self): + return datetime.datetime.now() + + +class SrcPost(models.Model): + title = models.CharField(max_length=200) + slug = models.SlugField(unique_for_date='pub_date') + body_html = models.TextField(blank=True) + body_markdown = models.TextField() + pub_date = models.DateTimeField('Date published') + topics = models.ManyToManyField(Topic, blank=True) + last_updated = models.DateTimeField(auto_now=True) + enable_comments = models.BooleanField(default=False) + has_code = models.BooleanField(default=False) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + meta_description = models.CharField(max_length=256, null=True, blank=True) + TEMPLATES = ( + (0, 'default'), + ) + template_name = models.IntegerField(choices=TEMPLATES, default=0) + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + verbose_name_plural = 'posts' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('src:detail', kwargs={"slug": self.slug}) + + def comment_period_open(self): + return self.enable_comments and datetime.datetime.today() - datetime.timedelta(30) <= self.pub_date + + @property + def get_previous_published(self): + return self.get_previous_by_pub_date(status__exact=1) + + @property + def get_next_published(self): + return self.get_next_by_pub_date(status__exact=1) + + def save(self): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(SrcPost, self).save() + + +def get_upload_path(self, filename): + return "images/src/%s" % filename + + +class Book(models.Model): + title = models.CharField(max_length=200) + image = models.FileField(blank=True, null=True, upload_to=get_upload_path) + slug = models.SlugField(unique_for_date='pub_date') + body_html = models.TextField(blank=True) + body_markdown = models.TextField() + pub_date = models.DateTimeField('Date published') + last_updated = models.DateTimeField(auto_now=True) + PUB_STATUS = ( + (0, 'Draft'), + (1, 'Published'), + ) + status = models.IntegerField(choices=PUB_STATUS, default=0) + price = models.FloatField() + price_sale = models.FloatField() + meta_description = models.CharField(max_length=256, null=True, blank=True) + pages = models.DecimalField(max_digits=3, decimal_places=0, null=True, blank=True) + DEFAULT = 'details/src_book.html' + BOOK2 = 'details/src_book_2.html' + TEMPLATES = ( + (DEFAULT, 'Default'), + (BOOK2, 'Book Two'), + ) + template_name = models.CharField( + max_length=200, + choices=TEMPLATES, + default=DEFAULT + ) + + class Meta: + ordering = ('-pub_date',) + get_latest_by = 'pub_date' + + def __str__(self): + return self.title + + def get_absolute_url(self): + return reverse('src:detail_book', kwargs={"slug": self.slug}) + + def get_image_url(self): + img = self.image.url.split('src/')[1] + return '%ssrc/%s' % (settings.IMAGES_URL, img) + + def save(self): + md = render_images(self.body_markdown) + self.body_html = markdown_to_html(md) + super(Book, self).save() + + +'''class SrcDemo(models.Model): + title = models.CharField(max_length=254) + slug = models.SlugField() + body = models.TextField(blank=True, null=True) + head = models.TextField(blank=True, null=True) + DEMO_TEMPLATES = ( + (0, 'Blank'), + (1, 'Basic_light'), + ) + template = models.IntegerField(choices=DEMO_TEMPLATES, default=0) + pub_date = models.DateTimeField('Date published', blank=True) + + class Meta: + verbose_name_plural = "Demos" + app_label = 'projects' + ordering = ('-pub_date',) + + def save(self): + if not self.id: + self.pub_date = datetime.datetime.now() + super(SrcDemo, self).save() +''' + + +class SrcSitemap(Sitemap): + changefreq = "never" + priority = 0.7 + protocol = "https" + + def items(self): + return list(chain( + SrcPost.objects.filter(status=1), + Topic.objects.all() + )) + + def lastmod(self, obj): + return obj.pub_date diff --git a/app/unused_apps/src/templates/src/srcpost_detail.html b/app/unused_apps/src/templates/src/srcpost_detail.html new file mode 100644 index 0000000..733f586 --- /dev/null +++ b/app/unused_apps/src/templates/src/srcpost_detail.html @@ -0,0 +1,112 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} +{% block pagetitle %}{{object.title|striptags}} - by Scott Gilbertson{% endblock %} +{% block metadescription %}{% autoescape on %}{{object.meta_description|striptags|safe}}{% endautoescape %}{% endblock %} +{%block extrahead%} + <meta property="og:type" content="article" /> + <meta property="og:site_name" content="luxagraf:src"/> + <meta property="og:title" content="{{object.title|safe}}" /> + <meta property="og:url" content="https://luxagraf.net{{object.get_absolute_url}}" /> + <meta property="og:image" content=""> + <meta property="og:description" content="{{object.meta_description}}" /> + <meta property="article:published_time" content="{{object.pub_date|date:'c'}}" /> + <meta property="article:author" content="Luxagraf" /> + <meta property="og:site_name" content="Luxagraf:src" /> + <meta property="og:locale" content="en_US" /> + <meta name="twitter:card" content="summary_large_image"/> + <meta name="twitter:site" content="@luxagraf"/> + <meta name="twitter:creator" content="@luxagraf"/> + <link rel="stylesheet" href="/media/src/solarized.css" type="text/css" media="screen"/> +{%endblock%} + +{% block bodyid %}class="src detail single"{% endblock %} +{%block sitesubtitle %}Code Slowly{% endblock%} +{% block breadcrumbs %}<ol class="bl" id="breadcrumbs" itemscope itemtype="http://schema.org/BreadcrumbList"> + <li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> + <a itemprop="item" href="/"> + <span itemprop="name">Home</span> + </a> → + <meta itemprop="position" content="1" /> + </li> + <li itemprop="itemListElement" itemscope itemtype="http://schema.org/ListItem"> + <a href="/src/" itemprop="item"> + <span itemprop="name">Src</span> + </a> + <meta itemprop="position" content="2" /> + </li> + </ol>{% endblock %} +{% block primary %}<main role="main"> + <article class="hentry post-article{% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %} post--article--double{%endif%}{%endwith%}" itemscope itemType="http://schema.org/Article"> + <header id="header" class="post-header {% with object.get_template_name_display as t %}{%if t == "double" or t == "double-dark" %}post--header--double{%endif%}{%endwith%}"> + <h1 class="p-name entry-title post--title" itemprop="headline">{%if object.template_name == 1 or object.template_name == 3 %}{{object.title|safe|smartypants}}{%else%}{{object.title|safe|smartypants|widont}}{%endif%}</h1> + <h2 class="post-subtitle">{{object.meta_description|smartypants|safe}}</h2> + <div class="post-linewrapper"> + {% if object.originally_published_by %}<h4 class="post-source">Originally Published By: <a href="{{object.originally_published_by_url}}" title="View {{object.title}} on {{object.originally_published_by}}">{{object.originally_published_by}}</a></h4>{%endif%} + {% if object.topics.all %}<h4 class="post-source">Topics: {% for topic in object.topics.all%} <a href="/src/topic/{{topic.slug}}">{{topic.name}}</a>{%if forloop.last%}{%else%}, {%endif%}{%endfor%}</h4>{%endif%} + <time class="dt-published published dt-updated post-date" datetime="{{object.pub_date|date:'c'}}" itemprop="datePublished">{{object.pub_date|date:"F"}} <span>{{object.pub_date|date:"j, Y"}}</span></time> + <span class="hide" itemprop="author" itemscope itemtype="http://schema.org/Person">by <a class="p-author h-card" href="/about"><span itemprop="name">Scott Gilbertson</span></a></span> + </div> + </header> + + + <div id="article" class="e-content entry-content post-body post-body-{% with object.template_name as t %}{%if t == 0 or t == 2 %}single{%endif%}{%if t == 1 or t == 3 %}double{%endif%}{%endwith%}" itemprop="articleBody"> + {{object.body_html|safe|smartypants|widont}} + </div> + </article> + {% if object.slug != 'about' %} + {% with object.get_next_published as next %} + {% with object.get_previous_published as prev %} + <nav id="page-navigation"> + <ul>{% if prev%} + <li id="prev"><span class="bl">Previous:</span> + <a href="{{ prev.get_absolute_url }}" rel="prev" title=" {{prev.title}}">{{prev.title|safe}}</a> + </li>{%endif%}{% if next%} + <li id="next"><span class="bl">Next:</span> + <a href="{{ next.get_absolute_url }}" rel="next" title=" {{next.title}}">{{next.title|safe}}</a> + </li>{%endif%} + </ul> + </nav>{%endwith%}{%endwith%} + {%endif%} + </main> + {% if object.slug != 'about' %} + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} +<p class="comments--header">{{comment_count}} Comment{{ comment_count|pluralize }}</p> +{% render_comment_list for object %} +{%endif%} +<div class="comment--form--wrapper {%if comment_count > 0%}comment-form-border{%endif%}"> +{% render_comment_form for object %} +</div> +{% else %} +<p class="comments--header" style="text-align: center">Sorry, comments have been disabled for this post.</p> +{%endif%} +{%endif%} +{% endblock %} +{% block js %} +<script type="text/javascript"> +window.onload = function() { + {% if object.enable_comments %} +{% get_comment_count for object as comment_count %} +{%if comment_count > 0 %} + //delay loading of gravatar images using noscript data-hash attribute + dataattr = document.getElementsByClassName("datahashloader"); + for(var i=0; i<dataattr.length; i++) { + var c = dataattr[i].parentNode; + var img = document.createElement("img"); + img.src = 'https://images.luxagraf.net/gravcache/' + dataattr[i].getAttribute('data-hash') + '.jpg'; + img.className += "gravatar"; + c.insertBefore(img, c.childNodes[3]); + } +{%endif%} +{%endif%} + {% with object.get_template_name_display as t %}{%if t == "single" or t == "single-dark" %} + createMap(); + var open = false; + {%endif%}{%endwith%} +} +</script> +{% if object.has_code %} +{%endif %} +{% endblock %} diff --git a/app/unused_apps/src/templates/src/srcpost_list.html b/app/unused_apps/src/templates/src/srcpost_list.html new file mode 100644 index 0000000..dd5d410 --- /dev/null +++ b/app/unused_apps/src/templates/src/srcpost_list.html @@ -0,0 +1,30 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} + +{% block pagetitle %}Tutorials and tools for building great things{% endblock %} +{% block metadescription %}Tutorials and tools for building great things on the web - by Scott Gilbertson.{% endblock %} +{%block sitesubtitle %}Code Slowly{% endblock%} +{% block breadcrumbs %}{% include "lib/breadcrumbs.html" with breadcrumbs=breadcrumbs %}{% endblock %} +{% block primary %}<main role="main" id="essay-archive" class="essay-archive archive-list"> + <div class="essay-intro"> + <h2>Tutorials and tools for building great things on the web.</h2> + <p>The indie web is an amazing democratic publishing platform unlike anything in history. The catch is, to avoid serving at the pleasure of the corporate king, you need to know <em>how</em> to publish. That's what these articles are here for, to help you learn how to use independent, community supported open source tools. The web won't last forever, let's build something cool while we can.</p> + <p>Topics include HTML, CSS, Django, Linux, Nginx, Python, Postgresql, free software, and, once, the evil that is Google AMP.</p> + <p>A few of the articles below were previously published in: <em><a href="https://arstechnica.com/">Ars Technica</a></em>, <em><a href="https://www.wired.com/author/scott-gilbertson/">Wired</a></em>, and <em><a href="https://www.theregister.co.uk/Author/Scott-Gilbertson/">The Register</a></em></p> + </div> + <h1 class="topic-hed">Articles</h1> + <ul class="fancy-archive-list">{% for object in object_list %}{% if object.slug != 'about' %} + <li class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published">{{object.pub_date|date:"F Y"}}</span> + <a href="{{object.get_absolute_url}}"> + <h2>{{object.title|safe|smartypants|widont}}</h2> + <p class="p-summary">{{object.meta_description|safe|smartypants|widont}}</p> + </a> + </li> + {%endif%}{%endfor%}</ul> + + + + </main> +{%endblock%} diff --git a/app/unused_apps/src/templates/src/topic_list.html b/app/unused_apps/src/templates/src/topic_list.html new file mode 100644 index 0000000..7149823 --- /dev/null +++ b/app/unused_apps/src/templates/src/topic_list.html @@ -0,0 +1,35 @@ +{% extends 'base.html' %} +{% load typogrify_tags %} +{% load comments %} + +{% block pagetitle %}Tutorials and tools for building great things{% endblock %} + +{% block metadescription %}Tutorials about {{topic}} - by Scott Gilbertson.{% endblock %} +{%block sitesubtitle %}Code Slowly{% endblock%} +{% block primary %}<ul class="bl" id="breadcrumbs" itemscope itemtype="http://data-vocabulary.org/Breadcrumb"> + <li><a href="/" title="luxagraf homepage" itemprop="url"><span itemprop="title">Home</span></a> → </li>{% if topic %} + <li><a href="/src/" title="luxagraf:src homepage" itemprop="url"><span itemprop="title"><code>src</code></span></a> → </li> + <li>{{topic}}</li>{%else%} + <li><code>src</code></li>{%endif%} + </ul> + <main role="main" id="essay-archive" class="essay-archive archive-list"> + <div class="essay-intro"> + <h2>Tutorials and tools for building great things on the web.</h2> + <p>The indie web is an amazing democratic publishing platform unlike anything in history. The catch is, to avoid serving at the pleasure of the corporate king, you need to know <em>how</em> to publish. That's what these articles are here for, to help you learn how to use independent, community supported open source tools. The web won't last forever, let's build something cool while we can.</p> + <p>A few of the articles below were previously published in: <em><a href="https://arstechnica.com/">Ars Technica</a></em>, <em><a href="https://www.wired.com/author/scott-gilbertson/">Wired</a></em>, and <em><a href="https://www.theregister.co.uk/Author/Scott-Gilbertson/">The Register</a></em></p> + </div> + <h1 class="topic-hed">Tutorials about {{topic}}</h1> + <ul class="fancy-archive-list">{% for object in object_list %}{% if object.slug != 'about' %} + <li class="h-entry hentry" itemscope itemType="http://schema.org/Article"> + <span class="date dt-published">{{object.pub_date|date:"F Y"}}</span> + <a href="{{object.get_absolute_url}}"> + <h2>{{object.title|safe|smartypants|widont}}</h2> + <p class="p-summary">{{object.meta_description|safe|smartypants|widont}}</p> + </a> + </li> + {%endif%}{%endfor%}</ul> + + + + </main> +{%endblock%} diff --git a/app/unused_apps/src/urls.py b/app/unused_apps/src/urls.py new file mode 100644 index 0000000..0ac6897 --- /dev/null +++ b/app/unused_apps/src/urls.py @@ -0,0 +1,49 @@ +from django.urls import path, re_path + +from . import views + +app_name = "src" + +urlpatterns = [ + path( + r'feed.xml', + views.SrcRSSFeedView(), + name="feed" + ), + path( + r'topic/<str:slug>', + views.TopicListView.as_view(), + name="list_topics" + ), + path( + r'books/<str:slug>', + views.BookDetailView.as_view(), + name='detail_book' + ), + path( + r'books/', + views.BookListView.as_view(), + name='list_books' + ), + path( + r'<str:slug>.txt', + views.EntryDetailViewTXT.as_view(), + name="detail-txt" + ), + path( + r'<str:slug>', + views.EntryDetailView.as_view(), + name="detail" + ), + re_path( + r'<int:page>', + views.SrcListView.as_view(), + name="list" + ), + path( + r'', + views.SrcListView.as_view(), + {'page':1}, + name="list" + ), +] diff --git a/app/unused_apps/src/views.py b/app/unused_apps/src/views.py new file mode 100644 index 0000000..7540e02 --- /dev/null +++ b/app/unused_apps/src/views.py @@ -0,0 +1,89 @@ +from django.views.generic import ListView +from django.views.generic.detail import DetailView +from django.contrib.syndication.views import Feed +from django.urls import reverse +from django.conf import settings + +#from paypal.standard.forms import PayPalPaymentsForm +from utils.views import PaginatedListView +from .models import SrcPost, Topic, Book + + +class BookListView(ListView): + template_name = "archives/src_books.html" + + def queryset(self): + return Book.objects.filter(status__exact=1) + + +class BookDetailView(DetailView): + model = Book + + def get_template_names(self): + book = self.get_object() + return [book.template_name] + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(BookDetailView, self).get_context_data(**kwargs) + book = self.get_object() + if book.price_sale < book.price: + price = book.price_sale + else: + price = book.price + #paypal_dict = { + # "business": settings.PAYPAL_RECEIVER_EMAIL, + # "amount": price, + # "item_name": book.title, + # "invoice": "unique-invoice-id", + # "notify_url": "https://luxagraf.net/src/paypal/" + reverse('src:paypal-ipn'), + # "return_url": "https://luxagraf.net/src/thank-you", + # "cancel_return": "https://luxagraf.net/src/books/", + #} + #context['paypal_form'] = PayPalPaymentsForm(initial=paypal_dict) + return context + + +class SrcListView(PaginatedListView): + model = SrcPost + + def get_queryset(self): + return SrcPost.objects.filter(status__exact=1) + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(SrcListView, self).get_context_data(**kwargs) + context['topics'] = Topic.objects.all() + return context + + +class EntryDetailView(DetailView): + model = SrcPost + slug_field = "slug" + + +class EntryDetailViewTXT(EntryDetailView): + template_name = "jrnl/entry_detail.txt" + + +class TopicListView(ListView): + template_name = 'src/topic_list.html' + + def get_queryset(self): + return SrcPost.objects.filter(topics__slug=self.kwargs['slug']) + + def get_context_data(self, **kwargs): + # Call the base implementation first to get a context + context = super(TopicListView, self).get_context_data(**kwargs) + context['topic'] = Topic.objects.get(slug__exact=self.kwargs['slug']) + return context + + +class SrcRSSFeedView(Feed): + title = "luxagraf:src Code and Technology" + link = "/src/" + description = "Latest postings to luxagraf.net/src" + description_template = 'feeds/blog_description.html' + + def items(self): + return SrcPost.objects.filter(status__exact=1).order_by('-pub_date')[:10] |