Add CRUD for Drug

This commit is contained in:
2024-01-01 18:21:27 +00:00
parent 0249b66be7
commit 37534b31bf
16 changed files with 1355 additions and 54 deletions

View File

@@ -1,14 +1,14 @@
import os
import stripe
from django.conf import settings
# import stripe
# from django.conf import settings
os.environ["DJANGO_ALLOW_ASYNC_UNSAFE"] = "true"
# from redis import StrictRedis
# r = StrictRedis(unix_socket_path="/var/run/redis/redis.sock", db=0)
if settings.STRIPE_TEST:
stripe.api_key = settings.STRIPE_API_KEY_TEST
else:
stripe.api_key = settings.STRIPE_API_KEY_PROD
# if settings.STRIPE_TEST:
# stripe.api_key = settings.STRIPE_API_KEY_TEST
# else:
# stripe.api_key = settings.STRIPE_API_KEY_PROD

View File

@@ -2,7 +2,20 @@ from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
from .forms import CustomUserCreationForm
from .models import NotificationSettings, User
from .models import (
SEI,
Action,
Dosage,
Drug,
Effect,
Entry,
Experience,
ExperienceDose,
NotificationSettings,
Source,
Timing,
User,
)
# Register your models here.
@@ -34,3 +47,13 @@ class NotificationSettingsAdmin(admin.ModelAdmin):
admin.site.register(User, CustomUserAdmin)
admin.site.register(NotificationSettings, NotificationSettingsAdmin)
admin.site.register(Drug)
admin.site.register(Entry)
admin.site.register(Dosage)
admin.site.register(Timing)
admin.site.register(Effect)
admin.site.register(Action)
admin.site.register(Experience)
admin.site.register(Source)
admin.site.register(SEI)
admin.site.register(ExperienceDose)

View File

@@ -3,7 +3,9 @@ from django.contrib.auth.forms import UserCreationForm
from django.forms import ModelForm
from mixins.restrictions import RestrictedFormMixin
from .models import NotificationSettings, User
from mxs.restrictions import RestrictedFormMixinStaff
from .models import Drug, NotificationSettings, User
# Create your forms here.
@@ -47,3 +49,32 @@ class CustomUserCreationForm(UserCreationForm):
class Meta:
model = User
fields = "__all__"
class DrugForm(RestrictedFormMixinStaff, ModelForm):
class Meta:
model = Drug
fields = (
"name",
"drug_class",
"common_name",
"links",
"dosages",
"timings",
"effects",
"actions",
"experiences",
)
help_texts = {
"name": "Lysergic acid diethylamide, Phenibut",
"drug_class": "Psychedelic, Sedative, Stimulant",
"common_name": "LSD",
"links": "Factsheets, posts",
"dosages": "Dosages, how much to take to get a certain effect",
"timings": (
"Timings, how long to wait to reach maximum intensity (and " "others)"
),
"effects": "Effects, what does it do on a subjective level?",
"actions": "Actions, what does it do on an objective level?",
"experiences": "Experiences, what do people experience?",
}

View File

