Compare commits

...

8 Commits

Author SHA1 Message Date
Chris GIACOFEI
581289c947 A little restructuring. 2024-05-31 11:56:07 -04:00
Chris GIACOFEI
c4d9d9489d Fix names to make all the things work.
Need to use 'yeast' instead of 'sample' to keep thing consistent
for the label generator.
2024-05-31 08:46:57 -04:00
Chris GIACOFEI
f59ec40958 Hopefully this makes gunicorn work... 2024-05-31 08:14:37 -04:00
Chris GIACOFEI
77354bfcbd Custom UUID field for yeast samples/batches.
Prepends date 'YYYYMMDD' to some random numbers.
2024-05-31 08:14:07 -04:00
Chris GIACOFEI
2e21838898 Some housekeeping 2024-05-31 08:13:20 -04:00
Chris GIACOFEI
f5c87eb22f Add missing requirement. 2024-05-31 08:13:05 -04:00
Chris GIACOFEI
ee1cdd2a39 Fix incorrect data for label. 2024-05-31 08:12:28 -04:00
Chris GIACOFEI
18b675af85 Fix wrong name. 2024-05-31 08:12:07 -04:00
16 changed files with 113 additions and 52 deletions

1
.gitignore vendored
View File

@ -6,3 +6,4 @@ __pycache__
brewery.sqlite
media
secrets.json
.env

View File

