Improving on 3.0.0 / adding productorder link based on slug

This commit is contained in:
Nico Schottelius 2022-01-15 00:26:35 +01:00
parent d3b6d28ae6
commit 8952ef0b3a
9 changed files with 178 additions and 8 deletions

View File

@ -15,6 +15,40 @@ machine. Use `kubectl get nodes` to verify minikube is up and running.
## Versions ## Versions
#### 3.0.0 #### Future (unplanned)
* When/where to add timeframe constraints
* Timeframe slug-or-id
* Maybe slug and backlink to avail products
* Timeframe in product
* Should a product define list of time frames AND resources?
* Then can do autoselect on <resources x timeframes> and only show
complete ones
* resources are also timeframe bound
* name != unique (?)
* Can we filter drop down in admin?
* yes: ModelAdmin.formfield_for_manytomany(db_field, request, **kwargs)¶
* resources should have a slug
* can be used as an identifier and non unique names
#### 3.0.2 (planned)
* Add basic validation to ordering
#### 3.0.1 (planned)
* Show products [done]
* Link to ProductOrderForm [done]
* Continue to resources / add resources
* Confirm & create
#### 3.0.0 (2022-01-14)
* Introduce ProductOrderView * Introduce ProductOrderView
## Pre-Production requirements
* Products need to ensure *all* resources are consistent for different timeframes
* Products cannot have same resource linked twice in same timeframe

View File

@ -0,0 +1,18 @@
# Generated by Django 4.0 on 2022-01-14 22:20
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0004_auto_20220102_2020'),
]
operations = [
migrations.AddField(
model_name='product',
name='slug',
field=models.SlugField(null=True),
),
]

View File

@ -0,0 +1,28 @@
# Generated by Django 4.0 on 2022-01-14 23:25
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0005_product_slug'),
]
operations = [
migrations.AddField(
model_name='resource',
name='slug',
field=models.SlugField(null=True, unique=True),
),
migrations.AlterField(
model_name='product',
name='slug',
field=models.SlugField(null=True, unique=True),
),
migrations.AlterField(
model_name='resource',
name='name',
field=models.CharField(max_length=128),
),
]

View File

@ -1,6 +1,8 @@
from django.db import models from django.db import models
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.utils import timezone from django.utils import timezone
from django.urls import reverse
class Currency(models.Model): class Currency(models.Model):
name = models.CharField(max_length=128, unique=True) name = models.CharField(max_length=128, unique=True)
@ -43,7 +45,8 @@ class PricePerTime(models.Model):
return f"{self.price} {self.currency.short_name}/{self.timeframe}" return f"{self.price} {self.currency.short_name}/{self.timeframe}"
class Resource(models.Model): class Resource(models.Model):
name = models.CharField(max_length=128, unique=True) # CPU, RAM slug = models.SlugField(null=True, unique=True) # primary identifier
name = models.CharField(max_length=128, unique=False) # CPU, RAM
unit = models.CharField(max_length=128) # Count, GB unit = models.CharField(max_length=128) # Count, GB
minimum_units = models.FloatField(null=True, blank=True) # might have min minimum_units = models.FloatField(null=True, blank=True) # might have min
maximum_units = models.FloatField(null=True, blank=True) # might have max maximum_units = models.FloatField(null=True, blank=True) # might have max
@ -84,12 +87,16 @@ class Product(models.Model):
""" """
name = models.CharField(max_length=128, unique=True) name = models.CharField(max_length=128, unique=True)
slug = models.SlugField(null=True, unique=True)
# textconfig = models.ManyToManyField(ProductTextConfiguration) # textconfig = models.ManyToManyField(ProductTextConfiguration)
# textfieldconfig = models.ManyToManyField(ProductTextFieldConfiguration) # textfieldconfig = models.ManyToManyField(ProductTextFieldConfiguration)
resources = models.ManyToManyField(Resource, blank=True) resources = models.ManyToManyField(Resource, blank=True)
def get_absolute_url(self):
return reverse('product-detail', kwargs={'slug' : self.slug})
def __str__(self): def __str__(self):
return self.name return self.name

View File

@ -0,0 +1,10 @@
<h1>{{ object.name }}</h1>
<form method="post" >
{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="Buy">
</form>
HERE we show a link to <a href="{{ productorder }}">order</a>.

View File

@ -0,0 +1,24 @@
<h1>Select Product</h1>
<h2>Product Order</h2>
<ul>
{% for product in object_list %}
{% if product.slug %}
<li>
<a href="{{ product.get_absolute_url }}">{{ product.name }}</a>
</li>
{% endif %}
{% endfor %}
</ul>
<h2>Product List</h2>
<ul>
{% for product in object_list %}
{% if product.slug %}
<li>
<a href="{{ product.get_absolute_url }}">{{ product.name }}</a>
</li>
{% endif %}
{% endfor %}
</ul>

View File

@ -1,4 +1,7 @@
<form method="post">{% csrf_token %} Ordering a {{ product }} instance
<form method="post" >
{% csrf_token %}
{{ form.as_p }} {{ form.as_p }}
<input type="submit" value="Save"> <input type="submit" value="Next">
</form> </form>

View File

@ -1,8 +1,49 @@
from django.shortcuts import render from django.shortcuts import render, get_object_or_404
from django.urls import reverse
from django.views.generic.edit import CreateView from django.views.generic.edit import CreateView
from .models import ProductOrder from django.views.generic.base import TemplateView
from django.views.generic.list import ListView
from django.views.generic.detail import DetailView
from .models import *
class ProductOrderView(CreateView): class ProductOrderView(CreateView):
model = ProductOrder model = ProductOrder
fields = ['product', 'resources' ] fields = ['resources']
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['product'] = get_object_or_404(Product, slug=self.kwargs['product'])
print(context)
print(self.kwargs)
return context
class ProductDetailView(DetailView):
model = Product
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['productorder'] = reverse('product-order', kwargs={'product': self.object.slug })
return context
class ProductListView(ListView):
model = Product
class ProductSelectView(CreateView):
model = ProductOrder
fields = ['product' ]
class Yearly(TemplateView):
template_name = "app/config_product.html"
def get_context_data(self, **kwargs):
context = super(Yearly, self).get_context_data(**kwargs)
context['current_year'] = self.current_year
context['current_month'] = self.current_month
return context

View File

@ -19,5 +19,10 @@ from app import views as appviews
urlpatterns = [ urlpatterns = [
path('admin/', admin.site.urls), path('admin/', admin.site.urls),
path('order', appviews.ProductOrderView.as_view()) path('order', appviews.ProductSelectView.as_view()),
path('order/<slug:product>/', appviews.ProductOrderView.as_view(), name='product-order'),
path('order/<slug:product>/<slug:timeframe>/', appviews.ProductOrderView.as_view(), name='product-order'),
path('product/', appviews.ProductListView.as_view()),
path('product/<slug:slug>/', appviews.ProductDetailView.as_view(), name='product-detail')
] ]