@@ -0,0 +1,162 @@
# Generated by Django 4.2.8 on 2024-01-01 17:37
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0001_initial'),
]
operations = [
migrations.CreateModel(
name='Action',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('site', models.CharField(choices=[('5HT2C', '5-HT2C'), ('5HT2A', '5-HT2A'), ('GABAB', 'GABAB'), ('NMDA', 'NMDA')], max_length=255)),
('mechanism', models.CharField(choices=[('AGONISM', 'Agonism'), ('ANTAGONISM', 'Antagomism'), ('MODULATION', 'Modulation')], max_length=255)),
('affinity', models.IntegerField(blank=True)),
('reversible', models.BooleanField(blank=True, null=True)),
],
),
migrations.CreateModel(
name='Dosage',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('unit', models.CharField(choices=[('mg', 'mg'), ('g', 'g'), ('ug', 'ug')], max_length=255)),
('threshold', models.IntegerField()),
('light', models.IntegerField()),
('common', models.IntegerField()),
('strong', models.IntegerField()),
('heavy', models.IntegerField()),
],
),
migrations.CreateModel(
name='Drug',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('drug_class', models.CharField(max_length=255)),
('common_name', models.CharField(max_length=1024, unique=True)),
('actions', models.ManyToManyField(to='core.action')),
('dosages', models.ManyToManyField(to='core.dosage')),
],
),
migrations.CreateModel(
name='Entry',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('slug', models.CharField(blank=True, max_length=1024, null=True)),
('author', models.CharField(blank=True, max_length=255, null=True)),
('description', models.CharField(blank=True, max_length=1024, null=True)),
],
),
migrations.CreateModel(
name='SEI',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('type', models.CharField(choices=[('PHYSICAL', 'Physical'), ('COGNITIVE', 'Cognitive'), ('VISUAL', 'Visual'), ('AUDITORY', 'Auditory'), ('MULTISENSORY', 'Multi-sensory'), ('TRANSPERSONAL', 'Transpersonal')], default='PHYSICAL', max_length=255)),
('subtype', models.CharField(choices=[('ENTACTOGENIC', 'Entactogenic (touch-enhancing)'), ('ENTHEOGENIC', 'Entheogenic (spirituality-enhancing)'), ('PSYCHEDELIC', 'Psychedelic (mind-manifesting)'), ('DISSOCIATIVE', 'Dissociative'), ('HALLUCINOGENIC', 'Hallucinogenic (hallucination-inducing)'), ('DELIRIANT', 'Deliriant'), ('PSYCHOTOMIMETIC', 'Psychotomimetic (psychosis-inducing)'), ('STIMULATING', 'Stimulating'), ('SEDATING', 'Sedating'), ('DEPRESSANT', 'Depressant'), ('EUPHORIC', 'Euphoric'), ('ANXIOLYTIC', 'Anxiolytic'), ('ANTIPSYCHOTIC', 'Antipsychotic'), ('PSYCHOSTIMULANT', 'Psychostimulant'), ('EUGEROIC', 'Eugeroic (wakefulness-promoting)'), ('NOOTROPIC', 'Nootropic')], max_length=255)),
('description', models.CharField(blank=True, max_length=4096, null=True)),
],
),
migrations.CreateModel(
name='Source',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=255, unique=True)),
('type', models.CharField(choices=[('PSITE', 'Professional pharmaceutical data repository'), ('DWIKI', 'Dedicated peer-reviewed community wiki'), ('CWIKI', 'Peer-reviewed community wiki'), ('WIKI', 'Private wiki'), ('DFORUM', 'Dedicated community forum'), ('FORUM', 'Community forum')], max_length=255)),
('endpoint', models.CharField(blank=True, max_length=1024, null=True)),
('score', models.IntegerField(blank=True)),
],
),
migrations.CreateModel(
name='Timing',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('unit', models.CharField(choices=[('SECONDS', 'Seconds'), ('MINUTES', 'Minutes'), ('HOURS', 'Hours'), ('DAYS', 'Days :D'), ('WEEKS', 'Weeks :O'), ('MONTHS', 'Months :-|'), ('YEARS', 'Years x_X')], default='HOURS', max_length=255)),
('onset', models.IntegerField()),
('comeup', models.IntegerField()),
('peak', models.IntegerField()),
('offset', models.IntegerField(blank=True, null=True)),
('total', models.IntegerField()),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.entry')),
],
),
migrations.CreateModel(
name='ExperienceDose',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('seconds_since_start', models.IntegerField()),
('dose', models.IntegerField()),
('dose_per_kg', models.IntegerField()),
('unit', models.CharField(choices=[('mg', 'mg'), ('g', 'g'), ('ug', 'ug')], max_length=255)),
('roa', models.CharField(max_length=255)),
('form', models.CharField(max_length=255)),
('drug', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.drug')),
],
),
migrations.CreateModel(
name='Experience',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('body_weight_kg', models.IntegerField(blank=True, null=True)),
('year_of_experience', models.IntegerField(blank=True, null=True)),
('gender', models.CharField(blank=True, max_length=255, null=True)),
('age_at_experience', models.IntegerField(blank=True, null=True)),
('date_published', models.DateTimeField(blank=True, null=True)),
('views', models.IntegerField(blank=True, null=True)),
('date_crawled', models.DateTimeField(blank=True, null=True)),
('tags', models.CharField(blank=True, max_length=255, null=True)),
('experience_id', models.IntegerField(blank=True, null=True)),
('text', models.TextField()),
('doses', models.ManyToManyField(to='core.experiencedose')),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.entry')),
],
),
migrations.AddField(
model_name='entry',
name='source',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.source'),
),
migrations.CreateModel(
name='Effect',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('entry', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.entry')),
('subjective_effects', models.ManyToManyField(to='core.sei')),
],
),
migrations.AddField(
model_name='drug',
name='effects',
field=models.ManyToManyField(to='core.effect'),
),
migrations.AddField(
model_name='drug',
name='experiences',
field=models.ManyToManyField(to='core.experience'),
),
migrations.AddField(
model_name='drug',
name='links',
field=models.ManyToManyField(to='core.entry'),
),
migrations.AddField(
model_name='drug',
name='timings',
field=models.ManyToManyField(to='core.timing'),
),
migrations.AddField(
model_name='dosage',
name='entry',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.entry'),
),
migrations.AddField(
model_name='action',
name='entry',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='core.entry'),
),
]

