-
Notifications
You must be signed in to change notification settings - Fork 9
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Update backend to latest developments
- Loading branch information
Showing
12 changed files
with
607 additions
and
347 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,28 @@ | |
|
||
|
||
def init(): | ||
# create initial admins given by an env var. Mails separated by comma | ||
for email in [m.strip() for m in config("BACKEND_ADMINS", "").split(",")]: | ||
if not get_user_model().objects.filter(email=email): | ||
get_user_model().objects.create_superuser(email, terms_of_use=True) | ||
# create initial admins given by an env var. Mails separated by comma, with optional token | ||
# So the env var can be in the form: [email protected]=ABCDEFGH,[email protected],[email protected] | ||
# this allows a user to have a persistent token among all the deployments | ||
for admin in [ | ||
m.strip().split("=") for m in config("BACKEND_ADMINS", "").split(",") | ||
]: | ||
if len(admin) > 1: | ||
# we specified the mail and token | ||
(email, token) = admin | ||
if not get_user_model().objects.filter(email=email): | ||
# user not found by mail, create it | ||
get_user_model().objects.create_superuser( | ||
email, terms_of_use=True, token=token | ||
) | ||
elif not get_user_model().objects.filter(email=email, token=token): | ||
# user found by mail but not by token, update the token | ||
user = get_user_model().objects.filter(email=email).first() | ||
if user: | ||
user.token = token | ||
user.save() | ||
else: | ||
# we specified only the mail | ||
(email,) = admin | ||
if not get_user_model().objects.filter(email=email): | ||
get_user_model().objects.create_superuser(email, terms_of_use=True) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,13 @@ | ||
import uuid | ||
|
||
from django.db import models | ||
from django.db.models import BooleanField, CharField | ||
from django.utils.translation import gettext_lazy as _ | ||
from mailauth.contrib.user.models import AbstractEmailUser | ||
|
||
|
||
class EcobalyseUser(AbstractEmailUser): | ||
organization = models.CharField( | ||
_("Organization"), max_length=150, blank=True, default="" | ||
) | ||
terms_of_use = models.BooleanField(default=False) | ||
token = models.CharField( | ||
organization = CharField(_("Organization"), max_length=150, blank=True, default="") | ||
terms_of_use = BooleanField(default=False) | ||
token = CharField( | ||
_("TOKEN"), max_length=36, default=uuid.uuid4, editable=False, db_index=True | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
{% extends "admin/change_list.html" %} | ||
{% load i18n static %} | ||
|
||
{% block object-tools-items %} | ||
{{ block.super }} | ||
<li> | ||
<a href="{% url 'admin:from-json' %}" class="button"> | ||
{% trans "Create from JSON" %} | ||
</a> | ||
</li> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
{% extends "admin/base_site.html" %} | ||
{% load i18n static %} | ||
{% block content %} | ||
<h1>{% trans "Create the Example from the provided JSON block in Ecobalyse" %}</h1> | ||
<div class="module"> | ||
<form method="post"> | ||
{% csrf_token %} | ||
{{ form.as_p }} | ||
|
||
<input type="submit" value="{% trans 'Submit' %}"> | ||
</form> | ||
</div> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,32 +1,247 @@ | ||
from django.contrib import admin | ||
import json | ||
|
||
from django import forms | ||
from django.contrib import admin, messages | ||
from django.http import HttpResponseRedirect | ||
from django.shortcuts import render | ||
from django.urls import path, reverse | ||
from django.utils.html import format_html | ||
from django.utils.translation import gettext_lazy as _ | ||
|
||
from backend.admin import admin_site | ||
from textile.models import Example, Material, Process, Product | ||
|
||
|
||
class ProductAdmin(admin.ModelAdmin): | ||
save_on_top = True | ||
search_fields = ["name"] | ||
list_display = ("name", "id", "mass", "volume") | ||
fieldsets = [ | ||
(None, {"fields": ("name", "id", "mass", "surfaceMass", "yarnSize", "fabric")}), | ||
( | ||
_("Economics"), | ||
{ | ||
"fields": ( | ||
"business", | ||
"marketingDuration", | ||
"numberOfReferences", | ||
"price", | ||
"repairCost", | ||
"traceability", | ||
) | ||
}, | ||
), | ||
(_("Dyeing"), {"fields": ("defaultMedium",)}), | ||
(_("Making"), {"fields": ("pcrWaste", "complexity")}), | ||
( | ||
_("Use"), | ||
{ | ||
"fields": ( | ||
"ironingElecInMJ", | ||
"nonIroningProcessUuid", | ||
"daysOfWear", | ||
"defaultNbCycles", | ||
"ratioDryer", | ||
"ratioIroning", | ||
"timeIroning", | ||
"wearsPerCycle", | ||
) | ||
}, | ||
), | ||
(_("End Of Life"), {"fields": ("volume",)}), | ||
] | ||
|
||
|
||
class MaterialsInline(admin.TabularInline): | ||
model = Example.materials.through | ||
|
||
|
||
class MaterialAdmin(admin.ModelAdmin): | ||
save_on_top = True | ||
search_fields = ["name"] | ||
# inlines = [MaterialsInline] | ||
list_display = ("name", "shortName", "id", "related_process") | ||
|
||
def related_process(self, obj): | ||
url = reverse( | ||
"admin:textile_process_change", args=(obj.materialProcessUuid.pk,) | ||
) | ||
return format_html(f'<a href="{url}">{obj.materialProcessUuid.name}</a>') | ||
|
||
related_process.allow_tags = True | ||
fieldsets = [ | ||
(None, {"fields": ("name", "shortName", "origin", "priority")}), | ||
( | ||
_("Processes"), | ||
{"fields": ("materialProcessUuid", "recycledProcessUuid", "recycledFrom")}, | ||
), | ||
(_("Geography"), {"fields": ("geographicOrigin", "defaultCountry")}), | ||
(_("Other"), {"fields": ("manufacturerAllocation", "recycledQualityRatio")}), | ||
] | ||
|
||
|
||
class ProcessAdmin(admin.ModelAdmin): | ||
save_on_top = True | ||
search_fields = ["name"] | ||
list_display = ("name", "source", "uuid", "step_usage") | ||
fieldsets = [ | ||
( | ||
None, | ||
{ | ||
"fields": ( | ||
"name", | ||
"uuid", | ||
"source", | ||
"search", | ||
"info", | ||
"unit", | ||
"step_usage", | ||
"correctif", | ||
) | ||
}, | ||
), | ||
(_("Energy"), {"fields": ("heat_MJ", "elec_pppm", "elec_MJ")}), | ||
(_("Scores"), {"fields": ("pef", "ecs")}), | ||
( | ||
_("Impacts"), | ||
{ | ||
"fields": ( | ||
"acd", | ||
"cch", | ||
"etf", | ||
"etfc", | ||
"fru", | ||
"fwe", | ||
"htc", | ||
"htcc", | ||
"htn", | ||
"htnc", | ||
"ior", | ||
"ldu", | ||
"mru", | ||
"ozd", | ||
"pco", | ||
"pma", | ||
"swe", | ||
"tre", | ||
"wtu", | ||
) | ||
}, | ||
), | ||
] | ||
|
||
|
||
class ExampleJSONForm(forms.ModelForm): | ||
class Meta: | ||
model = Example | ||
fields = ["id", "name", "product"] | ||
|
||
query = forms.JSONField() | ||
|
||
class ExempleAdmin(admin.ModelAdmin): | ||
|
||
class ExampleAdmin(admin.ModelAdmin): | ||
search_fields = ["name"] | ||
inlines = [MaterialsInline] | ||
change_list_template = "admin/textile/example/change_list.html" | ||
save_on_top = True | ||
list_display = ("name", "id", "product") | ||
fieldsets = [ | ||
(None, {"fields": ["id", "name", "mass"]}), | ||
( | ||
"Durabilité non-physique", | ||
{ | ||
"fields": [ | ||
"product", | ||
"numberOfReferences", | ||
"price", | ||
"marketingDuration", | ||
"business", | ||
"traceability", | ||
"repairCost", | ||
], | ||
"description": "Paramètres de durabilité non-physique. Voir la <a href='https://fabrique-numerique.gitbook.io/ecobalyse/textile/durabilite'>Documentation</a>", | ||
}, | ||
), | ||
( | ||
"Filature", | ||
{ | ||
"fields": [ | ||
"countrySpinning", | ||
], | ||
"description": "<a href='https://fabrique-numerique.gitbook.io/ecobalyse/textile/etapes-du-cycle-de-vie/etape-2-fabrication-du-fil-new'>Documentation</a>", | ||
}, | ||
), | ||
( | ||
"Fabrication", | ||
{ | ||
"fields": [ | ||
"fabricProcess", | ||
"countryFabric", | ||
], | ||
"description": "<a href='https://fabrique-numerique.gitbook.io/ecobalyse/textile/cycle-de-vie-des-produits-textiles/etape-2-fabrication-du-fil'>Documentation</a>", | ||
}, | ||
), | ||
( | ||
"Confection", | ||
{ | ||
"fields": [ | ||
"airTransportRatio", | ||
"countryMaking", | ||
], | ||
"description": "<a href='https://fabrique-numerique.gitbook.io/ecobalyse/textile/etapes-du-cycle-de-vie/confection'>Documentation</a>", | ||
}, | ||
), | ||
( | ||
"Ennoblissement", | ||
{ | ||
"fields": [ | ||
"countryDyeing", | ||
], | ||
"description": "<a href='https://fabrique-numerique.gitbook.io/ecobalyse/textile/etapes-du-cycle-de-vie/ennoblissement'>Documentation</a>", | ||
}, | ||
), | ||
] | ||
|
||
def get_urls(self): | ||
return [ | ||
path( | ||
"from-json/", | ||
self.admin_site.admin_view(self.from_json), | ||
name="from-json", | ||
) | ||
] + super().get_urls() | ||
|
||
def from_json(self, request): | ||
"""/admin/textile/example/from-json/ form""" | ||
if request.method == "POST": | ||
form = ExampleJSONForm(request.POST) | ||
if form.is_valid(): | ||
json_example = { | ||
"id": request.POST["id"], | ||
"name": request.POST["name"], | ||
"product": request.POST["product"], | ||
"query": json.loads(request.POST["query"]), | ||
} | ||
try: | ||
example = Example._fromJSON(json_example) | ||
example.save() | ||
|
||
for share in json_example["query"]["materials"]: | ||
example.add_material(share) | ||
self.message_user(request, _("Your Example has been recorded")) | ||
return HttpResponseRedirect("..") | ||
except TypeError: | ||
self.message_user( | ||
request, | ||
_("Your JSON doesn't look like a valid example"), | ||
level=messages.ERROR, | ||
) | ||
else: | ||
form = ExampleJSONForm() | ||
context = dict(self.admin_site.each_context(request), form=form) | ||
return render(request, "admin/textile/example/from_json.html", context) | ||
|
||
|
||
admin_site.register(Product, ProductAdmin) | ||
admin_site.register(Material, MaterialAdmin) | ||
admin_site.register(Process, ProcessAdmin) | ||
admin_site.register(Example, ExempleAdmin) | ||
admin_site.register(Example, ExampleAdmin) |
Oops, something went wrong.