我正在Django中制作一个“简单”的零件清单应用程序。
我以此为模型。
from django.db import models
# Create your models here.
class Site(models.Model):
create_date = models.DateField(auto_now_add=True)
name = models.TextField(max_length=150, null=False, unique=True, verbose_name="Site name")
update_date = models.DateField(auto_now=True)
def __str__(self):
return self.name
class Location(models.Model):
create_date = models.DateField(auto_now_add=True)
name = models.TextField(max_length=150, null=False, unique=False)
site = models.ForeignKey(Site, null=False, on_delete=models.PROTECT)
update_date = models.DateField(auto_now=True)
@property
def site_name(self):
try:
return self.site.name
except Exception as ex:
return 'Unknown'
def __str__(self):
return self.name
class Part(models.Model):
create_date = models.DateField(auto_now_add=True)
name = models.TextField(max_length=150, null=False, unique=True)
verbose_name = models.TextField(max_length=150, null=True)
update_date = models.DateField(auto_now=True)
def __str__(self):
return self.name
class PartLocation(models.Model):
create_date = models.DateField(auto_now_add=True)
location = models.ForeignKey(Location, null=False, on_delete=models.PROTECT)
number_of_parts = models.IntegerField(null=False)
part = models.ForeignKey(Part, null=False, on_delete=models.PROTECT)
update_date = models.DateField(auto_now=True)
@property
def site(self):
try:
return self.location.site.name
except Exception as ex:
return 'Unknown'
def __str__(self):
return f'{self.part.name}/{self.location.name}/{self.site}/{self.number_of_parts}'
我添加了一个看起来像这样的admin.py:
from django.contrib import admin
from .models import Location, Part, PartLocation, Site
class PartLocationAdmin(admin.ModelAdmin):
ordering = ('id', 'location', 'part', 'location__site__name', 'number_of_parts',)
list_display = ('id', 'part', 'get_part_verbose_name', 'location', 'site', 'number_of_parts',)
list_filter = ('id', 'part', 'location', 'location__site__name', 'number_of_parts',)
search_fields = ('id', 'part__name', 'location__name', 'location__site__name', 'number_of_parts',)
def get_part_verbose_name(self,obj):
if obj.part.verbose_name is None:
return "-"
return obj.part.verbose_name
get_part_verbose_name.command_order_field = 'Verbose name' #Allows column order sorting
get_part_verbose_name.short_description = 'Verbose name' #Renames column head
class LocationAdmin(admin.ModelAdmin):
ordering = ('id', 'name', 'site',)
list_display = ('id', 'name', 'site',)
search_fields = ('id', 'name', 'site__name',)
class PartAdmin(admin.ModelAdmin):
ordering = ('id', 'name', 'verbose_name')
list_display = ('id', 'name', 'verbose_name')
search_fields = ('id', 'name', 'verbose_name')
# Register your models here.
admin.site.register(Site)
admin.site.register(Location, LocationAdmin)
admin.site.register(Part, PartAdmin)
admin.site.register(PartLocation, PartLocationAdmin)
然后我在tests.py中添加了单元测试:
from django.test import TestCase, TransactionTestCase
import django.db.utils
from .models import Location, Part, PartLocation, Site
from django.db.models import ProtectedError
class ModelTestCases(TransactionTestCase):
def add_and_delete(self):
'''
In this test we will add a site, location, part and partlocation information into the database.
Then we will ensure that one cannot delete a site until all sub records have also been deleted.
:return:
'''
# Let's create a site.
site_1 = Site.objects.create(name='site_1')
# Let's demostrate that you cannot create a location without a cite.
try:
loc_1 = Location.objects.create(name='loc_1')
except django.db.utils.IntegrityError as ex:
self.assertEqual('null value in column "site_id" violates not-null constraint', ex.args[0].split('\n')[0])
# Create a Location at site_1
loc_1 = Location.objects.create(name='loc_1', site=site_1)
# Create a Part
part_1 = Part.objects.create(name='part_1', verbose_name='Part One')
# Let's add inventory or part_1 in loc_1.
part_loc_1 = PartLocation(location=loc_1, part=part_1, number_of_parts=5)
# Let's demostrate that one cannot remove site_1 because it has a location.
try:
site_1.delete()
self.fail('Deletion of site not prevented.')
except ProtectedError as ex:
pass
# Let's demostrate that one cannot remove loc_1 because it has a PartLocation record.
try:
loc_1.delete()
self.assertEqual(0, Location.objects.count())
self.fail('Deletion of location not prevented.')
except ProtectedError as ex:
pass
如果我转到管理面板中的“位置”列表,则会看到此信息...
...,然后单击“转到”按钮以删除所选位置,我看到以下内容:
这是我想要的行为。但是我的单元测试允许删除包含零件的位置并引发此错误。
AssertionError: Deletion of location not prevented.
为什么我的管理代码阻止删除,而我的单元测试没有阻止删除?
我的Django版本是:
django.VERSION
(2, 1, 7, 'final', 0)
答案 0 :(得分:0)
DOH!我总是犯这个错误!在我的单元测试中,我有这个:
part_loc_1 = PartLocation(location=loc_1, part=part_1, number_of_parts=5)
当我应该写这篇文章的时候:
part_loc_1 = PartLocation.objects.create(location=loc_1, part=part_1, number_of_parts=5)