View File

@@ -0,0 +1,146 @@
# Generated by Django 4.2.8 on 2024-01-01 17:56
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0002_action_dosage_drug_entry_sei_source_timing_and_more'),
]
operations = [
migrations.RemoveField(
model_name='timing',
name='comeup',
),
migrations.RemoveField(
model_name='timing',
name='offset',
),
migrations.RemoveField(
model_name='timing',
name='onset',
),
migrations.RemoveField(
model_name='timing',
name='peak',
),
migrations.RemoveField(
model_name='timing',
name='total',
),
migrations.AddField(
model_name='timing',
name='comeup_lower',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='comeup_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='offset_lower',
field=models.FloatField(blank=True, null=True),
),
migrations.AddField(
model_name='timing',
name='offset_upper',
field=models.FloatField(blank=True, null=True),
),
migrations.AddField(
model_name='timing',
name='onset_lower',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='onset_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='peak_lower',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='peak_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='total_lower',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='total_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AlterField(
model_name='dosage',
name='common',
field=models.FloatField(),
),
migrations.AlterField(
model_name='dosage',
name='heavy',
field=models.FloatField(),
),
migrations.AlterField(
model_name='dosage',
name='light',
field=models.FloatField(),
),
migrations.AlterField(
model_name='dosage',
name='strong',
field=models.FloatField(),
),
migrations.AlterField(
model_name='dosage',
name='threshold',
field=models.FloatField(),
),
migrations.AlterField(
model_name='drug',
name='actions',
field=models.ManyToManyField(blank=True, to='core.action'),
),
migrations.AlterField(
model_name='drug',
name='dosages',
field=models.ManyToManyField(blank=True, to='core.dosage'),
),
migrations.AlterField(
model_name='drug',
name='effects',
field=models.ManyToManyField(blank=True, to='core.effect'),
),
migrations.AlterField(
model_name='drug',
name='experiences',
field=models.ManyToManyField(blank=True, to='core.experience'),
),
migrations.AlterField(
model_name='drug',
name='links',
field=models.ManyToManyField(blank=True, to='core.entry'),
),
migrations.AlterField(
model_name='drug',
name='timings',
field=models.ManyToManyField(blank=True, to='core.timing'),
),
]

View File