@ -1,4 +1,9 @@
import labels
import datetime
from random import randint
from django.db.models import BigIntegerField
from django.urls import reverse
from reportlab.graphics import shapes
@ -9,6 +14,12 @@ from config.settings import DEBUG
BREWFATHER_APP_ROOT = 'https://web.brewfather.app'
def random_with_N_digits(n):
range_start = 10**(n-1)
range_end = (10**n)-1
return randint(range_start, range_end)
class AveryLabel:
"""
test_labels = [
@ -164,3 +175,40 @@ class AveryLabel:
# Save the file and we are done.
sheet.save(render_file)
class DateUUIDField(BigIntegerField):
"""
A field which stores a Short UUID value with prepended date. This may also have
the Boolean attribute 'auto' which will set the value on initial save to a
new UUID value (calculated using shortuuid's default (uuid4)). Note that while all
UUIDs are expected to be unique we enforce this with a DB constraint.
"""
def __init__(self, auto=True, *args, **kwargs):
self.auto = auto
if auto:
# Do not let the user edit UUIDs if they are auto-assigned.
kwargs['editable'] = False
kwargs['blank'] = True
kwargs['unique'] = True # if you want to be paranoid, set unique=True in your instantiation of the field.
super(DateUUIDField, self).__init__(*args, **kwargs)
def pre_save(self, model_instance, add):
"""
This is used to ensure that we auto-set values if required.
See CharField.pre_save
"""
value = super(DateUUIDField, self).pre_save(model_instance, add)
if self.auto and not value:
# Assign a new value for this attribute if required.
x = datetime.datetime.now()
front = x.strftime("%Y%m%d")
value = int('{}{}'.format(front,random_with_N_digits(6)))
setattr(model_instance, self.attname, value)
return value
def formfield(self, **kwargs):
if self.auto:
return None
return super(DateUUIDField, self).formfield(**kwargs)

View File

@ -72,7 +72,7 @@ MIDDLEWARE = [
MEDIA_ROOT = '/tmp/media/'
MEDIA_URL = '/media/'
STATIC_ROOT = '/tmp/static/'
STATIC_ROOT = os.path.join(BASE_DIR,'sitestatic')
STATIC_URL = '/static/'
TEMPLATES = [

View File

@ -1,16 +1,16 @@
"""
WSGI config for django_sqlite project.
WSGI config for testing project.
It exposes the WSGI callable as a module-level variable named ``application``.
For more information on this file, see
https://docs.djangoproject.com/en/1.10/howto/deployment/wsgi/
https://docs.djangoproject.com/en/5.0/howto/deployment/wsgi/
"""
import os
from django.core.wsgi import get_wsgi_application
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "django_sqlite.settings")
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'config.settings')
application = get_wsgi_application()

View File

@ -6,3 +6,4 @@ docutils==0.21.2
django-mathfilters==1.0.0
pylabels==1.2.1
reportlab==4.2.0
wiki==0.11.1

View File

@ -1,30 +0,0 @@
{% extends "base.html" %}
{% load mathfilters %}
{% block title %}Yeast Samples{% endblock %}
{% block content %}
<main role="main">
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">Yeast Sample: {{ sample.id }}</h1>
</div>
</div>
<div class="container">
<h3>{{ batch.strain.name }}</h3>
Batch Source: {{ batch.source }}
</div> <!-- /container -->
{% for sample in batch.remaining_samples %}
<ul>
<li><a href="/samples/{{ sample.id }}">{{ sample.packaging_date }}</a> Strain: {{ sample.age }} days, Viability:{{ sample.viability|mul:100|floatformat:1 }}%</li>
</ul>
{% endfor %}
</main>
{% endblock %}

View File

@ -6,6 +6,7 @@ from django.contrib.auth.models import User
from django.db.models import Count
import math
from config.extras import DateUUIDField
import logging
logger = logging.getLogger('django')
@ -71,7 +72,7 @@ class Batch(CustomModel):
'PR': 'Propogated',
'SL': 'Slurry',
}
id = DateUUIDField(primary_key=True)
parent = models.ManyToManyField('Yeast', related_name='+', blank=True)
production_date = models.DateField()
strain = models.ForeignKey(Strain, on_delete=models.PROTECT, default=0)
@ -105,6 +106,7 @@ class Yeast(CustomModel):
"""
Store an individual sample of yeast.
"""
id = DateUUIDField(primary_key=True)
batch = models.ForeignKey(Batch, on_delete=models.CASCADE)
generation_num = models.IntegerField(default=0)
storage = models.ForeignKey(Storage, on_delete=models.CASCADE)

View File

@ -19,7 +19,6 @@
<p><p>
</div> <!-- /container -->
{% url 'yeast:labels' batch.id %}
<div class="container">
<form action="{% url 'yeast:labels' batch.id %}" method="post">
<fieldset>

View File

@ -25,12 +25,26 @@
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
<p><p>
Test
<a href="{% url 'yeast:addbatch' %}">Add Batch</a>
<ul>
{% for batch in object_list %}
{% if not batch.remaining_samples %}
<li><a href="{% url 'yeast:batch' batch.id %}">{{ batch }}</a></li>
<ul>
{% for sample in batch.yeast_set.all %}
{% if sample.pitched %}<strike>{% endif %}
<li><a href="{% url 'yeast:yeast' sample.id %}">Sample #{{ sample.id }}</a> Age: {{ sample.age }} days, Viability: {{ sample.viability|mul:100|floatformat:1 }}%</li>
{% if sample.pitched %}</strike>{% endif %}
{% endfor %}
</ul>
{% endif %}
{% endfor %}
</ul>
<p><p>
<a href="{% url 'yeast:addbatch' %}">Add Batch</a><br>
<a href="{% url 'yeast:addstrain' %}">Add Yeast Strain</a>
</div> <!-- /container -->

View File

@ -0,0 +1,36 @@
{% extends "base.html" %}
{% load mathfilters %}
{% block title %}Yeast Samples{% endblock %}
{% block content %}
<main role="main">
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<div class="container">
<h1 class="display-3">Yeast Sample: {{ yeast.id }}</h1>
</div>
</div>
<div class="container">
<h3>{{ batch.strain.name }}</h3>
Batch Source: {{ batch.get_source_display }}<br>
Production Date: {{ sample.batch.production_date }}
<p><p>
{% for sample in batch.remaining_samples %}
<ul>
<li><a href="{% url 'yeast:yeast' sample.id %}">{{ sample.id }}</a> - Storage method: {{ sample.storage.name }} for {{ sample.age }} days, Viability: {{ sample.viability|mul:100|floatformat:1 }}%</li>
</ul>
{% endfor %}
{% for sample in batch.used_samples %}
<ul>
<li><a href="{% url 'yeast:yeast' sample.id %}">{{ sample.id }}</a></li>
</ul>
{% endfor %}
</div> <!-- /container -->
</main>
{% endblock %}

View File

@ -18,9 +18,9 @@ class YeastListView(ListView):
class BatchListView(ListView):
model = Batch
def sample(request, sample_id):
def sample(request, yeast_id):
sample = get_object_or_404(Yeast, pk=sample_id)
sample = get_object_or_404(Yeast, pk=yeast_id)
sample_batch = get_object_or_404(Batch, pk=sample.batch_id)
return render(request, 'yeast/sample.html', {'sample': sample, 'batch':sample_batch})
@ -36,9 +36,7 @@ def batch_labels(request, batch_id):
"""
skip_count = request.POST.get("skip_count", "")
samples = request.POST.getlist("samples", "")
batch = get_object_or_404(Batch, pk=batch_id)
to_print = list(filter(lambda d: str(d.id) in samples, batch.yeast_set.all()))
# Create the HttpResponse object with the appropriate PDF headers.
@ -51,17 +49,9 @@ def batch_labels(request, batch_id):
labels = []
for sample in to_print:
# labels.append({
# 'date': sample.batch.production_date,
# 'name': sample.name,
# 'manufacturer': sample.batch.strain.manufacturer.name,
# 'id': sample.id,
# 'blank': False,
# 'host': request.get_host(),
# })
labels.append({
'id': sample.id,
'title': '{} {}'.format(sample.batch.strain.manufacturer.name, sample.name),
'title': '{} {}'.format(sample.batch.strain.manufacturer.name, sample.batch.strain.name),
'data': ['ID: {}'.format(sample.id), 'Date: {}'.format(sample.batch.production_date)],
'blank': False,
'host': request.get_host(),