kopia lustrzana https://github.com/jedie/PyInventory
Move source code from /src/
rodzic
48e1cd2697
commit
bc825f44ed
|
@ -75,18 +75,15 @@ class BaseImageModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.Tabu
|
||||||
url=instance.image.url,
|
url=instance.image.url,
|
||||||
name=instance.name,
|
name=instance.name,
|
||||||
)
|
)
|
||||||
|
|
||||||
extra = 0
|
extra = 0
|
||||||
fields = (
|
fields = ('position', 'preview', 'image', 'name', 'tags')
|
||||||
'position', 'preview', 'image', 'name', 'tags'
|
|
||||||
)
|
|
||||||
readonly_fields = ('preview',)
|
readonly_fields = ('preview',)
|
||||||
|
|
||||||
|
|
||||||
class BaseFileModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.TabularInline):
|
class BaseFileModelInline(UserInlineMixin, SortableInlineAdminMixin, admin.TabularInline):
|
||||||
extra = 0
|
extra = 0
|
||||||
fields = (
|
fields = ('position', 'file', 'name', 'tags')
|
||||||
'position', 'file', 'name', 'tags'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class LimitTreeDepthListFilter(admin.SimpleListFilter):
|
class LimitTreeDepthListFilter(admin.SimpleListFilter):
|
|
@ -13,7 +13,6 @@ from inventory.string_utils import ltruncatechars
|
||||||
|
|
||||||
|
|
||||||
class LocationModelResource(ModelResource):
|
class LocationModelResource(ModelResource):
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
model = LocationModel
|
model = LocationModel
|
||||||
|
|
|
@ -41,32 +41,33 @@ class MemoModelAdmin(TagulousModelAdminFix, ImportExportMixin, SortableAdminMixi
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
date_hierarchy = 'create_dt'
|
date_hierarchy = 'create_dt'
|
||||||
list_display = (
|
list_display = ('name', 'update_dt')
|
||||||
'name', 'update_dt'
|
|
||||||
)
|
|
||||||
ordering = ('-update_dt',)
|
ordering = ('-update_dt',)
|
||||||
list_display_links = ('name',)
|
list_display_links = ('name',)
|
||||||
list_filter = ('tags',)
|
list_filter = ('tags',)
|
||||||
search_fields = ('name', 'memo', 'tags__name')
|
search_fields = ('name', 'memo', 'tags__name')
|
||||||
fieldsets = (
|
fieldsets = (
|
||||||
(_('Internals'), {
|
(
|
||||||
'classes': ('collapse',),
|
_('Internals'),
|
||||||
'fields': (
|
{
|
||||||
('id', 'version'),
|
'classes': ('collapse',),
|
||||||
'user',
|
'fields': (
|
||||||
)
|
('id', 'version'),
|
||||||
}),
|
'user',
|
||||||
(_('Meta'), {
|
),
|
||||||
'classes': ('collapse',),
|
},
|
||||||
'fields': (
|
),
|
||||||
'create_dt', 'update_dt'
|
(_('Meta'), {'classes': ('collapse',), 'fields': ('create_dt', 'update_dt')}),
|
||||||
)
|
(
|
||||||
}),
|
_('Basic'),
|
||||||
(_('Basic'), {'fields': (
|
{
|
||||||
'name',
|
'fields': (
|
||||||
'memo',
|
'name',
|
||||||
'tags',
|
'memo',
|
||||||
)}),
|
'tags',
|
||||||
|
)
|
||||||
|
},
|
||||||
|
),
|
||||||
)
|
)
|
||||||
readonly_fields = ('id', 'create_dt', 'update_dt', 'user')
|
readonly_fields = ('id', 'create_dt', 'update_dt', 'user')
|
||||||
inlines = (MemoImageModelInline, MemoFileModelInline, MemoLinkModelInline)
|
inlines = (MemoImageModelInline, MemoFileModelInline, MemoLinkModelInline)
|
|
@ -34,14 +34,10 @@ def iter_location_chain(user, location_count):
|
||||||
room = LocationModel.objects.create(user=user, name=f'Room {next(room_no)}')
|
room = LocationModel.objects.create(user=user, name=f'Room {next(room_no)}')
|
||||||
room.full_clean()
|
room.full_clean()
|
||||||
for _ in range(2):
|
for _ in range(2):
|
||||||
cupboard = LocationModel.objects.create(
|
cupboard = LocationModel.objects.create(user=user, name=f'Cupboard {next(cupboard_no)}', parent=room)
|
||||||
user=user, name=f'Cupboard {next(cupboard_no)}', parent=room
|
|
||||||
)
|
|
||||||
cupboard.full_clean()
|
cupboard.full_clean()
|
||||||
for _ in range(2):
|
for _ in range(2):
|
||||||
drawer = LocationModel.objects.create(
|
drawer = LocationModel.objects.create(user=user, name=f'Drawer {next(drawer_no)}', parent=cupboard)
|
||||||
user=user, name=f'Drawer {next(drawer_no)}', parent=cupboard
|
|
||||||
)
|
|
||||||
drawer.full_clean()
|
drawer.full_clean()
|
||||||
yield drawer
|
yield drawer
|
||||||
location_no += 1
|
location_no += 1
|
||||||
|
@ -97,15 +93,9 @@ class Command(BaseCommand):
|
||||||
help = 'Fill database with example data'
|
help = 'Fill database with example data'
|
||||||
|
|
||||||
def add_arguments(self, parser):
|
def add_arguments(self, parser):
|
||||||
parser.add_argument(
|
parser.add_argument('--user-count', type=int, default=3, choices=range(1, 10), help='User count')
|
||||||
'--user-count', type=int, default=3, choices=range(1, 10), help='User count'
|
parser.add_argument('--location-count', type=int, default=3, choices=range(1, 20), help='Location count')
|
||||||
)
|
parser.add_argument('--item-count', type=int, default=4, choices=range(1, 40), help='Item count')
|
||||||
parser.add_argument(
|
|
||||||
'--location-count', type=int, default=3, choices=range(1, 20), help='Location count'
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
|
||||||
'--item-count', type=int, default=4, choices=range(1, 40), help='Item count'
|
|
||||||
)
|
|
||||||
|
|
||||||
def handle(self, **options):
|
def handle(self, **options):
|
||||||
self.stdout.write(self.help)
|
self.stdout.write(self.help)
|
|
@ -0,0 +1,596 @@
|
||||||
|
# Generated by Django 2.2.16 on 2020-10-17 17:26
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import ckeditor_uploader.fields
|
||||||
|
import django.db.models.deletion
|
||||||
|
import tagulous.models.fields
|
||||||
|
import tagulous.models.models
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_LocationModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemModel_producer',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemModel_kind',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemLinkModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_BaseModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_BaseLink_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='LocationModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
help_text='BaseModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
verbose_name='BaseModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'description',
|
||||||
|
ckeditor_uploader.fields.RichTextUploadingField(
|
||||||
|
help_text='LocationModel.description.help_text',
|
||||||
|
verbose_name='LocationModel.description.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'parent',
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
help_text='LocationModel.parent.help_text',
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to='inventory.LocationModel',
|
||||||
|
verbose_name='LocationModel.parent.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
to='inventory.Tagulous_LocationModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'LocationModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'LocationModel.verbose_name_plural',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ItemModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
help_text='BaseModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
verbose_name='BaseModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'description',
|
||||||
|
ckeditor_uploader.fields.RichTextUploadingField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.description.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.description.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'fcc_id',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.fcc_id.help_text',
|
||||||
|
max_length=20,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.fcc_id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'lent_to',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.lent_to.help_text',
|
||||||
|
max_length=64,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.lent_to.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'lent_from_date',
|
||||||
|
models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.lent_from_date.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.lent_from_date.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'lent_until_date',
|
||||||
|
models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.lent_until_date.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.lent_until_date.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'received_from',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.received_from.help_text',
|
||||||
|
max_length=64,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.received_from.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'received_date',
|
||||||
|
models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.received_date.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.received_date.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'received_price',
|
||||||
|
models.DecimalField(
|
||||||
|
blank=True,
|
||||||
|
decimal_places=2,
|
||||||
|
help_text='ItemModel.received_price.help_text',
|
||||||
|
max_digits=6,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.received_price.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'handed_over_to',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.handed_over_to.help_text',
|
||||||
|
max_length=64,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.handed_over_to.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'handed_over_date',
|
||||||
|
models.DateField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.handed_over_date.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.handed_over_date.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'handed_over_price',
|
||||||
|
models.DecimalField(
|
||||||
|
blank=True,
|
||||||
|
decimal_places=2,
|
||||||
|
help_text='ItemModel.handed_over_price.help_text',
|
||||||
|
max_digits=6,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemModel.handed_over_price.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'kind',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='ItemModel.kind.help_text',
|
||||||
|
max_count=3,
|
||||||
|
to='inventory.Tagulous_ItemModel_kind',
|
||||||
|
verbose_name='ItemModel.kind.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'location',
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.location.help_text',
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to='inventory.LocationModel',
|
||||||
|
verbose_name='ItemModel.location.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'parent',
|
||||||
|
models.ForeignKey(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemModel.parent.help_text',
|
||||||
|
limit_choices_to={'parent_id': None},
|
||||||
|
null=True,
|
||||||
|
on_delete=django.db.models.deletion.SET_NULL,
|
||||||
|
to='inventory.ItemModel',
|
||||||
|
verbose_name='ItemModel.parent.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'producer',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='ItemModel.producer.help_text',
|
||||||
|
max_count=1,
|
||||||
|
to='inventory.Tagulous_ItemModel_producer',
|
||||||
|
verbose_name='ItemModel.producer.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
to='inventory.Tagulous_ItemModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ItemModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'ItemModel.verbose_name_plural',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ItemLinkModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseLink.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseLink.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('url', models.URLField(help_text='Link.url.help_text', verbose_name='Link.url.verbose_name')),
|
||||||
|
(
|
||||||
|
'last_check',
|
||||||
|
models.DateField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.url.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.url.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'status_code',
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.status_code.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.status_code.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'page_title',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.page_title.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.page_title.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.ItemModel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
to='inventory.Tagulous_ItemLinkModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ItemLinkModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'ItemLinkModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -0,0 +1,87 @@
|
||||||
|
# Generated by Django 2.2.16 on 2020-10-17 20:11
|
||||||
|
|
||||||
|
import tagulous.models.fields
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
('inventory', '0001_initial'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='itemlinkmodel',
|
||||||
|
name='tags',
|
||||||
|
field=tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemLinkModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='itemmodel',
|
||||||
|
name='kind',
|
||||||
|
field=tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='ItemModel.kind.help_text',
|
||||||
|
max_count=3,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemModel_kind',
|
||||||
|
verbose_name='ItemModel.kind.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='itemmodel',
|
||||||
|
name='producer',
|
||||||
|
field=tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='ItemModel.producer.help_text',
|
||||||
|
max_count=1,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemModel_producer',
|
||||||
|
verbose_name='ItemModel.producer.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='itemmodel',
|
||||||
|
name='tags',
|
||||||
|
field=tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='locationmodel',
|
||||||
|
name='tags',
|
||||||
|
field=tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_LocationModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
|
@ -5,7 +5,6 @@ from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0002_auto_20201017_2211'),
|
('inventory', '0002_auto_20201017_2211'),
|
||||||
]
|
]
|
||||||
|
@ -14,6 +13,11 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='locationmodel',
|
model_name='locationmodel',
|
||||||
name='description',
|
name='description',
|
||||||
field=ckeditor_uploader.fields.RichTextUploadingField(blank=True, help_text='LocationModel.description.help_text', null=True, verbose_name='LocationModel.description.verbose_name'),
|
field=ckeditor_uploader.fields.RichTextUploadingField(
|
||||||
|
blank=True,
|
||||||
|
help_text='LocationModel.description.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='LocationModel.description.verbose_name',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
|
@ -0,0 +1,129 @@
|
||||||
|
# Generated by Django 2.2.17 on 2020-11-15 11:09
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import tagulous.models.fields
|
||||||
|
import tagulous.models.models
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
import inventory.models.item
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('inventory', '0003_auto_20201024_1830'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemImageModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ItemImageModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'image',
|
||||||
|
models.ImageField(
|
||||||
|
help_text='ItemImageModel.image.help_text',
|
||||||
|
upload_to=inventory.models.item.user_directory_path,
|
||||||
|
verbose_name='ItemImageModel.image.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='ItemImageModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='ItemImageModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.ItemModel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemImageModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ItemImageModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'ItemImageModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -51,7 +51,7 @@ def forward_code(apps, schema_editor):
|
||||||
file_path = Path(str(image.file))
|
file_path = Path(str(image.file))
|
||||||
log(f'Old path: {file_path}')
|
log(f'Old path: {file_path}')
|
||||||
|
|
||||||
media_path=generate_media_path(user, filename=file_path.name)
|
media_path = generate_media_path(user, filename=file_path.name)
|
||||||
|
|
||||||
new_file_path = Path(settings.MEDIA_ROOT, media_path)
|
new_file_path = Path(settings.MEDIA_ROOT, media_path)
|
||||||
log(f'New path: {new_file_path}')
|
log(f'New path: {new_file_path}')
|
||||||
|
@ -67,7 +67,6 @@ def forward_code(apps, schema_editor):
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0004_item_user_images'),
|
('inventory', '0004_item_user_images'),
|
||||||
('serve_media_app', '0001_initial'),
|
('serve_media_app', '0001_initial'),
|
|
@ -1,11 +1,10 @@
|
||||||
# Generated by Django 2.2.20 on 2021-04-28 15:44
|
# Generated by Django 2.2.20 on 2021-04-28 15:44
|
||||||
|
|
||||||
from django.db import migrations, models
|
|
||||||
import tagulous.models.models
|
import tagulous.models.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0005_serve_uploads_by_django_tools'),
|
('inventory', '0005_serve_uploads_by_django_tools'),
|
||||||
]
|
]
|
||||||
|
@ -14,7 +13,13 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='itemimagemodel',
|
model_name='itemimagemodel',
|
||||||
name='name',
|
name='name',
|
||||||
field=models.CharField(blank=True, help_text='BaseItemAttachmentModel.name.help_text', max_length=255, null=True, verbose_name='BaseItemAttachmentModel.name.verbose_name'),
|
field=models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseItemAttachmentModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseItemAttachmentModel.name.verbose_name',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
migrations.CreateModel(
|
migrations.CreateModel(
|
||||||
name='Tagulous_BaseItemAttachmentModel_tags',
|
name='Tagulous_BaseItemAttachmentModel_tags',
|
||||||
|
@ -22,8 +27,14 @@ class Migration(migrations.Migration):
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
('slug', models.SlugField()),
|
('slug', models.SlugField()),
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
(
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
||||||
'ordering': ('name',),
|
'ordering': ('name',),
|
|
@ -0,0 +1,128 @@
|
||||||
|
# Generated by Django 2.2.20 on 2021-04-28 15:54
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django_tools.serve_media_app.models
|
||||||
|
import tagulous.models.fields
|
||||||
|
import tagulous.models.models
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('inventory', '0006_refactor_image_model'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_ItemFileModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='ItemFileModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseItemAttachmentModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseItemAttachmentModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
(
|
||||||
|
'file',
|
||||||
|
models.FileField(
|
||||||
|
help_text='ItemFileModel.file.help_text',
|
||||||
|
upload_to=django_tools.serve_media_app.models.user_directory_path,
|
||||||
|
verbose_name='ItemFileModel.file.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.ItemModel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_ItemFileModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'ItemFileModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'ItemFileModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -4,7 +4,6 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0007_add_file_attachment'),
|
('inventory', '0007_add_file_attachment'),
|
||||||
]
|
]
|
||||||
|
@ -13,6 +12,12 @@ class Migration(migrations.Migration):
|
||||||
migrations.AlterField(
|
migrations.AlterField(
|
||||||
model_name='itemlinkmodel',
|
model_name='itemlinkmodel',
|
||||||
name='last_check',
|
name='last_check',
|
||||||
field=models.DateTimeField(blank=True, editable=False, help_text='Link.url.help_text', null=True, verbose_name='Link.url.verbose_name'),
|
field=models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.url.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.url.verbose_name',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
|
@ -0,0 +1,517 @@
|
||||||
|
# Generated by Django 3.1.13 on 2021-10-09 17:38
|
||||||
|
|
||||||
|
import uuid
|
||||||
|
|
||||||
|
import ckeditor_uploader.fields
|
||||||
|
import django.db.models.deletion
|
||||||
|
import django_tools.serve_media_app.models
|
||||||
|
import tagulous.models.fields
|
||||||
|
import tagulous.models.models
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
('inventory', '0008_last_check_datetime'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_MemoModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_MemoLinkModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_MemoImageModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_MemoFileModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_BaseMemoAttachmentModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Tagulous_BaseAttachmentModel_tags',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
|
('slug', models.SlugField()),
|
||||||
|
(
|
||||||
|
'count',
|
||||||
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'protected',
|
||||||
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ('name',),
|
||||||
|
'abstract': False,
|
||||||
|
'unique_together': {('slug',)},
|
||||||
|
},
|
||||||
|
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MemoModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
help_text='BaseModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
verbose_name='BaseModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'memo',
|
||||||
|
ckeditor_uploader.fields.RichTextUploadingField(
|
||||||
|
blank=True,
|
||||||
|
help_text='MemoModel.description.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='MemoModel.description.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_MemoModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'MemoModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'MemoModel.verbose_name_plural',
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MemoLinkModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseLink.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseLink.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('url', models.URLField(help_text='Link.url.help_text', verbose_name='Link.url.verbose_name')),
|
||||||
|
(
|
||||||
|
'last_check',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.url.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.url.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'status_code',
|
||||||
|
models.PositiveSmallIntegerField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.status_code.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.status_code.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'page_title',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='Link.page_title.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='Link.page_title.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
('memo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.memomodel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_MemoLinkModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'MemoLinkModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'MemoLinkModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MemoImageModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseItemAttachmentModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseItemAttachmentModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
(
|
||||||
|
'image',
|
||||||
|
models.ImageField(
|
||||||
|
help_text='MemoImageModel.image.help_text',
|
||||||
|
upload_to=django_tools.serve_media_app.models.user_directory_path,
|
||||||
|
verbose_name='MemoImageModel.image.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('memo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.memomodel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_MemoImageModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'MemoImageModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'MemoImageModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='MemoFileModel',
|
||||||
|
fields=[
|
||||||
|
(
|
||||||
|
'create_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.create_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.create_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'update_dt',
|
||||||
|
models.DateTimeField(
|
||||||
|
blank=True,
|
||||||
|
editable=False,
|
||||||
|
help_text='ModelTimetrackingMixin.update_dt.help_text',
|
||||||
|
null=True,
|
||||||
|
verbose_name='ModelTimetrackingMixin.update_dt.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'id',
|
||||||
|
models.UUIDField(
|
||||||
|
default=uuid.uuid4,
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.id.help_text',
|
||||||
|
primary_key=True,
|
||||||
|
serialize=False,
|
||||||
|
verbose_name='BaseModel.id.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'name',
|
||||||
|
models.CharField(
|
||||||
|
blank=True,
|
||||||
|
help_text='BaseItemAttachmentModel.name.help_text',
|
||||||
|
max_length=255,
|
||||||
|
null=True,
|
||||||
|
verbose_name='BaseItemAttachmentModel.name.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('position', models.PositiveSmallIntegerField(default=0)),
|
||||||
|
(
|
||||||
|
'file',
|
||||||
|
models.FileField(
|
||||||
|
help_text='MemoFileModel.file.help_text',
|
||||||
|
upload_to=django_tools.serve_media_app.models.user_directory_path,
|
||||||
|
verbose_name='MemoFileModel.file.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
('memo', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.memomodel')),
|
||||||
|
(
|
||||||
|
'tags',
|
||||||
|
tagulous.models.fields.TagField(
|
||||||
|
_set_tag_meta=True,
|
||||||
|
blank=True,
|
||||||
|
case_sensitive=False,
|
||||||
|
force_lowercase=False,
|
||||||
|
help_text='BaseModel.tags.help_text',
|
||||||
|
max_count=10,
|
||||||
|
space_delimiter=False,
|
||||||
|
to='inventory.Tagulous_MemoFileModel_tags',
|
||||||
|
verbose_name='BaseModel.tags.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
(
|
||||||
|
'user',
|
||||||
|
models.ForeignKey(
|
||||||
|
editable=False,
|
||||||
|
help_text='BaseModel.user.help_text',
|
||||||
|
on_delete=django.db.models.deletion.CASCADE,
|
||||||
|
related_name='+',
|
||||||
|
to=settings.AUTH_USER_MODEL,
|
||||||
|
verbose_name='BaseModel.user.verbose_name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'verbose_name': 'MemoFileModel.verbose_name',
|
||||||
|
'verbose_name_plural': 'MemoFileModel.verbose_name_plural',
|
||||||
|
'ordering': ('position',),
|
||||||
|
},
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,11 +1,10 @@
|
||||||
# Generated by Django 3.1.13 on 2021-11-22 17:47
|
# Generated by Django 3.1.13 on 2021-11-22 17:47
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
import django_tools.model_version_protect.models
|
import django_tools.model_version_protect.models
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0009_add_memo'),
|
('inventory', '0009_add_memo'),
|
||||||
]
|
]
|
||||||
|
@ -14,16 +13,25 @@ class Migration(migrations.Migration):
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='itemmodel',
|
model_name='itemmodel',
|
||||||
name='version',
|
name='version',
|
||||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
field=django_tools.model_version_protect.models.VersionModelField(
|
||||||
|
default=0,
|
||||||
|
help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='locationmodel',
|
model_name='locationmodel',
|
||||||
name='version',
|
name='version',
|
||||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
field=django_tools.model_version_protect.models.VersionModelField(
|
||||||
|
default=0,
|
||||||
|
help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
migrations.AddField(
|
migrations.AddField(
|
||||||
model_name='memomodel',
|
model_name='memomodel',
|
||||||
name='version',
|
name='version',
|
||||||
field=django_tools.model_version_protect.models.VersionModelField(default=0, help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.'),
|
field=django_tools.model_version_protect.models.VersionModelField(
|
||||||
|
default=0,
|
||||||
|
help_text='Internal version number of this entry. Used to protect the overwriting of an older entry.',
|
||||||
|
),
|
||||||
),
|
),
|
||||||
]
|
]
|
|
@ -6,7 +6,6 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0010_version_protect_models'),
|
('inventory', '0010_version_protect_models'),
|
||||||
]
|
]
|
||||||
|
@ -59,23 +58,17 @@ class Migration(migrations.Migration):
|
||||||
fields=[
|
fields=[
|
||||||
(
|
(
|
||||||
'id',
|
'id',
|
||||||
models.AutoField(
|
models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID'),
|
||||||
auto_created=True, primary_key=True, serialize=False, verbose_name='ID'
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
('name', models.CharField(max_length=255, unique=True)),
|
||||||
('slug', models.SlugField()),
|
('slug', models.SlugField()),
|
||||||
(
|
(
|
||||||
'count',
|
'count',
|
||||||
models.IntegerField(
|
models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use'),
|
||||||
default=0, help_text='Internal counter of how many times this tag is in use'
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
(
|
(
|
||||||
'protected',
|
'protected',
|
||||||
models.BooleanField(
|
models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0'),
|
||||||
default=False, help_text='Will not be deleted when the count reaches 0'
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
options={
|
options={
|
|
@ -11,7 +11,6 @@ def forward_code(apps, schema_editor):
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0011_parent_tree1'),
|
('inventory', '0011_parent_tree1'),
|
||||||
]
|
]
|
|
@ -5,7 +5,6 @@ from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
dependencies = [
|
dependencies = [
|
||||||
('inventory', '0012_parent_tree2'),
|
('inventory', '0012_parent_tree2'),
|
||||||
]
|
]
|
|
@ -24,7 +24,7 @@ class BaseModel(TimetrackingBaseModel):
|
||||||
default=uuid.uuid4,
|
default=uuid.uuid4,
|
||||||
editable=False,
|
editable=False,
|
||||||
verbose_name=_('BaseModel.id.verbose_name'),
|
verbose_name=_('BaseModel.id.verbose_name'),
|
||||||
help_text=_('BaseModel.id.help_text')
|
help_text=_('BaseModel.id.help_text'),
|
||||||
)
|
)
|
||||||
user = models.ForeignKey( # "Owner" of this entry
|
user = models.ForeignKey( # "Owner" of this entry
|
||||||
settings.AUTH_USER_MODEL,
|
settings.AUTH_USER_MODEL,
|
||||||
|
@ -32,12 +32,10 @@ class BaseModel(TimetrackingBaseModel):
|
||||||
on_delete=models.CASCADE,
|
on_delete=models.CASCADE,
|
||||||
editable=False, # Must be set automatically and never changed
|
editable=False, # Must be set automatically and never changed
|
||||||
verbose_name=_('BaseModel.user.verbose_name'),
|
verbose_name=_('BaseModel.user.verbose_name'),
|
||||||
help_text=_('BaseModel.user.help_text')
|
help_text=_('BaseModel.user.help_text'),
|
||||||
)
|
)
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=255,
|
max_length=255, verbose_name=_('BaseModel.name.verbose_name'), help_text=_('BaseModel.name.help_text')
|
||||||
verbose_name=_('BaseModel.name.verbose_name'),
|
|
||||||
help_text=_('BaseModel.name.help_text')
|
|
||||||
)
|
)
|
||||||
tags = tagulous.models.TagField(
|
tags = tagulous.models.TagField(
|
||||||
blank=True,
|
blank=True,
|
||||||
|
@ -46,7 +44,7 @@ class BaseModel(TimetrackingBaseModel):
|
||||||
space_delimiter=False,
|
space_delimiter=False,
|
||||||
max_count=10,
|
max_count=10,
|
||||||
verbose_name=_('BaseModel.tags.verbose_name'),
|
verbose_name=_('BaseModel.tags.verbose_name'),
|
||||||
help_text=_('BaseModel.tags.help_text')
|
help_text=_('BaseModel.tags.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -183,16 +181,20 @@ class BaseAttachmentModel(BaseModel):
|
||||||
"""
|
"""
|
||||||
Base model to store files or images to Items
|
Base model to store files or images to Items
|
||||||
"""
|
"""
|
||||||
|
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
null=True, blank=True,
|
null=True,
|
||||||
|
blank=True,
|
||||||
max_length=255,
|
max_length=255,
|
||||||
verbose_name=_('BaseItemAttachmentModel.name.verbose_name'),
|
verbose_name=_('BaseItemAttachmentModel.name.verbose_name'),
|
||||||
help_text=_('BaseItemAttachmentModel.name.help_text')
|
help_text=_('BaseItemAttachmentModel.name.help_text'),
|
||||||
)
|
)
|
||||||
position = models.PositiveSmallIntegerField(
|
position = models.PositiveSmallIntegerField(
|
||||||
# Note: Will be set in admin via adminsortable2
|
# Note: Will be set in admin via adminsortable2
|
||||||
# The JavaScript which performs the sorting is 1-indexed !
|
# The JavaScript which performs the sorting is 1-indexed !
|
||||||
default=0, blank=False, null=False
|
default=0,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -213,6 +215,7 @@ class BaseItemAttachmentModel(BaseAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Base model to store files or images to Items
|
Base model to store files or images to Items
|
||||||
"""
|
"""
|
||||||
|
|
||||||
item = models.ForeignKey('ItemModel', on_delete=models.CASCADE)
|
item = models.ForeignKey('ItemModel', on_delete=models.CASCADE)
|
||||||
|
|
||||||
def full_clean(self, **kwargs):
|
def full_clean(self, **kwargs):
|
||||||
|
@ -226,6 +229,7 @@ class BaseMemoAttachmentModel(BaseAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Base model to store files or images to Memos
|
Base model to store files or images to Memos
|
||||||
"""
|
"""
|
||||||
|
|
||||||
memo = models.ForeignKey('MemoModel', on_delete=models.CASCADE)
|
memo = models.ForeignKey('MemoModel', on_delete=models.CASCADE)
|
||||||
|
|
||||||
def full_clean(self, **kwargs):
|
def full_clean(self, **kwargs):
|
|
@ -26,6 +26,7 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
"""
|
"""
|
||||||
A Item that can be described and store somewhere ;)
|
A Item that can be described and store somewhere ;)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
objects = ItemQuerySet.as_manager()
|
objects = ItemQuerySet.as_manager()
|
||||||
|
|
||||||
kind = tagulous.models.TagField(
|
kind = tagulous.models.TagField(
|
||||||
|
@ -34,7 +35,7 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
space_delimiter=False,
|
space_delimiter=False,
|
||||||
max_count=3,
|
max_count=3,
|
||||||
verbose_name=_('ItemModel.kind.verbose_name'),
|
verbose_name=_('ItemModel.kind.verbose_name'),
|
||||||
help_text=_('ItemModel.kind.help_text')
|
help_text=_('ItemModel.kind.help_text'),
|
||||||
)
|
)
|
||||||
producer = tagulous.models.TagField(
|
producer = tagulous.models.TagField(
|
||||||
blank=True,
|
blank=True,
|
||||||
|
@ -43,26 +44,30 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
space_delimiter=False,
|
space_delimiter=False,
|
||||||
max_count=1,
|
max_count=1,
|
||||||
verbose_name=_('ItemModel.producer.verbose_name'),
|
verbose_name=_('ItemModel.producer.verbose_name'),
|
||||||
help_text=_('ItemModel.producer.help_text')
|
help_text=_('ItemModel.producer.help_text'),
|
||||||
)
|
)
|
||||||
description = RichTextUploadingField(
|
description = RichTextUploadingField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
config_name='ItemModel.description',
|
config_name='ItemModel.description',
|
||||||
verbose_name=_('ItemModel.description.verbose_name'),
|
verbose_name=_('ItemModel.description.verbose_name'),
|
||||||
help_text=_('ItemModel.description.help_text')
|
help_text=_('ItemModel.description.help_text'),
|
||||||
)
|
)
|
||||||
fcc_id = models.CharField(
|
fcc_id = models.CharField(
|
||||||
max_length=20,
|
max_length=20,
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.fcc_id.verbose_name'),
|
verbose_name=_('ItemModel.fcc_id.verbose_name'),
|
||||||
help_text=_('ItemModel.fcc_id.help_text')
|
help_text=_('ItemModel.fcc_id.help_text'),
|
||||||
)
|
)
|
||||||
location = models.ForeignKey(
|
location = models.ForeignKey(
|
||||||
'inventory.LocationModel',
|
'inventory.LocationModel',
|
||||||
blank=True, null=True, on_delete=models.SET_NULL,
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
on_delete=models.SET_NULL,
|
||||||
related_name='items',
|
related_name='items',
|
||||||
verbose_name=_('ItemModel.location.verbose_name'),
|
verbose_name=_('ItemModel.location.verbose_name'),
|
||||||
help_text=_('ItemModel.location.help_text')
|
help_text=_('ItemModel.location.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
# ________________________________________________________________________
|
# ________________________________________________________________________
|
||||||
|
@ -70,19 +75,22 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
|
|
||||||
lent_to = models.CharField(
|
lent_to = models.CharField(
|
||||||
max_length=64,
|
max_length=64,
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.lent_to.verbose_name'),
|
verbose_name=_('ItemModel.lent_to.verbose_name'),
|
||||||
help_text=_('ItemModel.lent_to.help_text')
|
help_text=_('ItemModel.lent_to.help_text'),
|
||||||
)
|
)
|
||||||
lent_from_date = models.DateField(
|
lent_from_date = models.DateField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.lent_from_date.verbose_name'),
|
verbose_name=_('ItemModel.lent_from_date.verbose_name'),
|
||||||
help_text=_('ItemModel.lent_from_date.help_text')
|
help_text=_('ItemModel.lent_from_date.help_text'),
|
||||||
)
|
)
|
||||||
lent_until_date = models.DateField(
|
lent_until_date = models.DateField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.lent_until_date.verbose_name'),
|
verbose_name=_('ItemModel.lent_until_date.verbose_name'),
|
||||||
help_text=_('ItemModel.lent_until_date.help_text')
|
help_text=_('ItemModel.lent_until_date.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
# ________________________________________________________________________
|
# ________________________________________________________________________
|
||||||
|
@ -90,20 +98,24 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
|
|
||||||
received_from = models.CharField(
|
received_from = models.CharField(
|
||||||
max_length=64,
|
max_length=64,
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.received_from.verbose_name'),
|
verbose_name=_('ItemModel.received_from.verbose_name'),
|
||||||
help_text=_('ItemModel.received_from.help_text')
|
help_text=_('ItemModel.received_from.help_text'),
|
||||||
)
|
)
|
||||||
received_date = models.DateField(
|
received_date = models.DateField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.received_date.verbose_name'),
|
verbose_name=_('ItemModel.received_date.verbose_name'),
|
||||||
help_text=_('ItemModel.received_date.help_text')
|
help_text=_('ItemModel.received_date.help_text'),
|
||||||
)
|
)
|
||||||
received_price = models.DecimalField(
|
received_price = models.DecimalField(
|
||||||
decimal_places=2, max_digits=6, # up to 9999 with a resolution of 2 decimal places
|
decimal_places=2,
|
||||||
blank=True, null=True,
|
max_digits=6, # up to 9999 with a resolution of 2 decimal places
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.received_price.verbose_name'),
|
verbose_name=_('ItemModel.received_price.verbose_name'),
|
||||||
help_text=_('ItemModel.received_price.help_text')
|
help_text=_('ItemModel.received_price.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
# ________________________________________________________________________
|
# ________________________________________________________________________
|
||||||
|
@ -111,20 +123,24 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
|
|
||||||
handed_over_to = models.CharField(
|
handed_over_to = models.CharField(
|
||||||
max_length=64,
|
max_length=64,
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.handed_over_to.verbose_name'),
|
verbose_name=_('ItemModel.handed_over_to.verbose_name'),
|
||||||
help_text=_('ItemModel.handed_over_to.help_text')
|
help_text=_('ItemModel.handed_over_to.help_text'),
|
||||||
)
|
)
|
||||||
handed_over_date = models.DateField(
|
handed_over_date = models.DateField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.handed_over_date.verbose_name'),
|
verbose_name=_('ItemModel.handed_over_date.verbose_name'),
|
||||||
help_text=_('ItemModel.handed_over_date.help_text')
|
help_text=_('ItemModel.handed_over_date.help_text'),
|
||||||
)
|
)
|
||||||
handed_over_price = models.DecimalField(
|
handed_over_price = models.DecimalField(
|
||||||
decimal_places=2, max_digits=6, # up to 9999 with a resolution of 2 decimal places
|
decimal_places=2,
|
||||||
blank=True, null=True,
|
max_digits=6, # up to 9999 with a resolution of 2 decimal places
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('ItemModel.handed_over_price.verbose_name'),
|
verbose_name=_('ItemModel.handed_over_price.verbose_name'),
|
||||||
help_text=_('ItemModel.handed_over_price.help_text')
|
help_text=_('ItemModel.handed_over_price.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def local_admin_link(self):
|
def local_admin_link(self):
|
||||||
|
@ -142,9 +158,7 @@ class ItemModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
|
|
||||||
|
|
||||||
class ItemLinkModel(BaseLink):
|
class ItemLinkModel(BaseLink):
|
||||||
item = models.ForeignKey(
|
item = models.ForeignKey(ItemModel, on_delete=models.CASCADE)
|
||||||
ItemModel, on_delete=models.CASCADE
|
|
||||||
)
|
|
||||||
|
|
||||||
def full_clean(self, **kwargs):
|
def full_clean(self, **kwargs):
|
||||||
if self.user_id is None:
|
if self.user_id is None:
|
||||||
|
@ -162,10 +176,11 @@ class ItemImageModel(BaseItemAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Store images to Items
|
Store images to Items
|
||||||
"""
|
"""
|
||||||
|
|
||||||
image = models.ImageField(
|
image = models.ImageField(
|
||||||
upload_to=user_directory_path,
|
upload_to=user_directory_path,
|
||||||
verbose_name=_('ItemImageModel.image.verbose_name'),
|
verbose_name=_('ItemImageModel.image.verbose_name'),
|
||||||
help_text=_('ItemImageModel.image.help_text')
|
help_text=_('ItemImageModel.image.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -189,10 +204,11 @@ class ItemFileModel(BaseItemAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Store files to Items
|
Store files to Items
|
||||||
"""
|
"""
|
||||||
|
|
||||||
file = models.FileField(
|
file = models.FileField(
|
||||||
upload_to=user_directory_path,
|
upload_to=user_directory_path,
|
||||||
verbose_name=_('ItemFileModel.file.verbose_name'),
|
verbose_name=_('ItemFileModel.file.verbose_name'),
|
||||||
help_text=_('ItemFileModel.file.help_text')
|
help_text=_('ItemFileModel.file.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
|
@ -16,34 +16,42 @@ logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
class BaseLink(BaseModel):
|
class BaseLink(BaseModel):
|
||||||
name = models.CharField(
|
name = models.CharField(
|
||||||
max_length=255, blank=True, null=True,
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
verbose_name=_('BaseLink.name.verbose_name'),
|
verbose_name=_('BaseLink.name.verbose_name'),
|
||||||
help_text=_('BaseLink.name.help_text')
|
help_text=_('BaseLink.name.help_text'),
|
||||||
)
|
|
||||||
url = models.URLField(
|
|
||||||
verbose_name=_('Link.url.verbose_name'),
|
|
||||||
help_text=_('Link.url.help_text')
|
|
||||||
)
|
)
|
||||||
|
url = models.URLField(verbose_name=_('Link.url.verbose_name'), help_text=_('Link.url.help_text'))
|
||||||
last_check = models.DateTimeField(
|
last_check = models.DateTimeField(
|
||||||
blank=True, null=True, editable=False,
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
verbose_name=_('Link.url.verbose_name'),
|
verbose_name=_('Link.url.verbose_name'),
|
||||||
help_text=_('Link.url.help_text')
|
help_text=_('Link.url.help_text'),
|
||||||
)
|
)
|
||||||
status_code = models.PositiveSmallIntegerField(
|
status_code = models.PositiveSmallIntegerField(
|
||||||
blank=True, null=True, editable=False,
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
verbose_name=_('Link.status_code.verbose_name'),
|
verbose_name=_('Link.status_code.verbose_name'),
|
||||||
help_text=_('Link.status_code.help_text')
|
help_text=_('Link.status_code.help_text'),
|
||||||
)
|
)
|
||||||
page_title = models.CharField(
|
page_title = models.CharField(
|
||||||
max_length=255, blank=True, null=True, editable=False,
|
max_length=255,
|
||||||
|
blank=True,
|
||||||
|
null=True,
|
||||||
|
editable=False,
|
||||||
verbose_name=_('Link.page_title.verbose_name'),
|
verbose_name=_('Link.page_title.verbose_name'),
|
||||||
help_text=_('Link.page_title.help_text')
|
help_text=_('Link.page_title.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
position = models.PositiveSmallIntegerField(
|
position = models.PositiveSmallIntegerField(
|
||||||
# Note: Will be set in admin via adminsortable2
|
# Note: Will be set in admin via adminsortable2
|
||||||
# The JavaScript which performs the sorting is 1-indexed !
|
# The JavaScript which performs the sorting is 1-indexed !
|
||||||
default=0, blank=False, null=False
|
default=0,
|
||||||
|
blank=False,
|
||||||
|
null=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
def update_response_info(self):
|
def update_response_info(self):
|
|
@ -9,11 +9,13 @@ class LocationModel(BaseParentTreeModel, VersionProtectBaseModel):
|
||||||
"""
|
"""
|
||||||
A Storage for items.
|
A Storage for items.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
description = RichTextUploadingField(
|
description = RichTextUploadingField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
config_name='LocationModel.description',
|
config_name='LocationModel.description',
|
||||||
verbose_name=_('LocationModel.description.verbose_name'),
|
verbose_name=_('LocationModel.description.verbose_name'),
|
||||||
help_text=_('LocationModel.description.help_text')
|
help_text=_('LocationModel.description.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
|
@ -20,11 +20,13 @@ class MemoModel(BaseModel, VersionProtectBaseModel):
|
||||||
"""
|
"""
|
||||||
A Memo to hold some information independ of items/location
|
A Memo to hold some information independ of items/location
|
||||||
"""
|
"""
|
||||||
|
|
||||||
memo = RichTextUploadingField(
|
memo = RichTextUploadingField(
|
||||||
blank=True, null=True,
|
blank=True,
|
||||||
|
null=True,
|
||||||
config_name='MemoModel.description',
|
config_name='MemoModel.description',
|
||||||
verbose_name=_('MemoModel.description.verbose_name'),
|
verbose_name=_('MemoModel.description.verbose_name'),
|
||||||
help_text=_('MemoModel.description.help_text')
|
help_text=_('MemoModel.description.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def local_admin_link(self):
|
def local_admin_link(self):
|
||||||
|
@ -37,9 +39,7 @@ class MemoModel(BaseModel, VersionProtectBaseModel):
|
||||||
|
|
||||||
|
|
||||||
class MemoLinkModel(BaseLink):
|
class MemoLinkModel(BaseLink):
|
||||||
memo = models.ForeignKey(
|
memo = models.ForeignKey(MemoModel, on_delete=models.CASCADE)
|
||||||
MemoModel, on_delete=models.CASCADE
|
|
||||||
)
|
|
||||||
|
|
||||||
def full_clean(self, **kwargs):
|
def full_clean(self, **kwargs):
|
||||||
if self.user_id is None:
|
if self.user_id is None:
|
||||||
|
@ -57,10 +57,11 @@ class MemoImageModel(BaseMemoAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Store images to Memos
|
Store images to Memos
|
||||||
"""
|
"""
|
||||||
|
|
||||||
image = models.ImageField(
|
image = models.ImageField(
|
||||||
upload_to=user_directory_path,
|
upload_to=user_directory_path,
|
||||||
verbose_name=_('MemoImageModel.image.verbose_name'),
|
verbose_name=_('MemoImageModel.image.verbose_name'),
|
||||||
help_text=_('MemoImageModel.image.help_text')
|
help_text=_('MemoImageModel.image.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -84,10 +85,11 @@ class MemoFileModel(BaseMemoAttachmentModel):
|
||||||
"""
|
"""
|
||||||
Store files to Memos
|
Store files to Memos
|
||||||
"""
|
"""
|
||||||
|
|
||||||
file = models.FileField(
|
file = models.FileField(
|
||||||
upload_to=user_directory_path,
|
upload_to=user_directory_path,
|
||||||
verbose_name=_('MemoFileModel.file.verbose_name'),
|
verbose_name=_('MemoFileModel.file.verbose_name'),
|
||||||
help_text=_('MemoFileModel.file.help_text')
|
help_text=_('MemoFileModel.file.help_text'),
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
|
@ -45,9 +45,7 @@ def setup_normal_user_permissions(normal_user_group):
|
||||||
ItemImageModel,
|
ItemImageModel,
|
||||||
ItemLinkModel,
|
ItemLinkModel,
|
||||||
ItemModel,
|
ItemModel,
|
||||||
|
|
||||||
LocationModel,
|
LocationModel,
|
||||||
|
|
||||||
MemoFileModel,
|
MemoFileModel,
|
||||||
MemoImageModel,
|
MemoImageModel,
|
||||||
MemoLinkModel,
|
MemoLinkModel,
|
|
@ -6,10 +6,6 @@ from inventory.permissions import get_or_create_normal_user_group
|
||||||
|
|
||||||
def get_normal_pyinventory_user(**baker_kwargs):
|
def get_normal_pyinventory_user(**baker_kwargs):
|
||||||
pyinventory_user_group = get_or_create_normal_user_group()[0]
|
pyinventory_user_group = get_or_create_normal_user_group()[0]
|
||||||
pyinventory_user = baker.make(
|
pyinventory_user = baker.make(User, is_staff=True, is_active=True, is_superuser=False, **baker_kwargs)
|
||||||
User,
|
|
||||||
is_staff=True, is_active=True, is_superuser=False,
|
|
||||||
**baker_kwargs
|
|
||||||
)
|
|
||||||
pyinventory_user.groups.set([pyinventory_user_group])
|
pyinventory_user.groups.set([pyinventory_user_group])
|
||||||
return pyinventory_user
|
return pyinventory_user
|
|
@ -20,32 +20,21 @@ class ItemImagesTestCase(TestCase):
|
||||||
pyinventory_user2 = get_normal_pyinventory_user(id=2)
|
pyinventory_user2 = get_normal_pyinventory_user(id=2)
|
||||||
|
|
||||||
token1_instance = UserMediaTokenModel.objects.get(user=pyinventory_user1)
|
token1_instance = UserMediaTokenModel.objects.get(user=pyinventory_user1)
|
||||||
assert repr(token1_instance) == (
|
assert repr(token1_instance) == (f"<UserMediaTokenModel: user:1 token:'user1token' ({token1_instance.pk})>")
|
||||||
f"<UserMediaTokenModel: user:1 token:'user1token' ({token1_instance.pk})>"
|
|
||||||
)
|
|
||||||
token2_instance = UserMediaTokenModel.objects.get(user=pyinventory_user2)
|
token2_instance = UserMediaTokenModel.objects.get(user=pyinventory_user2)
|
||||||
assert repr(token2_instance) == (
|
assert repr(token2_instance) == (f"<UserMediaTokenModel: user:2 token:'user2token' ({token2_instance.pk})>")
|
||||||
f"<UserMediaTokenModel: user:2 token:'user2token' ({token2_instance.pk})>"
|
|
||||||
)
|
|
||||||
|
|
||||||
with tempfile.TemporaryDirectory() as temp:
|
with tempfile.TemporaryDirectory() as temp:
|
||||||
with override_settings(MEDIA_ROOT=temp):
|
with override_settings(MEDIA_ROOT=temp):
|
||||||
with mock.patch('secrets.token_urlsafe', return_value='12345678901234567890'):
|
with mock.patch('secrets.token_urlsafe', return_value='12345678901234567890'):
|
||||||
image_instance = baker.make(
|
image_instance = baker.make(ItemImageModel, user=pyinventory_user1, _create_files=True)
|
||||||
ItemImageModel,
|
|
||||||
user=pyinventory_user1,
|
|
||||||
_create_files=True
|
|
||||||
)
|
|
||||||
|
|
||||||
assert image_instance.image is not None
|
assert image_instance.image is not None
|
||||||
url = image_instance.image.url
|
url = image_instance.image.url
|
||||||
assert url == '/media/user1token/12345678901234567890/mock_img.jpeg'
|
assert url == '/media/user1token/12345678901234567890/mock_img.jpeg'
|
||||||
|
|
||||||
# HTTP -> HTTPS redirect:
|
# HTTP -> HTTPS redirect:
|
||||||
response = self.client.get(
|
response = self.client.get('/media/user1token/12345678901234567890/mock_img.jpeg', secure=False)
|
||||||
'/media/user1token/12345678901234567890/mock_img.jpeg',
|
|
||||||
secure=False
|
|
||||||
)
|
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
status_code=301,
|
status_code=301,
|
|
@ -17,10 +17,7 @@ class ItemLinkModelTestCase(TestCase):
|
||||||
with self.assertLogs('django_tools'):
|
with self.assertLogs('django_tools'):
|
||||||
item = baker.make(ItemModel)
|
item = baker.make(ItemModel)
|
||||||
|
|
||||||
link = ItemLinkModel(
|
link = ItemLinkModel(item=item, url='http://test.tld/foo/bar')
|
||||||
item=item,
|
|
||||||
url='http://test.tld/foo/bar'
|
|
||||||
)
|
|
||||||
|
|
||||||
offset = datetime.timedelta(seconds=30)
|
offset = datetime.timedelta(seconds=30)
|
||||||
with patch.object(timezone, 'now', MockDatetimeGenerator(offset)):
|
with patch.object(timezone, 'now', MockDatetimeGenerator(offset)):
|
||||||
|
@ -35,9 +32,7 @@ class ItemLinkModelTestCase(TestCase):
|
||||||
assert link.last_check == parse_dt('2000-01-01T00:00:30+0000')
|
assert link.last_check == parse_dt('2000-01-01T00:00:30+0000')
|
||||||
|
|
||||||
logs = logs.output
|
logs = logs.output
|
||||||
assert logs == [
|
assert logs == ["WARNING:inventory.models.links:No title found in 'http://test.tld/foo/bar'"]
|
||||||
"WARNING:inventory.models.links:No title found in 'http://test.tld/foo/bar'"
|
|
||||||
]
|
|
||||||
|
|
||||||
# We should not create request on every admin save call
|
# We should not create request on every admin save call
|
||||||
|
|
||||||
|
@ -49,7 +44,7 @@ class ItemLinkModelTestCase(TestCase):
|
||||||
logs = logs.output
|
logs = logs.output
|
||||||
assert logs == [
|
assert logs == [
|
||||||
'DEBUG:inventory.models.links:Last check is 0:00:30 ago.',
|
'DEBUG:inventory.models.links:Last check is 0:00:30 ago.',
|
||||||
"INFO:inventory.models.links:Skip request for: 'http://test.tld/foo/bar'"
|
"INFO:inventory.models.links:Skip request for: 'http://test.tld/foo/bar'",
|
||||||
]
|
]
|
||||||
|
|
||||||
# Next try after 1 Min
|
# Next try after 1 Min
|
||||||
|
@ -61,9 +56,7 @@ class ItemLinkModelTestCase(TestCase):
|
||||||
assert link.name == 'A Title!'
|
assert link.name == 'A Title!'
|
||||||
|
|
||||||
logs = logs.output
|
logs = logs.output
|
||||||
assert logs == [
|
assert logs == ["INFO:inventory.models.links:Found title: 'A <boom>Title</boom>!'"]
|
||||||
"INFO:inventory.models.links:Found title: 'A <boom>Title</boom>!'"
|
|
||||||
]
|
|
||||||
|
|
||||||
# Don't make requests, if we have a link name!
|
# Don't make requests, if we have a link name!
|
||||||
|
|
||||||
|
@ -75,8 +68,5 @@ class ItemLinkModelTestCase(TestCase):
|
||||||
|
|
||||||
logs = logs.output
|
logs = logs.output
|
||||||
assert logs == [
|
assert logs == [
|
||||||
(
|
("DEBUG:inventory.models.links:Skip link request:" " because we have a name: 'A Title!'")
|
||||||
"DEBUG:inventory.models.links:Skip link request:"
|
|
||||||
" because we have a name: 'A Title!'"
|
|
||||||
)
|
|
||||||
]
|
]
|
|
@ -13,9 +13,7 @@ class ManagementCommandTestCase(TestCase):
|
||||||
def test_seed_data_command(self):
|
def test_seed_data_command(self):
|
||||||
output = io.StringIO()
|
output = io.StringIO()
|
||||||
|
|
||||||
management.call_command(
|
management.call_command(seed_data.Command(), user_count=2, location_count=2, item_count=2, stdout=output)
|
||||||
seed_data.Command(), user_count=2, location_count=2, item_count=2, stdout=output
|
|
||||||
)
|
|
||||||
assert User.objects.count() == 2
|
assert User.objects.count() == 2
|
||||||
assert LocationModel.objects.count() == 8
|
assert LocationModel.objects.count() == 8
|
||||||
assert ItemModel.objects.count() == 16
|
assert ItemModel.objects.count() == 16
|
|
@ -24,6 +24,4 @@ class ManagementCommandTestCase(TestCase):
|
||||||
assert "{'level': 1, 'path_str': 'OLD', 'path': ['OLD'], 'name': 'Foo Bar'}" in output
|
assert "{'level': 1, 'path_str': 'OLD', 'path': ['OLD'], 'name': 'Foo Bar'}" in output
|
||||||
|
|
||||||
assert "New information about model: 'Item'" in output
|
assert "New information about model: 'Item'" in output
|
||||||
assert (
|
assert "{'level': 1, 'path_str': 'foobar', 'path': ['Foo Bar'], 'name': 'Foo Bar'}" in output
|
||||||
"{'level': 1, 'path_str': 'foobar', 'path': ['Foo Bar'], 'name': 'Foo Bar'}" in output
|
|
||||||
)
|
|
|
@ -13,10 +13,7 @@ def test_values_list_tree():
|
||||||
(6, '2.', None),
|
(6, '2.', None),
|
||||||
]
|
]
|
||||||
random.shuffle(values_list)
|
random.shuffle(values_list)
|
||||||
values = [
|
values = [{'pk': entry[0], 'name': entry[1], 'parent__pk': entry[2], 'path': ''} for entry in values_list]
|
||||||
{'pk': entry[0], 'name': entry[1], 'parent__pk': entry[2], 'path': ''}
|
|
||||||
for entry in values_list
|
|
||||||
]
|
|
||||||
tree = ValuesListTree(values)
|
tree = ValuesListTree(values)
|
||||||
|
|
||||||
tree_path = tree.get_tree_path()
|
tree_path = tree.get_tree_path()
|
|
@ -0,0 +1,9 @@
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
from bx_py_utils.path import assert_is_dir
|
||||||
|
|
||||||
|
import inventory
|
||||||
|
|
||||||
|
|
||||||
|
PACKAGE_ROOT = Path(inventory.__file__).parent.parent
|
||||||
|
assert_is_dir(PACKAGE_ROOT / 'inventory')
|
|
@ -12,13 +12,10 @@ from dev_shell.utils.colorful import blue, bright_yellow, print_error
|
||||||
from dev_shell.utils.subprocess_utils import argv2str, make_relative_path, verbose_check_call
|
from dev_shell.utils.subprocess_utils import argv2str, make_relative_path, verbose_check_call
|
||||||
|
|
||||||
import inventory
|
import inventory
|
||||||
|
from inventory_project import PACKAGE_ROOT
|
||||||
from inventory_project.manage import main
|
from inventory_project.manage import main
|
||||||
|
|
||||||
|
|
||||||
PACKAGE_ROOT = Path(inventory.__file__).parent.parent.parent
|
|
||||||
assert_is_dir(PACKAGE_ROOT / 'src' / 'inventory')
|
|
||||||
|
|
||||||
|
|
||||||
class TempCwd:
|
class TempCwd:
|
||||||
def __init__(self, cwd: Path):
|
def __init__(self, cwd: Path):
|
||||||
assert_is_dir(cwd)
|
assert_is_dir(cwd)
|
||||||
|
@ -76,21 +73,15 @@ class PyInventoryCommandSet(DevShellBaseCommandSet):
|
||||||
'--ignore=.*',
|
'--ignore=.*',
|
||||||
'--ignore=htmlcov',
|
'--ignore=htmlcov',
|
||||||
'--ignore=volumes',
|
'--ignore=volumes',
|
||||||
cwd=PACKAGE_ROOT / 'src' / 'inventory'
|
cwd=PACKAGE_ROOT / 'inventory',
|
||||||
)
|
|
||||||
call_manage_py(
|
|
||||||
'compilemessages',
|
|
||||||
cwd=PACKAGE_ROOT / 'src' / 'inventory'
|
|
||||||
)
|
)
|
||||||
|
call_manage_py('compilemessages', cwd=PACKAGE_ROOT / 'inventory')
|
||||||
|
|
||||||
def do_update_rst_readme(self, statement: cmd2.Statement):
|
def do_update_rst_readme(self, statement: cmd2.Statement):
|
||||||
"""
|
"""
|
||||||
update README.rst from README.creole
|
update README.rst from README.creole
|
||||||
"""
|
"""
|
||||||
update_rst_readme(
|
update_rst_readme(package_root=PACKAGE_ROOT, filename='README.creole')
|
||||||
package_root=PACKAGE_ROOT,
|
|
||||||
filename='README.creole'
|
|
||||||
)
|
|
||||||
|
|
||||||
def do_ckeditor_info(self, statement: cmd2.Statement):
|
def do_ckeditor_info(self, statement: cmd2.Statement):
|
||||||
"""
|
"""
|
||||||
|
@ -142,7 +133,7 @@ class PyInventoryCommandSet(DevShellBaseCommandSet):
|
||||||
for lang_code in ('de', 'en'):
|
for lang_code in ('de', 'en'):
|
||||||
print('_' * 100)
|
print('_' * 100)
|
||||||
print(lang_code)
|
print(lang_code)
|
||||||
po_file_path = PACKAGE_ROOT / f'src/inventory/locale/{lang_code}/LC_MESSAGES/django.po'
|
po_file_path = PACKAGE_ROOT / f'inventory/locale/{lang_code}/LC_MESSAGES/django.po'
|
||||||
old_content = []
|
old_content = []
|
||||||
new_content = []
|
new_content = []
|
||||||
with po_file_path.open('r') as f:
|
with po_file_path.open('r') as f:
|
||||||
|
@ -193,7 +184,7 @@ class PyInventoryCommandSet(DevShellBaseCommandSet):
|
||||||
extra_env={
|
extra_env={
|
||||||
# https://github.com/boxine/bx_py_utils#notes-about-snapshot
|
# https://github.com/boxine/bx_py_utils#notes-about-snapshot
|
||||||
'RAISE_SNAPSHOT_ERRORS': '0'
|
'RAISE_SNAPSHOT_ERRORS': '0'
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
def do_playwright(self, statement: cmd2.Statement):
|
def do_playwright(self, statement: cmd2.Statement):
|
||||||
|
@ -253,16 +244,14 @@ def get_devshell_app_kwargs():
|
||||||
config = DevShellConfig(package_module=inventory)
|
config = DevShellConfig(package_module=inventory)
|
||||||
|
|
||||||
# initialize all CommandSet() with context:
|
# initialize all CommandSet() with context:
|
||||||
kwargs = dict(
|
kwargs = dict(config=config)
|
||||||
config=config
|
|
||||||
)
|
|
||||||
|
|
||||||
app_kwargs = dict(
|
app_kwargs = dict(
|
||||||
config=config,
|
config=config,
|
||||||
command_sets=[
|
command_sets=[
|
||||||
PyInventoryCommandSet(**kwargs),
|
PyInventoryCommandSet(**kwargs),
|
||||||
DevShellCommandSet(**kwargs),
|
DevShellCommandSet(**kwargs),
|
||||||
]
|
],
|
||||||
)
|
)
|
||||||
return app_kwargs
|
return app_kwargs
|
||||||
|
|
|
@ -25,6 +25,7 @@ def main(argv):
|
||||||
execute_from_command_line(argv)
|
execute_from_command_line(argv)
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
from bx_py_utils.error_handling import print_exc_plus
|
from bx_py_utils.error_handling import print_exc_plus
|
||||||
|
|
||||||
print_exc_plus(err)
|
print_exc_plus(err)
|
||||||
raise
|
raise
|
||||||
|
|
|
@ -1,20 +1,16 @@
|
||||||
from pathlib import Path
|
|
||||||
|
|
||||||
from poetry_publish.publish import poetry_publish
|
from poetry_publish.publish import poetry_publish
|
||||||
from poetry_publish.utils.subprocess_utils import verbose_check_call
|
from poetry_publish.utils.subprocess_utils import verbose_check_call
|
||||||
|
|
||||||
# https://github.com/jedie/PyInventory
|
# https://github.com/jedie/PyInventory
|
||||||
import inventory
|
import inventory
|
||||||
|
from inventory_project import PACKAGE_ROOT
|
||||||
|
|
||||||
PACKAGE_ROOT = Path(inventory.__file__).parent.parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
def publish():
|
def publish():
|
||||||
"""
|
"""
|
||||||
Publish to PyPi
|
Publish to PyPi
|
||||||
Call this via:
|
Call this via:
|
||||||
$ poetry run publish
|
$ poetry run publish
|
||||||
"""
|
"""
|
||||||
verbose_check_call('make', 'pytest') # don't publish if tests fail
|
verbose_check_call('make', 'pytest') # don't publish if tests fail
|
||||||
verbose_check_call('make', 'fix-code-style') # don't publish if code style wrong
|
verbose_check_call('make', 'fix-code-style') # don't publish if code style wrong
|
|
@ -27,7 +27,7 @@ print(f'BASE_PATH:{BASE_PATH}')
|
||||||
|
|
||||||
# Paths with Django dev. server:
|
# Paths with Django dev. server:
|
||||||
# BASE_PATH...: .../django-for-runners
|
# BASE_PATH...: .../django-for-runners
|
||||||
# PROJECT_PATH: .../django-for-runners/src
|
# PROJECT_PATH: .../django-for-runners
|
||||||
#
|
#
|
||||||
# Paths in Docker container:
|
# Paths in Docker container:
|
||||||
# BASE_PATH...: /for_runners_volumes
|
# BASE_PATH...: /for_runners_volumes
|
||||||
|
@ -55,6 +55,7 @@ __SECRET_FILE = __Path(BASE_PATH, 'secret.txt').resolve()
|
||||||
if not __SECRET_FILE.is_file():
|
if not __SECRET_FILE.is_file():
|
||||||
print(f'Generate {__SECRET_FILE}')
|
print(f'Generate {__SECRET_FILE}')
|
||||||
from secrets import token_urlsafe as __token_urlsafe
|
from secrets import token_urlsafe as __token_urlsafe
|
||||||
|
|
||||||
__SECRET_FILE.open('w').write(__token_urlsafe(128))
|
__SECRET_FILE.open('w').write(__token_urlsafe(128))
|
||||||
|
|
||||||
SECRET_KEY = __SECRET_FILE.open('r').read().strip()
|
SECRET_KEY = __SECRET_FILE.open('r').read().strip()
|
||||||
|
@ -70,7 +71,6 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
'django.contrib.sites',
|
'django.contrib.sites',
|
||||||
|
|
||||||
'bx_django_utils', # https://github.com/boxine/bx_django_utils
|
'bx_django_utils', # https://github.com/boxine/bx_django_utils
|
||||||
'import_export', # https://github.com/django-import-export/django-import-export
|
'import_export', # https://github.com/django-import-export/django-import-export
|
||||||
'dbbackup', # https://github.com/django-dbbackup/django-dbbackup
|
'dbbackup', # https://github.com/django-dbbackup/django-dbbackup
|
||||||
|
@ -81,13 +81,10 @@ INSTALLED_APPS = [
|
||||||
'tagulous', # https://github.com/radiac/django-tagulous
|
'tagulous', # https://github.com/radiac/django-tagulous
|
||||||
'adminsortable2', # https://github.com/jrief/django-admin-sortable2
|
'adminsortable2', # https://github.com/jrief/django-admin-sortable2
|
||||||
'axes', # https://github.com/jazzband/django-axes
|
'axes', # https://github.com/jazzband/django-axes
|
||||||
|
|
||||||
# https://github.com/jedie/django-tools/tree/master/django_tools/serve_media_app
|
# https://github.com/jedie/django-tools/tree/master/django_tools/serve_media_app
|
||||||
'django_tools.serve_media_app.apps.UserMediaFilesConfig',
|
'django_tools.serve_media_app.apps.UserMediaFilesConfig',
|
||||||
|
|
||||||
# https://github.com/jedie/django-tools/tree/master/django_tools/model_version_protect
|
# https://github.com/jedie/django-tools/tree/master/django_tools/model_version_protect
|
||||||
'django_tools.model_version_protect.apps.ModelVersionProtectConfig',
|
'django_tools.model_version_protect.apps.ModelVersionProtectConfig',
|
||||||
|
|
||||||
'inventory.apps.InventoryConfig',
|
'inventory.apps.InventoryConfig',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -106,13 +103,10 @@ MIDDLEWARE = [
|
||||||
'django.middleware.common.CommonMiddleware',
|
'django.middleware.common.CommonMiddleware',
|
||||||
'django.middleware.csrf.CsrfViewMiddleware',
|
'django.middleware.csrf.CsrfViewMiddleware',
|
||||||
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
'django.contrib.auth.middleware.AuthenticationMiddleware',
|
||||||
|
|
||||||
'inventory.middlewares.RequestDictMiddleware',
|
'inventory.middlewares.RequestDictMiddleware',
|
||||||
|
|
||||||
'django.contrib.messages.middleware.MessageMiddleware',
|
'django.contrib.messages.middleware.MessageMiddleware',
|
||||||
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
'django.middleware.clickjacking.XFrameOptionsMiddleware',
|
||||||
'django.middleware.security.SecurityMiddleware',
|
'django.middleware.security.SecurityMiddleware',
|
||||||
|
|
||||||
'axes.middleware.AxesMiddleware', # AxesMiddleware should be the last middleware
|
'axes.middleware.AxesMiddleware', # AxesMiddleware should be the last middleware
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -167,12 +161,7 @@ SECURE_HSTS_INCLUDE_SUBDOMAINS = True
|
||||||
|
|
||||||
LANGUAGE_CODE = 'en'
|
LANGUAGE_CODE = 'en'
|
||||||
|
|
||||||
LANGUAGES = [
|
LANGUAGES = [('ca', _('Catalan')), ('de', _('German')), ('en', _('English')), ('es', _('Spanish'))]
|
||||||
('ca', _('Catalan')),
|
|
||||||
('de', _('German')),
|
|
||||||
('en', _('English')),
|
|
||||||
('es', _('Spanish'))
|
|
||||||
]
|
|
||||||
USE_I18N = True
|
USE_I18N = True
|
||||||
USE_L10N = True
|
USE_L10N = True
|
||||||
TIME_ZONE = 'Europe/Paris'
|
TIME_ZONE = 'Europe/Paris'
|
||||||
|
@ -199,140 +188,145 @@ DBBACKUP_STORAGE_OPTIONS = {'location': str(__Path(BASE_PATH, 'backups'))}
|
||||||
CKEDITOR_BASEPATH = STATIC_URL + 'ckeditor/ckeditor/'
|
CKEDITOR_BASEPATH = STATIC_URL + 'ckeditor/ckeditor/'
|
||||||
CKEDITOR_FILENAME_GENERATOR = 'inventory.ckeditor_upload.get_filename'
|
CKEDITOR_FILENAME_GENERATOR = 'inventory.ckeditor_upload.get_filename'
|
||||||
CKEDITOR_DEFAULT_CONFIG = DEFAULT_CONFIG
|
CKEDITOR_DEFAULT_CONFIG = DEFAULT_CONFIG
|
||||||
CKEDITOR_DEFAULT_CONFIG.update({
|
CKEDITOR_DEFAULT_CONFIG.update(
|
||||||
'removeButtons': 'Language,Cut,Copy,Paste,Undo,Redo,Anchor',
|
{
|
||||||
|
'removeButtons': 'Language,Cut,Copy,Paste,Undo,Redo,Anchor',
|
||||||
# plugins are here: .../site-packages/ckeditor/static/ckeditor/ckeditor/plugins
|
# plugins are here: .../site-packages/ckeditor/static/ckeditor/ckeditor/plugins
|
||||||
# and here: https://github.com/ckeditor/ckeditor4/tree/major/plugins
|
# and here: https://github.com/ckeditor/ckeditor4/tree/major/plugins
|
||||||
# See also: .../site-packages/ckeditor/static/ckeditor/ckeditor/build-config.js
|
# See also: .../site-packages/ckeditor/static/ckeditor/ckeditor/build-config.js
|
||||||
'removePlugins': (
|
'removePlugins': (
|
||||||
# Generated with devshell command:
|
# Generated with devshell command:
|
||||||
# (inventory) ckeditor_info
|
# (inventory) ckeditor_info
|
||||||
'a11yhelp',
|
'a11yhelp',
|
||||||
# 'about',
|
# 'about',
|
||||||
'adobeair',
|
'adobeair',
|
||||||
'ajax',
|
'ajax',
|
||||||
'autoembed',
|
'autoembed',
|
||||||
# 'autogrow',
|
# 'autogrow',
|
||||||
'autolink',
|
'autolink',
|
||||||
# 'basicstyles',
|
# 'basicstyles',
|
||||||
'bbcode',
|
'bbcode',
|
||||||
'bidi',
|
'bidi',
|
||||||
# 'blockquote',
|
# 'blockquote',
|
||||||
'clipboard',
|
'clipboard',
|
||||||
'codesnippet',
|
'codesnippet',
|
||||||
'codesnippetgeshi',
|
'codesnippetgeshi',
|
||||||
# 'colorbutton',
|
# 'colorbutton',
|
||||||
# 'colordialog',
|
# 'colordialog',
|
||||||
'contextmenu',
|
'contextmenu',
|
||||||
'copyformatting',
|
'copyformatting',
|
||||||
'devtools',
|
'devtools',
|
||||||
'dialog',
|
'dialog',
|
||||||
'dialogadvtab',
|
'dialogadvtab',
|
||||||
'div',
|
'div',
|
||||||
'divarea',
|
'divarea',
|
||||||
'docprops',
|
'docprops',
|
||||||
# 'elementspath',
|
# 'elementspath',
|
||||||
'embed',
|
'embed',
|
||||||
'embedbase',
|
'embedbase',
|
||||||
'embedsemantic',
|
'embedsemantic',
|
||||||
'enterkey',
|
'enterkey',
|
||||||
# 'entities',
|
# 'entities',
|
||||||
'exportpdf',
|
'exportpdf',
|
||||||
# 'filebrowser',
|
# 'filebrowser',
|
||||||
# 'filetools',
|
# 'filetools',
|
||||||
'find',
|
'find',
|
||||||
'flash',
|
'flash',
|
||||||
# 'floatingspace',
|
# 'floatingspace',
|
||||||
# 'font',
|
# 'font',
|
||||||
# 'format',
|
# 'format',
|
||||||
'forms',
|
'forms',
|
||||||
# 'horizontalrule',
|
# 'horizontalrule',
|
||||||
'htmlwriter',
|
'htmlwriter',
|
||||||
'iframe',
|
'iframe',
|
||||||
'iframedialog',
|
'iframedialog',
|
||||||
# 'image',
|
# 'image',
|
||||||
# 'image2',
|
# 'image2',
|
||||||
# 'indentblock',
|
# 'indentblock',
|
||||||
# 'indentlist',
|
# 'indentlist',
|
||||||
# 'justify',
|
# 'justify',
|
||||||
'language',
|
'language',
|
||||||
# 'lineutils',
|
# 'lineutils',
|
||||||
# 'link',
|
# 'link',
|
||||||
# 'list',
|
# 'list',
|
||||||
# 'liststyle',
|
# 'liststyle',
|
||||||
'magicline',
|
'magicline',
|
||||||
'mathjax',
|
'mathjax',
|
||||||
# 'maximize',
|
# 'maximize',
|
||||||
# 'menubutton',
|
# 'menubutton',
|
||||||
'newpage',
|
'newpage',
|
||||||
'notification',
|
'notification',
|
||||||
'notificationaggregator',
|
'notificationaggregator',
|
||||||
'pagebreak',
|
'pagebreak',
|
||||||
'pastefromgdocs',
|
'pastefromgdocs',
|
||||||
'pastefromword',
|
'pastefromword',
|
||||||
'pastetext',
|
'pastetext',
|
||||||
'pastetools',
|
'pastetools',
|
||||||
'placeholder',
|
'placeholder',
|
||||||
'preview',
|
'preview',
|
||||||
'print',
|
'print',
|
||||||
# 'removeformat',
|
# 'removeformat',
|
||||||
# 'resize',
|
# 'resize',
|
||||||
'save',
|
'save',
|
||||||
'scayt',
|
'scayt',
|
||||||
'selectall',
|
'selectall',
|
||||||
'sharedspace',
|
'sharedspace',
|
||||||
# 'showblocks',
|
# 'showblocks',
|
||||||
# 'showborders',
|
# 'showborders',
|
||||||
'smiley',
|
'smiley',
|
||||||
# 'sourcearea',
|
# 'sourcearea',
|
||||||
'sourcedialog',
|
'sourcedialog',
|
||||||
'specialchar',
|
'specialchar',
|
||||||
'stylescombo',
|
'stylescombo',
|
||||||
'stylesheetparser',
|
'stylesheetparser',
|
||||||
'tab',
|
'tab',
|
||||||
# 'table',
|
# 'table',
|
||||||
# 'tableresize',
|
# 'tableresize',
|
||||||
# 'tableselection',
|
# 'tableselection',
|
||||||
# 'tabletools',
|
# 'tabletools',
|
||||||
'templates',
|
'templates',
|
||||||
# 'toolbar',
|
# 'toolbar',
|
||||||
'uicolor',
|
'uicolor',
|
||||||
# 'undo',
|
# 'undo',
|
||||||
# 'uploadimage',
|
# 'uploadimage',
|
||||||
# 'uploadwidget',
|
# 'uploadwidget',
|
||||||
'widget',
|
'widget',
|
||||||
'wsc',
|
'wsc',
|
||||||
# 'wysiwygarea',
|
# 'wysiwygarea',
|
||||||
'xml',
|
'xml',
|
||||||
),
|
),
|
||||||
'toolbar_PyInventoryToolbarConfig': [
|
'toolbar_PyInventoryToolbarConfig': [
|
||||||
{'name': 'basicstyles', 'items': [
|
{'name': 'basicstyles', 'items': ['Bold', 'Italic', 'Underline', 'Strike', '-', 'RemoveFormat']},
|
||||||
'Bold', 'Italic', 'Underline', 'Strike',
|
{
|
||||||
'-',
|
'name': 'paragraph',
|
||||||
'RemoveFormat'
|
'items': [
|
||||||
]},
|
'NumberedList',
|
||||||
{'name': 'paragraph', 'items': [
|
'BulletedList',
|
||||||
'NumberedList', 'BulletedList',
|
'-',
|
||||||
'-',
|
'Outdent',
|
||||||
'Outdent', 'Indent',
|
'Indent',
|
||||||
'-',
|
'-',
|
||||||
'Blockquote',
|
'Blockquote',
|
||||||
'-',
|
'-',
|
||||||
'JustifyLeft', 'JustifyCenter', 'JustifyRight', 'JustifyBlock',
|
'JustifyLeft',
|
||||||
]},
|
'JustifyCenter',
|
||||||
{'name': 'links', 'items': ['Link', 'Unlink', 'Anchor']},
|
'JustifyRight',
|
||||||
{'name': 'insert', 'items': ['Image', 'Table', 'HorizontalRule']},
|
'JustifyBlock',
|
||||||
'/',
|
],
|
||||||
{'name': 'styles', 'items': ['Styles', 'Format', 'Font', 'FontSize']},
|
},
|
||||||
{'name': 'colors', 'items': ['TextColor', 'BGColor']},
|
{'name': 'links', 'items': ['Link', 'Unlink', 'Anchor']},
|
||||||
{'name': 'tools', 'items': ['Maximize', 'ShowBlocks', 'Source']},
|
{'name': 'insert', 'items': ['Image', 'Table', 'HorizontalRule']},
|
||||||
{'name': 'about', 'items': ['About']},
|
'/',
|
||||||
],
|
{'name': 'styles', 'items': ['Styles', 'Format', 'Font', 'FontSize']},
|
||||||
'toolbar': 'PyInventoryToolbarConfig',
|
{'name': 'colors', 'items': ['TextColor', 'BGColor']},
|
||||||
'height': '25em',
|
{'name': 'tools', 'items': ['Maximize', 'ShowBlocks', 'Source']},
|
||||||
'width': '100%',
|
{'name': 'about', 'items': ['About']},
|
||||||
})
|
],
|
||||||
|
'toolbar': 'PyInventoryToolbarConfig',
|
||||||
|
'height': '25em',
|
||||||
|
'width': '100%',
|
||||||
|
}
|
||||||
|
)
|
||||||
CKEDITOR_CONFIGS = {
|
CKEDITOR_CONFIGS = {
|
||||||
'ItemModel.description': CKEDITOR_DEFAULT_CONFIG,
|
'ItemModel.description': CKEDITOR_DEFAULT_CONFIG,
|
||||||
'LocationModel.description': CKEDITOR_DEFAULT_CONFIG,
|
'LocationModel.description': CKEDITOR_DEFAULT_CONFIG,
|
|
@ -18,9 +18,9 @@ TEMPLATE_DEBUG = False
|
||||||
|
|
||||||
ALLOWED_HOSTS = ('127.0.0.1', '0.0.0.0', 'localhost')
|
ALLOWED_HOSTS = ('127.0.0.1', '0.0.0.0', 'localhost')
|
||||||
|
|
||||||
LOGGING['formatters']['colored']['format'] = (
|
LOGGING['formatters']['colored'][
|
||||||
'%(log_color)s%(name)s %(levelname)8s %(cut_path)s:%(lineno)-3s %(message)s'
|
'format'
|
||||||
)
|
] = '%(log_color)s%(name)s %(levelname)8s %(cut_path)s:%(lineno)-3s %(message)s'
|
||||||
|
|
||||||
|
|
||||||
# https://github.com/microsoft/playwright-pytest/issues/115
|
# https://github.com/microsoft/playwright-pytest/issues/115
|
|
@ -8,12 +8,8 @@ class AdminAnonymousTests(TestCase):
|
||||||
|
|
||||||
def test_login_en(self):
|
def test_login_en(self):
|
||||||
response = self.client.get('/admin/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
response = self.client.get('/admin/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
||||||
self.assertRedirects(
|
self.assertRedirects(response, expected_url='/admin/login/?next=/admin/', fetch_redirect_response=False)
|
||||||
response, expected_url='/admin/login/?next=/admin/', fetch_redirect_response=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def test_login_de(self):
|
def test_login_de(self):
|
||||||
response = self.client.get('/admin/', secure=True, HTTP_ACCEPT_LANGUAGE='de')
|
response = self.client.get('/admin/', secure=True, HTTP_ACCEPT_LANGUAGE='de')
|
||||||
self.assertRedirects(
|
self.assertRedirects(response, expected_url='/admin/login/?next=/admin/', fetch_redirect_response=False)
|
||||||
response, expected_url='/admin/login/?next=/admin/', fetch_redirect_response=False
|
|
||||||
)
|
|
|
@ -24,19 +24,16 @@ ITEM_FORM_DEFAULTS = {
|
||||||
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
'itemimagemodel_set-MIN_NUM_FORMS': '0',
|
||||||
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
'itemimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'itemimagemodel_set-__prefix__-position': '0',
|
'itemimagemodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'itemfilemodel_set-TOTAL_FORMS': '0',
|
'itemfilemodel_set-TOTAL_FORMS': '0',
|
||||||
'itemfilemodel_set-INITIAL_FORMS': '0',
|
'itemfilemodel_set-INITIAL_FORMS': '0',
|
||||||
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
'itemfilemodel_set-MIN_NUM_FORMS': '0',
|
||||||
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
'itemfilemodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'itemfilemodel_set-__prefix__-position': '0',
|
'itemfilemodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
'itemlinkmodel_set-TOTAL_FORMS': '0',
|
||||||
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
'itemlinkmodel_set-INITIAL_FORMS': '0',
|
||||||
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
'itemlinkmodel_set-MIN_NUM_FORMS': '0',
|
||||||
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
'itemlinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'itemlinkmodel_set-__prefix__-position': '0',
|
'itemlinkmodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'_save': 'Save',
|
'_save': 'Save',
|
||||||
}
|
}
|
||||||
ITEM_FORM_DEFAULTS = tuple(ITEM_FORM_DEFAULTS.items())
|
ITEM_FORM_DEFAULTS = tuple(ITEM_FORM_DEFAULTS.items())
|
||||||
|
@ -51,7 +48,7 @@ class AdminAnonymousTests(HtmlAssertionMixin, TestCase):
|
||||||
response,
|
response,
|
||||||
expected_url='https://testserver/admin/',
|
expected_url='https://testserver/admin/',
|
||||||
status_code=301, # Permanent redirect
|
status_code=301, # Permanent redirect
|
||||||
fetch_redirect_response=False
|
fetch_redirect_response=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
response = self.client.get(path='/admin/inventory/itemmodel/add/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
response = self.client.get(path='/admin/inventory/itemmodel/add/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
||||||
|
@ -152,11 +149,13 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
img = ImageDummy(width=1, height=1, format='png').in_memory_image_file(filename='test.png')
|
img = ImageDummy(width=1, height=1, format='png').in_memory_image_file(filename='test.png')
|
||||||
|
|
||||||
post_data = dict(ITEM_FORM_DEFAULTS)
|
post_data = dict(ITEM_FORM_DEFAULTS)
|
||||||
post_data.update({
|
post_data.update(
|
||||||
'itemimagemodel_set-TOTAL_FORMS': '1',
|
{
|
||||||
'itemimagemodel_set-0-position': '0',
|
'itemimagemodel_set-TOTAL_FORMS': '1',
|
||||||
'itemimagemodel_set-0-image': img,
|
'itemimagemodel_set-0-position': '0',
|
||||||
})
|
'itemimagemodel_set-0-image': img,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
response = self.client.post(
|
response = self.client.post(
|
||||||
path='/admin/inventory/itemmodel/add/',
|
path='/admin/inventory/itemmodel/add/',
|
||||||
|
@ -194,7 +193,7 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
main_item = ItemModel.objects.create(
|
main_item = ItemModel.objects.create(
|
||||||
id=f'00000000-000{main_item_no}-0000-0000-000000000000',
|
id=f'00000000-000{main_item_no}-0000-0000-000000000000',
|
||||||
user=self.normaluser,
|
user=self.normaluser,
|
||||||
name=f'main item {main_item_no}'
|
name=f'main item {main_item_no}',
|
||||||
)
|
)
|
||||||
main_item.full_clean()
|
main_item.full_clean()
|
||||||
for sub_item_no in range(1, 3):
|
for sub_item_no in range(1, 3):
|
||||||
|
@ -202,14 +201,18 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
id=f'00000000-000{main_item_no}-000{sub_item_no}-0000-000000000000',
|
id=f'00000000-000{main_item_no}-000{sub_item_no}-0000-000000000000',
|
||||||
user=self.normaluser,
|
user=self.normaluser,
|
||||||
parent=main_item,
|
parent=main_item,
|
||||||
name=f'sub item {main_item_no}.{sub_item_no}'
|
name=f'sub item {main_item_no}.{sub_item_no}',
|
||||||
)
|
)
|
||||||
sub_item.full_clean()
|
sub_item.full_clean()
|
||||||
|
|
||||||
names = list(ItemModel.objects.order_by('id').values_list('name', flat=True))
|
names = list(ItemModel.objects.order_by('id').values_list('name', flat=True))
|
||||||
assert names == [
|
assert names == [
|
||||||
'main item 1', 'sub item 1.1', 'sub item 1.2',
|
'main item 1',
|
||||||
'main item 2', 'sub item 2.1', 'sub item 2.2',
|
'sub item 1.1',
|
||||||
|
'sub item 1.2',
|
||||||
|
'main item 2',
|
||||||
|
'sub item 2.1',
|
||||||
|
'sub item 2.2',
|
||||||
]
|
]
|
||||||
|
|
||||||
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
with mock.patch.object(NowNode, 'render', return_value='MockedNowNode'), mock.patch.object(
|
|
@ -15,11 +15,7 @@ from inventory_project.tests.mocks import MockInventoryVersionString
|
||||||
|
|
||||||
class AdminAnonymousTests(TestCase):
|
class AdminAnonymousTests(TestCase):
|
||||||
def test_login(self):
|
def test_login(self):
|
||||||
response = self.client.get(
|
response = self.client.get('/admin/inventory/memomodel/add/', secure=True, HTTP_ACCEPT_LANGUAGE='en')
|
||||||
'/admin/inventory/memomodel/add/',
|
|
||||||
secure=True,
|
|
||||||
HTTP_ACCEPT_LANGUAGE='en'
|
|
||||||
)
|
|
||||||
self.assertRedirects(
|
self.assertRedirects(
|
||||||
response,
|
response,
|
||||||
expected_url='/admin/login/?next=/admin/inventory/memomodel/add/',
|
expected_url='/admin/login/?next=/admin/inventory/memomodel/add/',
|
||||||
|
@ -31,10 +27,7 @@ class AdminAnonymousTests(TestCase):
|
||||||
class AdminTestCase(HtmlAssertionMixin, TestCase):
|
class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
@classmethod
|
@classmethod
|
||||||
def setUpTestData(cls):
|
def setUpTestData(cls):
|
||||||
cls.normaluser = baker.make(
|
cls.normaluser = baker.make(User, username='NormalUser', is_staff=True, is_active=True, is_superuser=False)
|
||||||
User, username='NormalUser',
|
|
||||||
is_staff=True, is_active=True, is_superuser=False
|
|
||||||
)
|
|
||||||
assert cls.normaluser.user_permissions.count() == 0
|
assert cls.normaluser.user_permissions.count() == 0
|
||||||
group = get_or_create_normal_user_group()[0]
|
group = get_or_create_normal_user_group()[0]
|
||||||
cls.normaluser.groups.set([group])
|
cls.normaluser.groups.set([group])
|
||||||
|
@ -58,25 +51,21 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
'version': 0, # VersionProtectBaseModel field
|
'version': 0, # VersionProtectBaseModel field
|
||||||
'name': 'The Memo Name',
|
'name': 'The Memo Name',
|
||||||
'memo': 'This is a test Memo',
|
'memo': 'This is a test Memo',
|
||||||
|
|
||||||
'memoimagemodel_set-TOTAL_FORMS': '0',
|
'memoimagemodel_set-TOTAL_FORMS': '0',
|
||||||
'memoimagemodel_set-INITIAL_FORMS': '0',
|
'memoimagemodel_set-INITIAL_FORMS': '0',
|
||||||
'memoimagemodel_set-MIN_NUM_FORMS': '0',
|
'memoimagemodel_set-MIN_NUM_FORMS': '0',
|
||||||
'memoimagemodel_set-MAX_NUM_FORMS': '1000',
|
'memoimagemodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'memoimagemodel_set-__prefix__-position': '0',
|
'memoimagemodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'memofilemodel_set-TOTAL_FORMS': '0',
|
'memofilemodel_set-TOTAL_FORMS': '0',
|
||||||
'memofilemodel_set-INITIAL_FORMS': '0',
|
'memofilemodel_set-INITIAL_FORMS': '0',
|
||||||
'memofilemodel_set-MIN_NUM_FORMS': '0',
|
'memofilemodel_set-MIN_NUM_FORMS': '0',
|
||||||
'memofilemodel_set-MAX_NUM_FORMS': '1000',
|
'memofilemodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'memofilemodel_set-__prefix__-position': '0',
|
'memofilemodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'memolinkmodel_set-TOTAL_FORMS': '0',
|
'memolinkmodel_set-TOTAL_FORMS': '0',
|
||||||
'memolinkmodel_set-INITIAL_FORMS': '0',
|
'memolinkmodel_set-INITIAL_FORMS': '0',
|
||||||
'memolinkmodel_set-MIN_NUM_FORMS': '0',
|
'memolinkmodel_set-MIN_NUM_FORMS': '0',
|
||||||
'memolinkmodel_set-MAX_NUM_FORMS': '1000',
|
'memolinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'memolinkmodel_set-__prefix__-position': '0',
|
'memolinkmodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'_save': 'Save',
|
'_save': 'Save',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
@ -88,10 +77,13 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
|
|
||||||
item = MemoModel.objects.first()
|
item = MemoModel.objects.first()
|
||||||
|
|
||||||
self.assert_messages(response, expected_messages=[
|
self.assert_messages(
|
||||||
f'The Memo “<a href="/admin/inventory/memomodel/{item.pk}/change/">The Memo Name</a>”'
|
response,
|
||||||
' was added successfully.'
|
expected_messages=[
|
||||||
])
|
f'The Memo “<a href="/admin/inventory/memomodel/{item.pk}/change/">The Memo Name</a>”'
|
||||||
|
' was added successfully.'
|
||||||
|
],
|
||||||
|
)
|
||||||
|
|
||||||
assert item.user_id == self.normaluser.pk
|
assert item.user_id == self.normaluser.pk
|
||||||
|
|
||||||
|
@ -113,7 +105,6 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
'version': 0, # VersionProtectBaseModel field
|
'version': 0, # VersionProtectBaseModel field
|
||||||
'name': 'The Memo Name',
|
'name': 'The Memo Name',
|
||||||
'memo': 'This is a test Memo',
|
'memo': 'This is a test Memo',
|
||||||
|
|
||||||
'memoimagemodel_set-TOTAL_FORMS': '1',
|
'memoimagemodel_set-TOTAL_FORMS': '1',
|
||||||
'memoimagemodel_set-INITIAL_FORMS': '0',
|
'memoimagemodel_set-INITIAL_FORMS': '0',
|
||||||
'memoimagemodel_set-MIN_NUM_FORMS': '0',
|
'memoimagemodel_set-MIN_NUM_FORMS': '0',
|
||||||
|
@ -121,28 +112,28 @@ class AdminTestCase(HtmlAssertionMixin, TestCase):
|
||||||
'memoimagemodel_set-0-position': '0',
|
'memoimagemodel_set-0-position': '0',
|
||||||
'memoimagemodel_set-__prefix__-position': '0',
|
'memoimagemodel_set-__prefix__-position': '0',
|
||||||
'memoimagemodel_set-0-image': img,
|
'memoimagemodel_set-0-image': img,
|
||||||
|
|
||||||
'memofilemodel_set-TOTAL_FORMS': '0',
|
'memofilemodel_set-TOTAL_FORMS': '0',
|
||||||
'memofilemodel_set-INITIAL_FORMS': '0',
|
'memofilemodel_set-INITIAL_FORMS': '0',
|
||||||
'memofilemodel_set-MIN_NUM_FORMS': '0',
|
'memofilemodel_set-MIN_NUM_FORMS': '0',
|
||||||
'memofilemodel_set-MAX_NUM_FORMS': '1000',
|
'memofilemodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'memofilemodel_set-__prefix__-position': '0',
|
'memofilemodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'memolinkmodel_set-TOTAL_FORMS': '0',
|
'memolinkmodel_set-TOTAL_FORMS': '0',
|
||||||
'memolinkmodel_set-INITIAL_FORMS': '0',
|
'memolinkmodel_set-INITIAL_FORMS': '0',
|
||||||
'memolinkmodel_set-MIN_NUM_FORMS': '0',
|
'memolinkmodel_set-MIN_NUM_FORMS': '0',
|
||||||
'memolinkmodel_set-MAX_NUM_FORMS': '1000',
|
'memolinkmodel_set-MAX_NUM_FORMS': '1000',
|
||||||
'memolinkmodel_set-__prefix__-position': '0',
|
'memolinkmodel_set-__prefix__-position': '0',
|
||||||
|
|
||||||
'_save': 'Save',
|
'_save': 'Save',
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
assert response.status_code == 302, response.content.decode('utf-8') # Form error?
|
assert response.status_code == 302, response.content.decode('utf-8') # Form error?
|
||||||
memo = MemoModel.objects.first() or MemoModel()
|
memo = MemoModel.objects.first() or MemoModel()
|
||||||
self.assert_messages(response, expected_messages=[
|
self.assert_messages(
|
||||||
f'The Memo “<a href="/admin/inventory/memomodel/{memo.pk}/change/">The Memo Name</a>”'
|
response,
|
||||||
' was added successfully.'
|
expected_messages=[
|
||||||
])
|
f'The Memo “<a href="/admin/inventory/memomodel/{memo.pk}/change/">The Memo Name</a>”'
|
||||||
|
' was added successfully.'
|
||||||
|
],
|
||||||
|
)
|
||||||
self.assertRedirects(response, expected_url='/admin/inventory/memomodel/')
|
self.assertRedirects(response, expected_url='/admin/inventory/memomodel/')
|
||||||
|
|
||||||
data = list(MemoModel.objects.values_list('name', 'memo'))
|
data = list(MemoModel.objects.values_list('name', 'memo'))
|
|
@ -19,9 +19,5 @@ class BootstrapTestCase(TestCase):
|
||||||
|
|
||||||
are_the_same = filecmp.cmp(source_file_path, own_bootstrap_file, shallow=False)
|
are_the_same = filecmp.cmp(source_file_path, own_bootstrap_file, shallow=False)
|
||||||
if not are_the_same:
|
if not are_the_same:
|
||||||
shutil.copyfile(
|
shutil.copyfile(src=source_file_path, dst=own_bootstrap_file, follow_symlinks=False)
|
||||||
src=source_file_path,
|
|
||||||
dst=own_bootstrap_file,
|
|
||||||
follow_symlinks=False
|
|
||||||
)
|
|
||||||
raise AssertionError(f'Bootstrap "{own_bootstrap_file}" updated!')
|
raise AssertionError(f'Bootstrap "{own_bootstrap_file}" updated!')
|
|
@ -1,18 +1,14 @@
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
|
||||||
from unittest import TestCase
|
from unittest import TestCase
|
||||||
|
|
||||||
from dev_shell.utils.assertion import assert_is_file
|
from dev_shell.utils.assertion import assert_is_file
|
||||||
|
|
||||||
import inventory
|
from inventory_project import PACKAGE_ROOT
|
||||||
|
|
||||||
|
|
||||||
BASE_PATH = Path(inventory.__file__).parent.parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
def call_devshell_commands(*args):
|
def call_devshell_commands(*args):
|
||||||
dev_shell_py = BASE_PATH / 'devshell.py'
|
dev_shell_py = PACKAGE_ROOT / 'devshell.py'
|
||||||
assert_is_file(dev_shell_py)
|
assert_is_file(dev_shell_py)
|
||||||
output = subprocess.check_output(
|
output = subprocess.check_output(
|
||||||
[sys.executable, str(dev_shell_py)] + list(args), stderr=subprocess.STDOUT, text=True
|
[sys.executable, str(dev_shell_py)] + list(args), stderr=subprocess.STDOUT, text=True
|
||||||
|
@ -46,6 +42,6 @@ class DevShellTestCase(TestCase):
|
||||||
def test_manage_command(self):
|
def test_manage_command(self):
|
||||||
output = call_devshell_commands('manage', 'diffsettings')
|
output = call_devshell_commands('manage', 'diffsettings')
|
||||||
assert "DJANGO_SETTINGS_MODULE='inventory_project.settings.tests'" in output
|
assert "DJANGO_SETTINGS_MODULE='inventory_project.settings.tests'" in output
|
||||||
assert f"PROJECT_PATH:{BASE_PATH}/src" in output
|
assert f"PROJECT_PATH:{PACKAGE_ROOT}" in output
|
||||||
assert f"BASE_PATH:{BASE_PATH}" in output
|
assert f"BASE_PATH:{PACKAGE_ROOT}" in output
|
||||||
assert f"PROJECT_PATH = PosixPath('{BASE_PATH}/src')" in output
|
assert f"PROJECT_PATH = PosixPath('{PACKAGE_ROOT}')" in output
|
|
@ -6,18 +6,16 @@ from django.test import TestCase, override_settings
|
||||||
|
|
||||||
|
|
||||||
class TestMigrations(TestCase):
|
class TestMigrations(TestCase):
|
||||||
databases = ['default', ]
|
databases = [
|
||||||
|
'default',
|
||||||
|
]
|
||||||
|
|
||||||
@override_settings(MIGRATION_MODULES={})
|
@override_settings(MIGRATION_MODULES={})
|
||||||
def test_missing_migrations(self):
|
def test_missing_migrations(self):
|
||||||
output = io.StringIO()
|
output = io.StringIO()
|
||||||
try:
|
try:
|
||||||
management.call_command(
|
management.call_command(
|
||||||
makemigrations.Command(),
|
makemigrations.Command(), dry_run=True, check_changes=True, verbosity=1, stdout=output
|
||||||
dry_run=True,
|
|
||||||
check_changes=True,
|
|
||||||
verbosity=1,
|
|
||||||
stdout=output
|
|
||||||
)
|
)
|
||||||
except SystemExit as err:
|
except SystemExit as err:
|
||||||
if err.code != 0:
|
if err.code != 0:
|
|
@ -101,9 +101,7 @@ def test_normal_user_create_item(live_server, client, page: Page, png_image):
|
||||||
|
|
||||||
# Save the item:
|
# Save the item:
|
||||||
page.locator('input:has-text("Save and continue editing")').click()
|
page.locator('input:has-text("Save and continue editing")').click()
|
||||||
page.locator(
|
page.locator('text=The Tunes Item “A Test Tunes Item” was added successfully. You may edit it again')
|
||||||
'text=The Tunes Item “A Test Tunes Item” was added successfully. You may edit it again'
|
|
||||||
)
|
|
||||||
page.locator('text="Triple D Int.Ltd." - TD-20 (8088)')
|
page.locator('text="Triple D Int.Ltd." - TD-20 (8088)')
|
||||||
|
|
||||||
assert ItemModel.objects.count() == 1
|
assert ItemModel.objects.count() == 1
|
|
@ -12,9 +12,7 @@ from django_tools.unittest_utils.project_setup import check_editor_config
|
||||||
from packaging.version import Version
|
from packaging.version import Version
|
||||||
|
|
||||||
import inventory
|
import inventory
|
||||||
|
from inventory_project import PACKAGE_ROOT
|
||||||
|
|
||||||
PACKAGE_ROOT = Path(inventory.__file__).parent.parent.parent
|
|
||||||
|
|
||||||
|
|
||||||
def assert_file_contains_string(file_path, string):
|
def assert_file_contains_string(file_path, string):
|
||||||
|
@ -37,14 +35,9 @@ def test_version(package_root=None, version=None):
|
||||||
if not ver_obj.is_prerelease:
|
if not ver_obj.is_prerelease:
|
||||||
version_string = f'v{version}'
|
version_string = f'v{version}'
|
||||||
|
|
||||||
assert_file_contains_string(
|
assert_file_contains_string(file_path=Path(package_root, 'README.md'), string=version_string)
|
||||||
file_path=Path(package_root, 'README.md'), string=version_string
|
|
||||||
)
|
|
||||||
|
|
||||||
assert_file_contains_string(
|
assert_file_contains_string(file_path=Path(package_root, 'pyproject.toml'), string=f'version = "{version}"')
|
||||||
file_path=Path(package_root, 'pyproject.toml'),
|
|
||||||
string=f'version = "{version}"'
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_poetry_check(package_root=None):
|
def test_poetry_check(package_root=None):
|
|
@ -9,9 +9,7 @@ admin.autodiscover()
|
||||||
|
|
||||||
urlpatterns = [ # Don't use i18n_patterns() here
|
urlpatterns = [ # Don't use i18n_patterns() here
|
||||||
path('admin/', admin.site.urls),
|
path('admin/', admin.site.urls),
|
||||||
|
|
||||||
re_path(r'^$', RedirectView.as_view(pattern_name='admin:index')),
|
re_path(r'^$', RedirectView.as_view(pattern_name='admin:index')),
|
||||||
|
|
||||||
path('ckeditor/', include('ckeditor_uploader.urls')), # TODO: check permissions?
|
path('ckeditor/', include('ckeditor_uploader.urls')), # TODO: check permissions?
|
||||||
path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
path(settings.MEDIA_URL.lstrip('/'), include('django_tools.serve_media_app.urls')),
|
||||||
]
|
]
|
||||||
|
@ -19,4 +17,5 @@ urlpatterns = [ # Don't use i18n_patterns() here
|
||||||
|
|
||||||
if settings.DEBUG:
|
if settings.DEBUG:
|
||||||
import debug_toolbar
|
import debug_toolbar
|
||||||
|
|
||||||
urlpatterns = [re_path(r'^__debug__/', include(debug_toolbar.urls))] + urlpatterns
|
urlpatterns = [re_path(r'^__debug__/', include(debug_toolbar.urls))] + urlpatterns
|
|
@ -10,8 +10,8 @@ maintainers = [
|
||||||
]
|
]
|
||||||
homepage = "https://github.com/jedie/PyInventory"
|
homepage = "https://github.com/jedie/PyInventory"
|
||||||
packages = [
|
packages = [
|
||||||
{ include = "inventory", from = "src" },
|
{ include = "inventory" },
|
||||||
{ include = "inventory_project", from = "src" },
|
{ include = "inventory_project" },
|
||||||
]
|
]
|
||||||
keywords=['inventory','django']
|
keywords=['inventory','django']
|
||||||
classifiers = [
|
classifiers = [
|
||||||
|
|
|
@ -1,202 +0,0 @@
|
||||||
# Generated by Django 2.2.16 on 2020-10-17 17:26
|
|
||||||
|
|
||||||
import ckeditor_uploader.fields
|
|
||||||
from django.conf import settings
|
|
||||||
from django.db import migrations, models
|
|
||||||
import django.db.models.deletion
|
|
||||||
import tagulous.models.fields
|
|
||||||
import tagulous.models.models
|
|
||||||
import uuid
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
initial = True
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_LocationModel_tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_ItemModel_tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_ItemModel_producer',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_ItemModel_kind',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_ItemLinkModel_tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_BaseModel_tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='Tagulous_BaseLink_tags',
|
|
||||||
fields=[
|
|
||||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
|
||||||
('name', models.CharField(max_length=255, unique=True)),
|
|
||||||
('slug', models.SlugField()),
|
|
||||||
('count', models.IntegerField(default=0, help_text='Internal counter of how many times this tag is in use')),
|
|
||||||
('protected', models.BooleanField(default=False, help_text='Will not be deleted when the count reaches 0')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'ordering': ('name',),
|
|
||||||
'abstract': False,
|
|
||||||
'unique_together': {('slug',)},
|
|
||||||
},
|
|
||||||
bases=(tagulous.models.models.BaseTagModel, models.Model),
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='LocationModel',
|
|
||||||
fields=[
|
|
||||||
('create_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.create_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.create_dt.verbose_name')),
|
|
||||||
('update_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.update_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.update_dt.verbose_name')),
|
|
||||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='BaseModel.id.help_text', primary_key=True, serialize=False, verbose_name='BaseModel.id.verbose_name')),
|
|
||||||
('name', models.CharField(help_text='BaseModel.name.help_text', max_length=255, verbose_name='BaseModel.name.verbose_name')),
|
|
||||||
('description', ckeditor_uploader.fields.RichTextUploadingField(help_text='LocationModel.description.help_text', verbose_name='LocationModel.description.verbose_name')),
|
|
||||||
('parent', models.ForeignKey(blank=True, help_text='LocationModel.parent.help_text', null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.LocationModel', verbose_name='LocationModel.parent.verbose_name')),
|
|
||||||
('tags', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, to='inventory.Tagulous_LocationModel_tags', verbose_name='BaseModel.tags.verbose_name')),
|
|
||||||
('user', models.ForeignKey(editable=False, help_text='BaseModel.user.help_text', on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='BaseModel.user.verbose_name')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'LocationModel.verbose_name',
|
|
||||||
'verbose_name_plural': 'LocationModel.verbose_name_plural',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='ItemModel',
|
|
||||||
fields=[
|
|
||||||
('create_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.create_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.create_dt.verbose_name')),
|
|
||||||
('update_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.update_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.update_dt.verbose_name')),
|
|
||||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='BaseModel.id.help_text', primary_key=True, serialize=False, verbose_name='BaseModel.id.verbose_name')),
|
|
||||||
('name', models.CharField(help_text='BaseModel.name.help_text', max_length=255, verbose_name='BaseModel.name.verbose_name')),
|
|
||||||
('description', ckeditor_uploader.fields.RichTextUploadingField(blank=True, help_text='ItemModel.description.help_text', null=True, verbose_name='ItemModel.description.verbose_name')),
|
|
||||||
('fcc_id', models.CharField(blank=True, help_text='ItemModel.fcc_id.help_text', max_length=20, null=True, verbose_name='ItemModel.fcc_id.verbose_name')),
|
|
||||||
('lent_to', models.CharField(blank=True, help_text='ItemModel.lent_to.help_text', max_length=64, null=True, verbose_name='ItemModel.lent_to.verbose_name')),
|
|
||||||
('lent_from_date', models.DateField(blank=True, help_text='ItemModel.lent_from_date.help_text', null=True, verbose_name='ItemModel.lent_from_date.verbose_name')),
|
|
||||||
('lent_until_date', models.DateField(blank=True, help_text='ItemModel.lent_until_date.help_text', null=True, verbose_name='ItemModel.lent_until_date.verbose_name')),
|
|
||||||
('received_from', models.CharField(blank=True, help_text='ItemModel.received_from.help_text', max_length=64, null=True, verbose_name='ItemModel.received_from.verbose_name')),
|
|
||||||
('received_date', models.DateField(blank=True, help_text='ItemModel.received_date.help_text', null=True, verbose_name='ItemModel.received_date.verbose_name')),
|
|
||||||
('received_price', models.DecimalField(blank=True, decimal_places=2, help_text='ItemModel.received_price.help_text', max_digits=6, null=True, verbose_name='ItemModel.received_price.verbose_name')),
|
|
||||||
('handed_over_to', models.CharField(blank=True, help_text='ItemModel.handed_over_to.help_text', max_length=64, null=True, verbose_name='ItemModel.handed_over_to.verbose_name')),
|
|
||||||
('handed_over_date', models.DateField(blank=True, help_text='ItemModel.handed_over_date.help_text', null=True, verbose_name='ItemModel.handed_over_date.verbose_name')),
|
|
||||||
('handed_over_price', models.DecimalField(blank=True, decimal_places=2, help_text='ItemModel.handed_over_price.help_text', max_digits=6, null=True, verbose_name='ItemModel.handed_over_price.verbose_name')),
|
|
||||||
('kind', tagulous.models.fields.TagField(_set_tag_meta=True, force_lowercase=False, help_text='ItemModel.kind.help_text', max_count=3, to='inventory.Tagulous_ItemModel_kind', verbose_name='ItemModel.kind.verbose_name')),
|
|
||||||
('location', models.ForeignKey(blank=True, help_text='ItemModel.location.help_text', null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.LocationModel', verbose_name='ItemModel.location.verbose_name')),
|
|
||||||
('parent', models.ForeignKey(blank=True, help_text='ItemModel.parent.help_text', limit_choices_to={'parent_id': None}, null=True, on_delete=django.db.models.deletion.SET_NULL, to='inventory.ItemModel', verbose_name='ItemModel.parent.verbose_name')),
|
|
||||||
('producer', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, force_lowercase=False, help_text='ItemModel.producer.help_text', max_count=1, to='inventory.Tagulous_ItemModel_producer', verbose_name='ItemModel.producer.verbose_name')),
|
|
||||||
('tags', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, to='inventory.Tagulous_ItemModel_tags', verbose_name='BaseModel.tags.verbose_name')),
|
|
||||||
('user', models.ForeignKey(editable=False, help_text='BaseModel.user.help_text', on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='BaseModel.user.verbose_name')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'ItemModel.verbose_name',
|
|
||||||
'verbose_name_plural': 'ItemModel.verbose_name_plural',
|
|
||||||
},
|
|
||||||
),
|
|
||||||
migrations.CreateModel(
|
|
||||||
name='ItemLinkModel',
|
|
||||||
fields=[
|
|
||||||
('create_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.create_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.create_dt.verbose_name')),
|
|
||||||
('update_dt', models.DateTimeField(blank=True, editable=False, help_text='ModelTimetrackingMixin.update_dt.help_text', null=True, verbose_name='ModelTimetrackingMixin.update_dt.verbose_name')),
|
|
||||||
('id', models.UUIDField(default=uuid.uuid4, editable=False, help_text='BaseModel.id.help_text', primary_key=True, serialize=False, verbose_name='BaseModel.id.verbose_name')),
|
|
||||||
('name', models.CharField(blank=True, help_text='BaseLink.name.help_text', max_length=255, null=True, verbose_name='BaseLink.name.verbose_name')),
|
|
||||||
('url', models.URLField(help_text='Link.url.help_text', verbose_name='Link.url.verbose_name')),
|
|
||||||
('last_check', models.DateField(blank=True, editable=False, help_text='Link.url.help_text', null=True, verbose_name='Link.url.verbose_name')),
|
|
||||||
('status_code', models.PositiveSmallIntegerField(blank=True, editable=False, help_text='Link.status_code.help_text', null=True, verbose_name='Link.status_code.verbose_name')),
|
|
||||||
('page_title', models.CharField(blank=True, editable=False, help_text='Link.page_title.help_text', max_length=255, null=True, verbose_name='Link.page_title.verbose_name')),
|
|
||||||
('position', models.PositiveSmallIntegerField(default=0)),
|
|
||||||
('item', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='inventory.ItemModel')),
|
|
||||||
('tags', tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, to='inventory.Tagulous_ItemLinkModel_tags', verbose_name='BaseModel.tags.verbose_name')),
|
|
||||||
('user', models.ForeignKey(editable=False, help_text='BaseModel.user.help_text', on_delete=django.db.models.deletion.CASCADE, related_name='+', to=settings.AUTH_USER_MODEL, verbose_name='BaseModel.user.verbose_name')),
|
|
||||||
],
|
|
||||||
options={
|
|
||||||
'verbose_name': 'ItemLinkModel.verbose_name',
|
|
||||||
'verbose_name_plural': 'ItemLinkModel.verbose_name_plural',
|
|
||||||
'ordering': ('position',),
|
|
||||||
},
|
|
||||||
),
|
|
||||||
]
|
|
|
@ -1,39 +0,0 @@
|
||||||
# Generated by Django 2.2.16 on 2020-10-17 20:11
|
|
||||||
|
|
||||||
from django.db import migrations
|
|
||||||
import tagulous.models.fields
|
|
||||||
|
|
||||||
|
|
||||||
class Migration(migrations.Migration):
|
|
||||||
|
|
||||||
dependencies = [
|
|
||||||
('inventory', '0001_initial'),
|
|
||||||
]
|
|
||||||
|
|
||||||
operations = [
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='itemlinkmodel',
|
|
||||||
name='tags',
|
|
||||||
field=tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, case_sensitive=False, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, space_delimiter=False, to='inventory.Tagulous_ItemLinkModel_tags', verbose_name='BaseModel.tags.verbose_name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='itemmodel',
|
|
||||||
name='kind',
|
|
||||||
field=tagulous.models.fields.TagField(_set_tag_meta=True, case_sensitive=False, force_lowercase=False, help_text='ItemModel.kind.help_text', max_count=3, space_delimiter=False, to='inventory.Tagulous_ItemModel_kind', verbose_name='ItemModel.kind.verbose_name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='itemmodel',
|
|
||||||
name='producer',
|
|
||||||
field=tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, case_sensitive=False, force_lowercase=False, help_text='ItemModel.producer.help_text', max_count=1, space_delimiter=False, to='inventory.Tagulous_ItemModel_producer', verbose_name='ItemModel.producer.verbose_name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='itemmodel',
|
|
||||||
name='tags',
|
|
||||||
field=tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, case_sensitive=False, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, space_delimiter=False, to='inventory.Tagulous_ItemModel_tags', verbose_name='BaseModel.tags.verbose_name'),
|
|
||||||
),
|
|
||||||
migrations.AlterField(
|
|
||||||
model_name='locationmodel',
|
|
||||||
name='tags',
|
|
||||||
field=tagulous.models.fields.TagField(_set_tag_meta=True, blank=True, case_sensitive=False, force_lowercase=False, help_text='BaseModel.tags.help_text', max_count=10, space_delimiter=False, to='inventory.Tagulous_LocationModel_tags', verbose_name='BaseModel.tags.verbose_name'),
|
|
||||||
),
|
|
||||||
]
|
|
Some files were not shown because too many files have changed in this diff Show More
Ładowanie…
Reference in New Issue