mirror of
https://github.com/daniviga/django-ram.git
synced 2025-08-04 13:17:50 +02:00
Add shop field (from properties) (#48)
* Add shop field (from properties) * Update template
This commit is contained in:
Submodule arduino/dcc-ex.github.io updated: e661bb0fab...9acc446358
Submodule arduino/vim-arduino updated: 2ded67cdf0...111db616db
@@ -59,7 +59,7 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"number_of_pages",
|
"number_of_pages",
|
||||||
"published",
|
"published",
|
||||||
)
|
)
|
||||||
autocomplete_fields = ("authors", "publisher")
|
autocomplete_fields = ("authors", "publisher", "shop")
|
||||||
readonly_fields = ("creation_time", "updated_time")
|
readonly_fields = ("creation_time", "updated_time")
|
||||||
search_fields = ("title", "publisher__name", "authors__last_name")
|
search_fields = ("title", "publisher__name", "authors__last_name")
|
||||||
list_filter = ("publisher__name", "authors")
|
list_filter = ("publisher__name", "authors")
|
||||||
@@ -86,6 +86,7 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"Purchase data",
|
"Purchase data",
|
||||||
{
|
{
|
||||||
"fields": (
|
"fields": (
|
||||||
|
"shop",
|
||||||
"purchase_date",
|
"purchase_date",
|
||||||
"price",
|
"price",
|
||||||
)
|
)
|
||||||
@@ -133,6 +134,7 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"Publication Year",
|
"Publication Year",
|
||||||
"Description",
|
"Description",
|
||||||
"Tags",
|
"Tags",
|
||||||
|
"Shop",
|
||||||
"Purchase Date",
|
"Purchase Date",
|
||||||
"Price ({})".format(get_site_conf().currency),
|
"Price ({})".format(get_site_conf().currency),
|
||||||
"Notes",
|
"Notes",
|
||||||
@@ -158,6 +160,7 @@ class BookAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
settings.CSV_SEPARATOR_ALT.join(
|
settings.CSV_SEPARATOR_ALT.join(
|
||||||
t.name for t in obj.tags.all()
|
t.name for t in obj.tags.all()
|
||||||
),
|
),
|
||||||
|
obj.shop,
|
||||||
obj.purchase_date,
|
obj.purchase_date,
|
||||||
obj.price,
|
obj.price,
|
||||||
html.unescape(strip_tags(obj.notes)),
|
html.unescape(strip_tags(obj.notes)),
|
||||||
@@ -274,6 +277,7 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"Description",
|
"Description",
|
||||||
"Tags",
|
"Tags",
|
||||||
"Purchase Date",
|
"Purchase Date",
|
||||||
|
"Shop",
|
||||||
"Price ({})".format(get_site_conf().currency),
|
"Price ({})".format(get_site_conf().currency),
|
||||||
"Notes",
|
"Notes",
|
||||||
"Properties",
|
"Properties",
|
||||||
@@ -299,6 +303,7 @@ class CatalogAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
settings.CSV_SEPARATOR_ALT.join(
|
settings.CSV_SEPARATOR_ALT.join(
|
||||||
t.name for t in obj.tags.all()
|
t.name for t in obj.tags.all()
|
||||||
),
|
),
|
||||||
|
obj.shop,
|
||||||
obj.purchase_date,
|
obj.purchase_date,
|
||||||
obj.price,
|
obj.price,
|
||||||
html.unescape(strip_tags(obj.notes)),
|
html.unescape(strip_tags(obj.notes)),
|
||||||
|
46
ram/bookshelf/migrations/0022_basebook_shop.py
Normal file
46
ram/bookshelf/migrations/0022_basebook_shop.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-01-26 14:32
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def shop_from_property(apps, schema_editor):
|
||||||
|
basebook = apps.get_model("bookshelf", "BaseBook")
|
||||||
|
shop_model = apps.get_model("metadata", "Shop")
|
||||||
|
for row in basebook.objects.all():
|
||||||
|
property = row.property.filter(
|
||||||
|
property__name__icontains="shop"
|
||||||
|
).first()
|
||||||
|
if property:
|
||||||
|
shop, created = shop_model.objects.get_or_create(
|
||||||
|
name=property.value,
|
||||||
|
defaults={"on_line": False}
|
||||||
|
)
|
||||||
|
|
||||||
|
row.shop = shop
|
||||||
|
row.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("bookshelf", "0021_basebookdocument_creation_time_and_more"),
|
||||||
|
("metadata", "0023_shop"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="basebook",
|
||||||
|
name="shop",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="metadata.shop",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
shop_from_property,
|
||||||
|
reverse_code=migrations.RunPython.noop
|
||||||
|
),
|
||||||
|
]
|
@@ -7,10 +7,9 @@ from django_countries.fields import CountryField
|
|||||||
|
|
||||||
from tinymce import models as tinymce
|
from tinymce import models as tinymce
|
||||||
|
|
||||||
from metadata.models import Tag
|
|
||||||
from ram.utils import DeduplicatedStorage
|
from ram.utils import DeduplicatedStorage
|
||||||
from ram.models import BaseModel, Image, Document, PropertyInstance
|
from ram.models import BaseModel, Image, Document, PropertyInstance
|
||||||
from metadata.models import Scale, Manufacturer
|
from metadata.models import Scale, Manufacturer, Shop, Tag
|
||||||
|
|
||||||
|
|
||||||
class Publisher(models.Model):
|
class Publisher(models.Model):
|
||||||
@@ -50,6 +49,9 @@ class BaseBook(BaseModel):
|
|||||||
number_of_pages = models.SmallIntegerField(null=True, blank=True)
|
number_of_pages = models.SmallIntegerField(null=True, blank=True)
|
||||||
publication_year = models.SmallIntegerField(null=True, blank=True)
|
publication_year = models.SmallIntegerField(null=True, blank=True)
|
||||||
description = tinymce.HTMLField(blank=True)
|
description = tinymce.HTMLField(blank=True)
|
||||||
|
shop = models.ForeignKey(
|
||||||
|
Shop, on_delete=models.CASCADE, null=True, blank=True
|
||||||
|
)
|
||||||
price = models.DecimalField(
|
price = models.DecimalField(
|
||||||
max_digits=10,
|
max_digits=10,
|
||||||
decimal_places=2,
|
decimal_places=2,
|
||||||
|
@@ -26,7 +26,7 @@ class BookSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = Book
|
model = Book
|
||||||
exclude = ("purchase_date", "price",)
|
exclude = ("shop", "purchase_date", "price",)
|
||||||
read_only_fields = ("creation_time", "updated_time")
|
read_only_fields = ("creation_time", "updated_time")
|
||||||
|
|
||||||
|
|
||||||
|
@@ -8,6 +8,7 @@ from metadata.models import (
|
|||||||
Decoder,
|
Decoder,
|
||||||
DecoderDocument,
|
DecoderDocument,
|
||||||
Scale,
|
Scale,
|
||||||
|
Shop,
|
||||||
Manufacturer,
|
Manufacturer,
|
||||||
Company,
|
Company,
|
||||||
Tag,
|
Tag,
|
||||||
@@ -130,3 +131,10 @@ class GenericDocumentAdmin(admin.ModelAdmin):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
actions = [publish, unpublish]
|
actions = [publish, unpublish]
|
||||||
|
|
||||||
|
|
||||||
|
@admin.register(Shop)
|
||||||
|
class ShopAdmin(admin.ModelAdmin):
|
||||||
|
list_display = ("name", "on_line", "active")
|
||||||
|
list_filter = ("on_line", "active")
|
||||||
|
search_fields = ("name",)
|
||||||
|
40
ram/metadata/migrations/0023_shop.py
Normal file
40
ram/metadata/migrations/0023_shop.py
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-01-26 14:27
|
||||||
|
|
||||||
|
import django_countries.fields
|
||||||
|
import django.db.models.functions.text
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("metadata", "0022_decoderdocument_creation_time_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name="Shop",
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
"id",
|
||||||
|
models.BigAutoField(
|
||||||
|
auto_created=True,
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name="ID",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
("name", models.CharField(max_length=128, unique=True)),
|
||||||
|
(
|
||||||
|
"country",
|
||||||
|
django_countries.fields.CountryField(blank=True, max_length=2),
|
||||||
|
),
|
||||||
|
("website", models.URLField(blank=True)),
|
||||||
|
("on_line", models.BooleanField(default=True)),
|
||||||
|
("active", models.BooleanField(default=True)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
"ordering": [django.db.models.functions.text.Lower("name")],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
@@ -247,6 +247,20 @@ class GenericDocument(Document):
|
|||||||
verbose_name_plural = "Generic Documents"
|
verbose_name_plural = "Generic Documents"
|
||||||
|
|
||||||
|
|
||||||
|
class Shop(models.Model):
|
||||||
|
name = models.CharField(max_length=128, unique=True)
|
||||||
|
country = CountryField(blank=True)
|
||||||
|
website = models.URLField(blank=True)
|
||||||
|
on_line = models.BooleanField(default=True)
|
||||||
|
active = models.BooleanField(default=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = [models.functions.Lower("name"),]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
|
||||||
@receiver(models.signals.pre_save, sender=Manufacturer)
|
@receiver(models.signals.pre_save, sender=Manufacturer)
|
||||||
@receiver(models.signals.pre_save, sender=Company)
|
@receiver(models.signals.pre_save, sender=Company)
|
||||||
@receiver(models.signals.pre_save, sender=Scale)
|
@receiver(models.signals.pre_save, sender=Scale)
|
||||||
|
@@ -128,6 +128,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Shop</th>
|
||||||
|
<td>
|
||||||
|
{{ book.shop|default:"-" }}
|
||||||
|
{% if book.shop.website %} <a href="{{ book.shop.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-33" scope="row">Purchase date</th>
|
<th class="w-33" scope="row">Purchase date</th>
|
||||||
<td>{{ book.purchase_date|default:"-" }}</td>
|
<td>{{ book.purchase_date|default:"-" }}</td>
|
||||||
|
@@ -214,6 +214,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="table-group-divider">
|
<tbody class="table-group-divider">
|
||||||
|
<tr>
|
||||||
|
<th class="w-33" scope="row">Shop</th>
|
||||||
|
<td>
|
||||||
|
{{ rolling_stock.shop|default:"-" }}
|
||||||
|
{% if rolling_stock.shop.website %} <a href="{{ rolling_stock.shop.website }}" target="_blank"><i class="bi bi-box-arrow-up-right"></i></a>{% endif %}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<th class="w-33" scope="row">Purchase date</th>
|
<th class="w-33" scope="row">Purchase date</th>
|
||||||
<td>{{ rolling_stock.purchase_date|default:"-" }}</td>
|
<td>{{ rolling_stock.purchase_date|default:"-" }}</td>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
from ram.utils import git_suffix
|
from ram.utils import git_suffix
|
||||||
|
|
||||||
__version__ = "0.16.4"
|
__version__ = "0.16.5"
|
||||||
__version__ += git_suffix(__file__)
|
__version__ += git_suffix(__file__)
|
||||||
|
@@ -151,7 +151,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
RollingStockDocInline,
|
RollingStockDocInline,
|
||||||
RollingStockJournalInline,
|
RollingStockJournalInline,
|
||||||
)
|
)
|
||||||
autocomplete_fields = ("rolling_class",)
|
autocomplete_fields = ("rolling_class", "shop")
|
||||||
readonly_fields = ("preview", "creation_time", "updated_time")
|
readonly_fields = ("preview", "creation_time", "updated_time")
|
||||||
list_display = (
|
list_display = (
|
||||||
"__str__",
|
"__str__",
|
||||||
@@ -220,6 +220,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"Purchase data",
|
"Purchase data",
|
||||||
{
|
{
|
||||||
"fields": (
|
"fields": (
|
||||||
|
"shop",
|
||||||
"purchase_date",
|
"purchase_date",
|
||||||
"price",
|
"price",
|
||||||
)
|
)
|
||||||
@@ -266,6 +267,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
"Decoder Interface",
|
"Decoder Interface",
|
||||||
"Decoder",
|
"Decoder",
|
||||||
"Address",
|
"Address",
|
||||||
|
"Shop",
|
||||||
"Purchase Date",
|
"Purchase Date",
|
||||||
"Price ({})".format(get_site_conf().currency),
|
"Price ({})".format(get_site_conf().currency),
|
||||||
"Properties",
|
"Properties",
|
||||||
@@ -297,6 +299,7 @@ class RollingStockAdmin(SortableAdminBase, admin.ModelAdmin):
|
|||||||
obj.decoder,
|
obj.decoder,
|
||||||
obj.address,
|
obj.address,
|
||||||
obj.purchase_date,
|
obj.purchase_date,
|
||||||
|
obj.shop,
|
||||||
obj.price,
|
obj.price,
|
||||||
properties,
|
properties,
|
||||||
]
|
]
|
||||||
|
46
ram/roster/migrations/0034_rollingstock_shop.py
Normal file
46
ram/roster/migrations/0034_rollingstock_shop.py
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Generated by Django 5.1.4 on 2025-01-26 14:32
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
def shop_from_property(apps, schema_editor):
|
||||||
|
rolling_stock = apps.get_model("roster", "RollingStock")
|
||||||
|
shop_model = apps.get_model("metadata", "Shop")
|
||||||
|
for row in rolling_stock.objects.all():
|
||||||
|
property = row.property.filter(
|
||||||
|
property__name__icontains="shop"
|
||||||
|
).first()
|
||||||
|
if property:
|
||||||
|
shop, created = shop_model.objects.get_or_create(
|
||||||
|
name=property.value,
|
||||||
|
defaults={"on_line": False}
|
||||||
|
)
|
||||||
|
|
||||||
|
row.shop = shop
|
||||||
|
row.save()
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
("metadata", "0023_shop"),
|
||||||
|
("roster", "0033_rename_manufacturer_rollingclass_manufacturer_old"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="rollingstock",
|
||||||
|
name="shop",
|
||||||
|
field=models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
to="metadata.shop",
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.RunPython(
|
||||||
|
shop_from_property,
|
||||||
|
reverse_code=migrations.RunPython.noop
|
||||||
|
),
|
||||||
|
]
|
@@ -14,6 +14,7 @@ from ram.managers import PublicManager
|
|||||||
from metadata.models import (
|
from metadata.models import (
|
||||||
Scale,
|
Scale,
|
||||||
Manufacturer,
|
Manufacturer,
|
||||||
|
Shop,
|
||||||
Decoder,
|
Decoder,
|
||||||
Company,
|
Company,
|
||||||
Tag,
|
Tag,
|
||||||
@@ -102,6 +103,9 @@ class RollingStock(BaseModel):
|
|||||||
help_text="Era or epoch of the model",
|
help_text="Era or epoch of the model",
|
||||||
)
|
)
|
||||||
production_year = models.SmallIntegerField(null=True, blank=True)
|
production_year = models.SmallIntegerField(null=True, blank=True)
|
||||||
|
shop = models.ForeignKey(
|
||||||
|
Shop, on_delete=models.CASCADE, null=True, blank=True
|
||||||
|
)
|
||||||
purchase_date = models.DateField(null=True, blank=True)
|
purchase_date = models.DateField(null=True, blank=True)
|
||||||
price = models.DecimalField(
|
price = models.DecimalField(
|
||||||
max_digits=10,
|
max_digits=10,
|
||||||
|
@@ -29,5 +29,5 @@ class RollingStockSerializer(serializers.ModelSerializer):
|
|||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = RollingStock
|
model = RollingStock
|
||||||
exclude = ("purchase_date", "price",)
|
exclude = ("shop", "purchase_date", "price",)
|
||||||
read_only_fields = ("creation_time", "updated_time")
|
read_only_fields = ("creation_time", "updated_time")
|
||||||
|
Reference in New Issue
Block a user