Django管理员在编辑/创建特定模型时挂起(直到超时错误)

38 投票
4 回答
11471 浏览
提问于 2025-04-16 16:46

这件事让我很头疼。之前没有出现过这种情况(我甚至还为用户手册做了截图,因为客户要求)。

我最开始在生产服务器上发现这个问题,然后检查了一下,发现开发服务器上也有这个问题。这个模型在Django的管理后台主页面上显示,我可以点击它,看到销售点的列表。但是当我想编辑一个已有的实例或者创建一个新的实例时,就出现问题了。

我只需点击链接(或者在地址栏输入),结果页面就卡住了。

class PointOfSaleAdmin(admin.ModelAdmin):
    list_display = ('id','business', 'user', 'zipcode', 'address','date_registered')
    list_filter = ('business',)
    filter_horizontal = ('services',)
admin.site.register(models.PointOfSale, PointOfSaleAdmin)

这是模型的注册代码。所有模型都在管理应用中注册,而用来测试的用户是超级用户。这个模型是:

class PointOfSale(models.Model):
    user = models.ForeignKey(User)
    zipcode = models.ForeignKey(Zipcode)
    business = models.ForeignKey(Business)
    services = models.ManyToManyField(Service, 
        verbose_name='available services')
    date_registered = models.DateField(auto_now_add=True)
    address = models.CharField(max_length=300)

还有一些方法,应该不太影响这个问题。而且上次我测试管理后台是在创建这些方法之后,所以这应该不是问题所在。

管理员很少需要访问这个页面。通常只是列出销售点,但这让我很困扰。有没有人知道为什么会卡住?其他模型都运行得很好。

这个问题在Django 1.2.5和1.3上都存在。

编辑:

我修改了超时限制。现在是可以工作的,但似乎需要几分钟才能完成。所以,后台有些东西在拖慢速度。我不明白为什么只对这个模型出现这种情况,而且在不同的环境下(数据集也很小)都一样。


我几乎想给自己一巴掌。真是因为太久没睡觉了,才犯的错。

问题是邮政编码的列表非常大(有几万条),而外键字段是以HTML选择框的形式加载,这意味着它会加载每一条记录。这就是数据量太大的问题。

现在我在想如何控制外键在管理后台的显示方式。有没有人能帮忙解决这个问题?

4 个回答

6

对于仍然在这个页面上的朋友们:正如Mamsaac在他的原帖中提到的,超时发生是因为Django试图将所有的ForeignKey实例加载到一个HTML下拉框中。Django 2允许你添加一个自动完成字段,这样你就可以异步搜索ForeignKey,来解决这个问题。在你的admin.py文件中,可以这样做:

from django.contrib import admin
from .models import Parent, Child

@admin.register(Parent)
class ParentAdmin(admin.ModelAdmin):
    # tell admin to autocomplete-select the "Parent"-field 'children'
    autocomplete_fields = ['children']

@admin.register(Child)
class ChildAdmin(admin.ModelAdmin):
    # when using an autocomplete to find a child, search in the field 'name'
    search_fields = ['name']      
10

我想补充一点,这里还有一个选项,就是创建一个 read_only_fields 列表。在某些情况下,比如说你有一个和模型相关的字段,这个字段有很多选择(在我的例子中,是一个记录很多用户和讨论主题之间标记的关系表),但你并不需要编辑这个字段。你可以把它添加到 read_only_fields 列表中,这样它就只会显示值,而不是所有的选择。

class FlaggedCommentsAdmin(ModelAdmin):
    list_display = ('user', 'discussion', 'flagged_on')
    readonly_fields = ('user', 'discussion')
46

在你的 admin.py 文件中,在合适的管理类下面,设置

raw_id_fields = ('zipcode',)

这样做会让你看到邮政编码的主键,而不是一个下拉菜单。

你为什么要把邮政编码单独设置成一个模型,而不是用一个字符字段或者一个真正的邮政编码 模型字段 呢?

撰写回答