@@ -0,0 +1,68 @@
# Generated by Django 4.2.8 on 2024-01-01 17:59
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0003_remove_timing_comeup_remove_timing_offset_and_more'),
]
operations = [
migrations.RenameField(
model_name='dosage',
old_name='common',
new_name='common_lower',
),
migrations.RenameField(
model_name='dosage',
old_name='heavy',
new_name='heavy_lower',
),
migrations.RenameField(
model_name='dosage',
old_name='light',
new_name='light_lower',
),
migrations.RenameField(
model_name='dosage',
old_name='strong',
new_name='strong_lower',
),
migrations.RenameField(
model_name='dosage',
old_name='threshold',
new_name='threshold_lower',
),
migrations.AddField(
model_name='dosage',
name='common_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='dosage',
name='heavy_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='dosage',
name='light_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='dosage',
name='strong_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
migrations.AddField(
model_name='dosage',
name='threshold_upper',
field=models.FloatField(default=0),
preserve_default=False,
),
]

View File

@@ -0,0 +1,30 @@
# Generated by Django 4.2.8 on 2024-01-01 18:02
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('core', '0004_rename_common_dosage_common_lower_and_more'),
]
operations = [
migrations.AddField(
model_name='dosage',
name='roa',
field=models.CharField(choices=[('ORAL', 'Oral'), ('SMOKED', 'Smoked/vaped'), ('INSUFFLATED', 'Insufflated'), ('INJECTED', 'Injected'), ('SUBLINGUAL', 'Sublingual'), ('TRANSDERMAL', 'Transdermal'), ('RECTAL', 'Rectal')], default='ORAL', max_length=255),
preserve_default=False,
),
migrations.AddField(
model_name='timing',
name='roa',
field=models.CharField(choices=[('ORAL', 'Oral'), ('SMOKED', 'Smoked/vaped'), ('INSUFFLATED', 'Insufflated'), ('INJECTED', 'Injected'), ('SUBLINGUAL', 'Sublingual'), ('TRANSDERMAL', 'Transdermal'), ('RECTAL', 'Rectal')], default='ORAL', max_length=255),
preserve_default=False,
),
migrations.AlterField(
model_name='experiencedose',
name='roa',
field=models.CharField(choices=[('ORAL', 'Oral'), ('SMOKED', 'Smoked/vaped'), ('INSUFFLATED', 'Insufflated'), ('INJECTED', 'Injected'), ('SUBLINGUAL', 'Sublingual'), ('TRANSDERMAL', 'Transdermal'), ('RECTAL', 'Rectal')], max_length=255),
),
]

View File

