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