2011-05-23 28 views
5

我有2种型号:Django的管理表单 - 如何动态地改变选择选项?

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个城市相连。我希望他只能向他所联系的城市添加新闻。但superadmin必须有可能向每个城市添加新闻。 如何更改CityNews中的“城市”字段,它们只显示用户所连接的城市?我可以编写自定义的ModelForm,但我如何检查user_city并更改其查询集?

+0

有,你没有接受答案的理由?就是想。 – 2011-06-01 21:09:20

+0

不,我忘了:) – robos85 2011-06-02 21:15:13

回答

9

这样做的一个显而易见的方法是在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) 
+0

它很好用,但它不会从模型中返回verbose_name。相反,它会显示otiginal字段名称。你知道为什么吗? – robos85 2011-05-27 20:28:32

+0

远离计算机,但尝试将标签用作ModelChoiceField的关键字arg? – 2011-05-27 21:52:24

+0

我使用了label = base_class_db_field.verbose_name.capitalize(),它像一个魅力 – robos85 2011-05-28 12:54:19