@@ -19,6 +19,16 @@ MECHANISM_CHOICES = (
("MODULATION", "Modulation"),
)
ROA_CHOICES = (
("ORAL", "Oral"),
("SMOKED", "Smoked/vaped"),
("INSUFFLATED", "Insufflated"),
("INJECTED", "Injected"),
("SUBLINGUAL", "Sublingual"),
("TRANSDERMAL", "Transdermal"),
("RECTAL", "Rectal"),
)
SOURCE_TYPE_CHOICES = (
("PSITE", "Professional pharmaceutical data repository"),
("DWIKI", "Dedicated peer-reviewed community wiki"),
@@ -53,6 +63,30 @@ SEI_TYPE_CHOICES = (
("TRANSPERSONAL", "Transpersonal"),
)
SEI_SUBTYPE_CHOICES = (
# Common psychedelic subtypes
("ENTACTOGENIC", "Entactogenic (touch-enhancing)"),
("ENTHEOGENIC", "Entheogenic (spirituality-enhancing)"),
("PSYCHEDELIC", "Psychedelic (mind-manifesting)"),
("DISSOCIATIVE", "Dissociative"),
("HALLUCINOGENIC", "Hallucinogenic (hallucination-inducing)"),
# Unpleasant psychedelic-esque subtypes
("DELIRIANT", "Deliriant"),
("PSYCHOTOMIMETIC", "Psychotomimetic (psychosis-inducing)"),
# Common recreational drug subtypes
("STIMULATING", "Stimulating"),
("SEDATING", "Sedating"),
("DEPRESSANT", "Depressant"),
("EUPHORIC", "Euphoric"),
# Common pharmaceutical subtypes
("ANXIOLYTIC", "Anxiolytic"),
("ANTIPSYCHOTIC", "Antipsychotic"),
# Common nootropic subtypes
("PSYCHOSTIMULANT", "Psychostimulant"),
("EUGEROIC", "Eugeroic (wakefulness-promoting)"),
("NOOTROPIC", "Nootropic"),
)
class User(AbstractUser):
# Stripe customer ID
@@ -99,11 +133,14 @@ class Entry(models.Model):
Used to gather conflicting information and store it coherently.
"""
source = models.ForeignKey(Source)
source = models.ForeignKey(Source, on_delete=models.CASCADE)
# Slug of the article on the Source
slug = models.CharField(max_length=1024, null=True, blank=True)
# Authorship information, if present
author = models.CharField(max_length=255, null=True, blank=True)
# Extra information can be added
description = models.CharField(max_length=1024, null=True, blank=True)
@@ -114,26 +151,33 @@ class Dosage(models.Model):
Linked to Entry to analyse conflicting records.
"""
entry = models.ForeignKey("core.Entry")
entry = models.ForeignKey("core.Entry", on_delete=models.CASCADE)
roa = models.CharField(max_length=255, choices=ROA_CHOICES)
# Unit of mass as drugs are diverse
# Dosages varying between micrograms and grams
unit = models.CharField(max_length=255, choices=DOSAGE_UNIT_CHOICES)
# I can no longer say I am sober, but it is slight
threshold = models.IntegerField()
threshold_lower = models.FloatField()
threshold_upper = models.FloatField()
# Light
light = models.IntegerField()
light_lower = models.FloatField()
light_upper = models.FloatField()
# Average dose for a user
common = models.IntegerField()
common_lower = models.FloatField()
common_upper = models.FloatField()
# Strong intensity, many sober activities may become impossible
strong = models.IntegerField()
strong_lower = models.FloatField()
strong_upper = models.FloatField()
# Highest intensity
heavy = models.IntegerField()
heavy_lower = models.FloatField()
heavy_upper = models.FloatField()
class Timing(models.Model):
@@ -142,7 +186,9 @@ class Timing(models.Model):
Linked to Entry to analyse conflicting records.
"""
entry = models.ForeignKey("core.Entry")
entry = models.ForeignKey("core.Entry", on_delete=models.CASCADE)
roa = models.CharField(max_length=255, choices=ROA_CHOICES)
# Unit of time as drugs are diverse
# Half-lives varying between seconds and months
@@ -151,19 +197,24 @@ class Timing(models.Model):
)
# It has just now begin, I can no longer say I am sober
onset = models.IntegerField()
onset_lower = models.FloatField()
onset_upper = models.FloatField()
# The intensity is accelerating
comeup = models.IntegerField()
comeup_lower = models.FloatField()
comeup_upper = models.FloatField()
# The maximum intensity has been reached
# How long this state occurs
peak = models.IntegerField()
peak_lower = models.FloatField()
peak_upper = models.FloatField()
# How long it takes to get back to baseline
offset = models.IntegerField(null=True, blank=True)
offset_lower = models.FloatField(null=True, blank=True)
offset_upper = models.FloatField(null=True, blank=True)
total = models.IntegerField()
total_lower = models.FloatField()
total_upper = models.FloatField()
class SEI(models.Model):
@@ -178,6 +229,11 @@ class SEI(models.Model):
max_length=255, choices=SEI_TYPE_CHOICES, default="PHYSICAL"
)
subtype = models.CharField(
max_length=255,
choices=SEI_SUBTYPE_CHOICES,
)
# WIP: consider euphoric, depressant, relaxant
# Specify how
@@ -191,7 +247,7 @@ class Effect(models.Model):
Linked to Entry to analyse conflicting records.
"""
entry = models.ForeignKey("core.Entry")
entry = models.ForeignKey("core.Entry", on_delete=models.CASCADE)
# List of subjective effects, since they would likely be from the same entry
subjective_effects = models.ManyToManyField(SEI)
@@ -205,7 +261,7 @@ class Action(models.Model):
Linked to Entry to analyse conflicting records.
"""
entry = models.ForeignKey("core.Entry")
entry = models.ForeignKey("core.Entry", on_delete=models.CASCADE)
# Site - like 5HT2A for LSD
site = models.CharField(max_length=255, choices=SITE_CHOICES)
@@ -216,6 +272,73 @@ class Action(models.Model):
# Free integer for binding affinity
affinity = models.IntegerField(blank=True)
# For MAOI, SSRI
reversible = models.BooleanField(blank=True, null=True)
# MAOI A (I)
# Site: Monoamine Oxidase A
# Mechanism: Inhibition
# Affinity: Permanent (999999)
# Moclobemide
# Site: Monoamine Oxidase A
# Mechanism: Inhibition
# Affinity: Reversible (1)
class ExperienceDose(models.Model):
# Seconds since the start of the experiment
# To be converted to T+00:22 format
seconds_since_start = models.IntegerField()
# Dosage, integer
dose = models.IntegerField()
# Dose per kg of body weight
dose_per_kg = models.IntegerField()
# Unit of mass as drugs are diverse
unit = models.CharField(max_length=255, choices=DOSAGE_UNIT_CHOICES)
# Route of administration, oral, smoked, injected, etc
roa = models.CharField(max_length=255, choices=ROA_CHOICES)
# The drug that was taken, linked to our database
drug = models.ForeignKey("core.Drug", on_delete=models.CASCADE)
# The form of the drug: pills, powder, crystals, tabs, etc
form = models.CharField(max_length=255)
# TODO: Subjective effects (use AI/ML)
# TODO: Sentiment analysis (use AI/ML)
# TODO: Time-based effects (use AI/ML)
class Experience(models.Model):
"""
Registers a subjective experience from a user.
"""
# Where did the data come from?
entry = models.ForeignKey("core.Entry", on_delete=models.CASCADE)
# List of the doses and drugs taken
doses = models.ManyToManyField(ExperienceDose)
# Erowid-specific fields
body_weight_kg = models.IntegerField(blank=True, null=True)
year_of_experience = models.IntegerField(blank=True, null=True)
gender = models.CharField(max_length=255, blank=True, null=True)
age_at_experience = models.IntegerField(blank=True, null=True)
date_published = models.DateTimeField(blank=True, null=True)
views = models.IntegerField(blank=True, null=True)
date_crawled = models.DateTimeField(blank=True, null=True)
tags = models.CharField(max_length=255, blank=True, null=True)
experience_id = models.IntegerField(blank=True, null=True)
# Description of the experience
text = models.TextField()
class Drug(models.Model):
"""
@@ -225,42 +348,34 @@ class Drug(models.Model):
# Lysergic acid diethylamide, Phenibut
name = models.CharField(max_length=255, unique=True)
# Psychedelic, Sedative
# Psychedelic, Sedative, Stimulant
drug_class = models.CharField(max_length=255)
# LSD
common_name = models.CharField(max_length=1024, unique=True)
# Factsheets, posts
links = models.ManyToManyField(Entry)
links = models.ManyToManyField(Entry, blank=True)
# Dosages, how much to take to get a certain effect
dosages = models.ManyToManyField(Dosage)
dosages = models.ManyToManyField(Dosage, blank=True)
# Timings, how long to wait to reach maximum intensity (and others)
timings = models.ManyToManyField(Timing)
timings = models.ManyToManyField(Timing, blank=True)
# Effects, what does it do on a subjective level?
effects = models.ManyToManyField(Effect)
effects = models.ManyToManyField(Effect, blank=True)
# Actions, what does it do on an objective level?
actions = models.ManyToManyField(Action)
actions = models.ManyToManyField(Action, blank=True)
# Experiences, what do people experience?
experiences = models.ManyToManyField(Experience, blank=True)
# class Perms(models.Model):
# class Meta:
# permissions = (
# ("bypass_hashing", "Can bypass field hashing"), #
# ("bypass_blacklist", "Can bypass the blacklist"), #
# ("bypass_encryption", "Can bypass field encryption"), #
# ("bypass_obfuscation", "Can bypass field obfuscation"), #
# ("bypass_delay", "Can bypass data delay"), #
# ("bypass_randomisation", "Can bypass data randomisation"), #
# ("post_irc", "Can post to IRC"),
# ("post_discord", "Can post to Discord"),
# ("query_search", "Can search with query strings"), #
# ("use_insights", "Can use the Insights page"),
# ("index_int", "Can use the internal index"),
# ("index_meta", "Can use the meta index"),
# ("restricted_sources", "Can access restricted sources"),
# ("permission_name", "Permission description"),
# )

View File

@@ -208,8 +208,8 @@
</a>
<div class="navbar-dropdown">
<a class="navbar-item" href="#">
Admin1
<a class="navbar-item" href="{% url 'drugs' type='page' %}">
Drugs
</a>
<a class="navbar-item" href="#">
Admin2
@@ -292,8 +292,16 @@
{% endblock %}
<section class="section">
<div class="container">
{% block content %}
{% block content_wrapper %}
{% block content %}
{% endblock %}
{% endblock %}
<div id="modals-here">
</div>
<div id="windows-here">
</div>
<div id="widgets-here" style="display: none;">
</div>
</div>
</section>
</body>

View File

@@ -0,0 +1,73 @@
{% load cache %}
{% load cachalot cache %}
{% get_last_invalidation 'core.Drug' as last %}
{% include 'mixins/partials/notify.html' %}
{% cache 600 objects_drugs request.user.id object_list last %}
<table
class="table is-fullwidth is-hoverable"
hx-target="#{{ context_object_name }}-table"
id="{{ context_object_name }}-table"
hx-swap="outerHTML"
hx-trigger="{{ context_object_name_singular }}Event from:body"
hx-get="{{ list_url }}">
<thead>
<th>id</th>
<th>name</th>
<th>drug class</th>
<th>common name</th>
<th>links</th>
<th>dosages</th>
<th>timings</th>
<th>effects</th>
<th>actions</th>
<th>experiences</th>
<th>actions</th>
</thead>
{% for item in object_list %}
<tr>
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.drug_class }}</td>
<td>{{ item.common_name }}s</td>
<td>{{ item.links.count }}</td>
<td>{{ item.dosages.count }}</td>
<td>{{ item.timings.count }}</td>
<td>{{ item.effects.count }}</td>
<td>{{ item.actions.count }}</td>
<td>{{ item.experiences.count }}</td>
<td>
<div class="buttons">
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{% url 'drug_update' type=type pk=item.id %}"
hx-trigger="click"
hx-target="#{{ type }}s-here"
hx-swap="innerHTML"
class="button">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-pencil"></i>
</span>
</span>
</button>
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-delete="{% url 'drug_delete' type=type pk=item.id %}"
hx-trigger="click"
hx-target="#modals-here"
hx-swap="innerHTML"
hx-confirm="Are you sure you wish to delete {{ item.name }}?"
class="button">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-xmark"></i>
</span>
</span>
</button>
</div>
</td>
</tr>
{% endfor %}
</table>
{% endcache %}

