fix(MR-16): Use cache for FileField and ImageField (#17)

* Remove casting to list in _get_form_data

* Use cache for most fields and admin form for m2m files

* MR comments/clean up

* Cache should obey exclude and fields

* Some more tests and docs

* Only use cache for image files

* Even more tests and handle save as new

* fix test

* More tests

* minor refactor

* Improve test coverage

* Add no cover for some places

* V0.2.3.dev7

* Adding tests for fieldsets

* Added cache timeout

* Added another test for an edge case

* Fix issue with ManagementForm tampered with

* Update cache to only set when form is_multipart

* Even more testing changes

* Update based on comments on MR and clean up a bit

* make test names better

Co-authored-by: Thu Trang Pham <thu@joinmodernhealth.com>
This commit is contained in:
Thu Trang Pham
2021-02-27 15:39:01 -08:00
committed by GitHub
parent cc36492bfe
commit 06d3e1a208
31 changed files with 3017 additions and 116 deletions
-48
View File
@@ -1,48 +0,0 @@
from django.contrib import admin
from admin_confirm.admin import AdminConfirmMixin, confirm_action
from .models import Item, Inventory, Shop, ShoppingMall
class ItemAdmin(AdminConfirmMixin, admin.ModelAdmin):
list_display = ("name", "price", "currency")
confirm_change = True
class InventoryAdmin(AdminConfirmMixin, admin.ModelAdmin):
list_display = ("shop", "item", "quantity")
confirm_change = True
confirm_add = True
confirmation_fields = ["quantity"]
class ShopAdmin(AdminConfirmMixin, admin.ModelAdmin):
confirmation_fields = ["name"]
actions = ["show_message", "show_message_no_confirmation"]
@confirm_action
def show_message(modeladmin, request, queryset):
shops = ", ".join(shop.name for shop in queryset)
modeladmin.message_user(request, f"You selected with confirmation: {shops}")
show_message.allowed_permissions = ("delete",)
def show_message_no_confirmation(modeladmin, request, queryset):
shops = ", ".join(shop.name for shop in queryset)
modeladmin.message_user(request, f"You selected without confirmation: {shops}")
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
class ShoppingMallAdmin(AdminConfirmMixin, admin.ModelAdmin):
confirm_add = True
confirm_change = True
confirmation_fields = ["name"]
admin.site.register(Item, ItemAdmin)
admin.site.register(Inventory, InventoryAdmin)
admin.site.register(Shop, ShopAdmin)
admin.site.register(ShoppingMall, ShoppingMallAdmin)
+15
View File
@@ -0,0 +1,15 @@
from django.contrib import admin
from ..models import GeneralManager, Item, Inventory, Shop, ShoppingMall
from .item_admin import ItemAdmin
from .inventory_admin import InventoryAdmin
from .shop_admin import ShopAdmin
from .shoppingmall_admin import ShoppingMallAdmin
from .generalmanager_admin import GeneralManagerAdmin
admin.site.register(Item, ItemAdmin)
admin.site.register(Inventory, InventoryAdmin)
admin.site.register(Shop, ShopAdmin)
admin.site.register(ShoppingMall, ShoppingMallAdmin)
admin.site.register(GeneralManager, GeneralManagerAdmin)
@@ -0,0 +1,5 @@
from django.contrib.admin import ModelAdmin
class GeneralManagerAdmin(ModelAdmin):
save_as = True
+10
View File
@@ -0,0 +1,10 @@
from django.contrib.admin import ModelAdmin
from admin_confirm.admin import AdminConfirmMixin
class InventoryAdmin(AdminConfirmMixin, ModelAdmin):
list_display = ("shop", "item", "quantity")
confirm_change = True
confirm_add = True
confirmation_fields = ["quantity"]
+28
View File
@@ -0,0 +1,28 @@
from django.contrib.admin import ModelAdmin
from django.utils.safestring import mark_safe
from admin_confirm.admin import AdminConfirmMixin
class ItemAdmin(AdminConfirmMixin, ModelAdmin):
confirm_change = True
confirm_add = True
confirmation_fields = ["price"]
list_display = ("name", "price", "currency")
readonly_fields = ["image_preview"]
save_as = True
save_as_continue = False
def image_preview(self, obj):
if obj.image:
return mark_safe('<img src="{obj.image.url}" />')
# def one(self, obj):
# return "Read Only"
# def two(self, obj):
# return "Read Only"
# def three(self, obj):
# return "Read Only"
+21
View File
@@ -0,0 +1,21 @@
from django.contrib.admin import ModelAdmin
from admin_confirm.admin import AdminConfirmMixin, confirm_action
class ShopAdmin(AdminConfirmMixin, ModelAdmin):
confirmation_fields = ["name"]
actions = ["show_message", "show_message_no_confirmation"]
@confirm_action
def show_message(modeladmin, request, queryset):
shops = ", ".join(shop.name for shop in queryset)
modeladmin.message_user(request, f"You selected with confirmation: {shops}")
show_message.allowed_permissions = ("delete",)
def show_message_no_confirmation(modeladmin, request, queryset):
shops = ", ".join(shop.name for shop in queryset)
modeladmin.message_user(request, f"You selected without confirmation: {shops}")
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
+16
View File
@@ -0,0 +1,16 @@
from ..models import ShoppingMall
from django.contrib.admin import ModelAdmin
from django.contrib.admin.options import StackedInline
from admin_confirm.admin import AdminConfirmMixin
class ShopInline(StackedInline):
model = ShoppingMall.shops.through
class ShoppingMallAdmin(AdminConfirmMixin, ModelAdmin):
confirm_add = True
confirm_change = True
confirmation_fields = ["name"]
inlines = [ShopInline]
@@ -0,0 +1,48 @@
# Generated by Django 3.1.6 on 2021-02-22 03:12
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('market', '0005_shoppingmall'),
]
operations = [
migrations.CreateModel(
name='GeneralManager',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=120)),
],
),
migrations.CreateModel(
name='Town',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('name', models.CharField(max_length=120)),
],
),
migrations.AddField(
model_name='item',
name='file',
field=models.FileField(blank=True, null=True, upload_to='tmp/files'),
),
migrations.AddField(
model_name='item',
name='image',
field=models.ImageField(blank=True, null=True, upload_to='tmp/items'),
),
migrations.AddField(
model_name='shoppingmall',
name='general_manager',
field=models.OneToOneField(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='market.generalmanager'),
),
migrations.AddField(
model_name='shoppingmall',
name='town',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, to='market.town'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 3.1.6 on 2021-02-24 01:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('market', '0006_auto_20210222_0312'),
]
operations = [
migrations.AddField(
model_name='generalmanager',
name='headshot',
field=models.ImageField(blank=True, null=True, upload_to='tmp/gm/headshots'),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 3.1.6 on 2021-02-24 08:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('market', '0007_generalmanager_headshot'),
]
operations = [
migrations.AddField(
model_name='item',
name='description',
field=models.TextField(blank=True, null=True),
),
]
+17 -1
View File
@@ -9,6 +9,9 @@ class Item(models.Model):
name = models.CharField(max_length=120)
price = models.DecimalField(max_digits=5, decimal_places=2)
currency = models.CharField(max_length=3, choices=VALID_CURRENCIES)
image = models.ImageField(upload_to="tmp/items", null=True, blank=True)
file = models.FileField(upload_to="tmp/files", null=True, blank=True)
description = models.TextField(null=True, blank=True)
def __str__(self):
return self.name
@@ -18,7 +21,7 @@ class Shop(models.Model):
name = models.CharField(max_length=120)
def __str__(self):
return self.name
return str(self.name)
class Inventory(models.Model):
@@ -35,9 +38,22 @@ class Inventory(models.Model):
notes = models.TextField(default="This is the default", null=True, blank=True)
class GeneralManager(models.Model):
name = models.CharField(max_length=120)
headshot = models.ImageField(upload_to="tmp/gm/headshots", null=True, blank=True)
class Town(models.Model):
name = models.CharField(max_length=120)
class ShoppingMall(models.Model):
name = models.CharField(max_length=120)
shops = models.ManyToManyField(Shop)
general_manager = models.OneToOneField(
GeneralManager, on_delete=models.CASCADE, null=True, blank=True
)
town = models.ForeignKey(Town, on_delete=models.CASCADE, null=True, blank=True)
def __str__(self):
return self.name