Add ab-test

This commit is contained in:
Fam Zheng 2025-03-02 14:22:03 +00:00
parent 9e344b9920
commit a9c0b7c689
4 changed files with 117 additions and 1 deletions

View File

@ -20,3 +20,6 @@ class AuthTokenAdmin(admin.ModelAdmin):
admin.site.register(AuthToken, AuthTokenAdmin) admin.site.register(AuthToken, AuthTokenAdmin)
admin.site.register(GlobalConfig) admin.site.register(GlobalConfig)
admin.site.register(ABTest)
admin.site.register(ABTestSample)

View File

@ -414,3 +414,24 @@ class FrameLabel(models.Model):
def __str__(self): def __str__(self):
return self.oss_path return self.oss_path
class ABTest(models.Model):
name = models.CharField(max_length=128, verbose_name="名称", db_index=True, unique=True)
description = models.TextField(verbose_name="描述")
test_object = models.CharField(max_length=128, verbose_name="实验对象")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建日期")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新日期")
enabled = models.BooleanField(default=True, verbose_name="是否启用")
spec = models.TextField(verbose_name="实验配置")
def __str__(self):
return f"{self.name} {self.category}"
class ABTestSample(models.Model):
abtest = models.ForeignKey(ABTest, related_name="samples", on_delete=models.CASCADE)
data = models.TextField(verbose_name="实验数据")
create_time = models.DateTimeField(auto_now_add=True, verbose_name="创建日期")
update_time = models.DateTimeField(auto_now=True, verbose_name="更新日期")
def __str__(self):
return f"{self.pk} {self.abtest.name} {self.create_time}"

View File

@ -467,6 +467,24 @@ class CameraRuleResource(BaseResource):
schema['fields']['notes']['longtext'] = True schema['fields']['notes']['longtext'] = True
return schema return schema
class ABTestResource(BaseResource):
class Meta:
queryset = ABTest.objects.all().order_by('-pk')
resource_name = 'ab-test'
authorization = BaseAuthorization()
serializer = BaseSerializer()
auth_role = 'admin'
class ABTestSampleResource(BaseResource):
class Meta:
queryset = ABTestSample.objects.all().order_by('-pk')
resource_name = 'ab-test-sample'
authorization = BaseAuthorization()
serializer = BaseSerializer()
auth_role = 'admin'
for cls in BaseResource.__subclasses__(): for cls in BaseResource.__subclasses__():
v1_api.register(cls()) v1_api.register(cls())
@ -1887,3 +1905,37 @@ class LabelFrameView(BaseView):
'ok': True, 'ok': True,
'id': fo.id, 'id': fo.id,
}) })
class ABTestView(BaseView):
name = 'ab-test'
auth_check = None
def get(self, request):
test_object = request.GET.get('test_object', None)
abtest = ABTest.objects.filter(enabled=True)
if test_object:
abtest = abtest.filter(test_object=test_object)
return JsonResponse({
'items': [
{
'name': abtest.name,
'test_object': abtest.test_object,
'spec': abtest.spec,
}
for abtest in abtest
]
})
class ABTestReportView(BaseView):
name = 'ab-test-report'
auth_check = None
def post(self, request):
name = request.data.get('name')
abtest = ABTest.objects.filter(name=name).first()
if not abtest:
return http404()
sample = ABTestSample.objects.create(abtest=abtest, data=json.dumps(request.data.get('data')))
return JsonResponse({
'ok': True,
})

View File

@ -158,3 +158,43 @@ class APITest(TestCase):
) )
self.assertEqual(r.status_code, 200) self.assertEqual(r.status_code, 200)
self.assertIn('status', r.json()) self.assertIn('status', r.json())
def test_abtest(self):
r = self.get("/api/v1/ab-test/", admin=True)
self.assertEqual(r.status_code, 200)
self.assertIn('items', r.json())
self.assertEqual(len(r.json()['items']), 0)
spec = """
"""
ABTest.objects.create(name="test", test_object="dummy", spec=spec)
r = self.get("/api/v1/ab-test/", admin=True)
self.assertEqual(r.status_code, 200)
self.assertIn('items', r.json())
self.assertEqual(len(r.json()['items']), 1)
self.assertEqual(r.json()['items'][0]['name'], "test")
self.assertEqual(r.json()['items'][0]['test_object'], "dummy")
self.assertEqual(r.json()['items'][0]['spec'], spec)
r = self.get("/api/v1/ab-test/?test_object=dummy")
self.assertEqual(r.status_code, 200)
self.assertEqual(len(r.json()['items']), 1)
r = self.post("/api/v1/ab-test-report/", data={
'name': "test",
'data': {
'foo': "bar",
},
})
self.assertEqual(r.status_code, 200)
self.assertIn('ok', r.json())
self.assertTrue(r.json()['ok'])
abts = ABTestSample.objects.filter(abtest__name="test")
self.assertEqual(len(abts), 1)
self.assertEqual(abts[0].abtest.name, "test")
self.assertEqual(abts[0].data, json.dumps({
'foo': "bar",
}))