【问题标题】:Django admin form - how to change select options dynamically?Django 管理表单 - 如何动态更改选择选项?
【发布时间】:2011-08-31 12:18:55
【问题描述】:

我有 2 个模型:

class City(models.Model):
    name = models.CharField(max_length=50)
    slug = models.SlugField(max_length=50)


class CityNews(models.Model):
    title = models.CharField(max_length=100)
    slug = models.SlugField(max_length=100)
    add_date = models.DateTimeField(auto_now=False, auto_now_add=True, editable=False)
    content = models.TextField()
    city = models.ForeignKey(City)

我的每个用户都与 1 个城市建立了联系。我希望他只向他所连接的城市添加新闻。但是超级管理员必须有可能向每个城市添加新闻。 如何更改 CityNews 中的“城市”字段,使其仅显示用户连接的城市?我可以编写自定义 ModelForm,但如何检查 user_city 并更改其查询集?

【问题讨论】:

  • 您不接受答案的原因是什么?只是想知道。
  • 不,我忘了 :)

标签: django django-admin django-forms


【解决方案1】:

这样做的一个明显方法是利用 ModelAdmin 上的 formfield_for_foreignkey() 方法。

所以如果你的 models.py 看起来像这样:

from django.db import models
from django.contrib.auth.models import User

class City(models.Model):
    name = models.CharField(max_length=50)

    def __unicode__(self):
        return self.name

class CityNews(models.Model):
    added_by = models.ForeignKey(User)
    city = models.ForeignKey(City)
    title = models.CharField(max_length=100)
    content = models.TextField()

class UserExtra(models.Model):
    user = models.ForeignKey(User)
    city = models.ForeignKey(City)

那么您的 admin.py 可能如下所示:

from django.contrib import admin
from formtesting.models import City, CityNews, UserExtra
from django.forms.models import ModelChoiceField
from django.contrib.auth.models import User

class CityAdmin(admin.ModelAdmin):
    pass

admin.site.register(City, CityAdmin)

class CityNewsAdmin(admin.ModelAdmin):
    def formfield_for_foreignkey(self, db_field, request, **kwargs):
        if db_field.name == "city":
            if request.user.is_superuser:
                queryset = City.objects.all()
            else:
                queryset = City.objects.filter(userextra__user=request.user)
            return ModelChoiceField(queryset, initial=request.user)
        elif db_field.name == "added_by":
            if request.user.is_superuser:
                queryset = User.objects.all()
            else:
                queryset = User.objects.filter(id=request.user.id)
            return ModelChoiceField(queryset, initial=request.user)
        else:
            return super(CityNewsAdmin, self).formfield_for_foreignkey(db_field, 
                                                              request, **kwargs)

admin.site.register(CityNews, CityNewsAdmin)

class UserExtraAdmin(admin.ModelAdmin):
    pass

admin.site.register(UserExtra, UserExtraAdmin)

【讨论】:

  • 效果很好,但它不会从模型返回 verbose_name。相反,它显示原始字段名称。你知道为什么吗?
  • 远离电脑,但尝试使用label作为ModelChoiceField的关键字arg?
  • 我使用了 label=base_class_db_field.verbose_name.capitalize(),它就像一个魅力
猜你喜欢
  • 2012-04-12
  • 2015-09-09
  • 2018-09-15
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 1970-01-01
  • 1970-01-01
  • 2014-10-28
相关资源
最近更新 更多