52
core/views/drugs.py Normal file
View File

@@ -0,0 +1,52 @@
from django.contrib.auth.mixins import LoginRequiredMixin
from django.shortcuts import render
from rest_framework.views import APIView
from core.forms import DrugForm
from core.models import Drug
from mxs.restrictions import StaffMemberRequiredMixin
from mxs.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate
class DrugList(LoginRequiredMixin, StaffMemberRequiredMixin, ObjectList):
list_template = "partials/drug-list.html"
model = Drug
page_title = "Global list of drugs"
list_url_name = "drugs"
list_url_args = ["type"]
submit_url_name = "drug_create"
delete_all_url_name = "drug_clear"
class DrugCreate(LoginRequiredMixin, StaffMemberRequiredMixin, ObjectCreate):
model = Drug
form_class = DrugForm
submit_url_name = "drug_create"
class DrugUpdate(LoginRequiredMixin, StaffMemberRequiredMixin, ObjectUpdate):
model = Drug
form_class = DrugForm
submit_url_name = "drug_update"
class DrugDelete(LoginRequiredMixin, StaffMemberRequiredMixin, ObjectDelete):
model = Drug
class DrugClear(LoginRequiredMixin, StaffMemberRequiredMixin, APIView):
def delete(self, request):
template_name = "mixins/partials/notify.html"
drugs_all = Drug.objects.all()
drugs_all.delete()
context = {
"message": "Deleted all drugs",
"class": "success",
}
response = render(request, template_name, context)
response["HX-Trigger"] = "drugEvent"
return response