我正在尝试将Django管理员集成到接下来的三个相关模型中:
# models.py
class Seminar(models.Model):
title = models.CharField(max_length=128, unique=True)
start_date = models.DateField(db_index=True)
end_date = models.DateField(db_index=True)
class Event(models.Model):
title = models.CharField(max_length=128)
start_date = models.DateTimeField(db_index=True)
end_date = models.DateTimeField(db_index=True)
seminar = models.ForeignKey('Seminar')
class Registration(models.Model):
name = models.CharField(max_length=128)
first_name = models.CharField(max_length=128)
seminar = models.ForeignKey('Seminar')
events = models.ManyToManyField('Event', null=True)
# admin.py
class EventInline(admin.TabularInline):
model = Event
class SeminarAdmin(admin.ModelAdmin):
list_display = ('title', 'start_date', 'end_date')
inlines = [
EventInline,
]
class RegistrationAdmin(admin.ModelAdmin):
list_display = ('seminar', 'name', 'first_name')
正如您所看到的,每个研讨会可能有几个事件,从Seminar
管理员添加为内联条目。
我的问题在于注册,因为它们是:
当然,管理员列出了所有事件而不是与研讨会相关的子集,因此:
Registration
上的Event
M2M适当的还是我应该以不同的方式将这两个模型联系起来?谢谢!
答案 0 :(得分:1)
那么,在问这里之前,我通过使用不同的添加/更改视图表单,做了类似于Django的auth.User
模型的操作。我希望有一个更好的解决方案,显然不是。
所以这就是我所做的:
# models.py
class Registration(models.Model):
# [...] - add form excludes it, should allow blank on events field
events = models.ManyToManyField('Event', blank=True, null=True)
# admin.py
class RegistrationAdmin(admin.ModelAdmin):
change_form = RegistrationChangeForm
def get_form(self, request, obj=None, **kwargs):
defaults = {}
if obj is None:
defaults.update(exclude=('events',))
else:
defaults.update(form=self.change_form)
defaults.update(kwargs)
return super(RegistrationAdmin, self).get_form(request, obj, **defaults)
# forms.py
class RegistrationChangeForm(forms.ModelForm):
class Meta:
model = Registration
exclude = ('seminar',)
def __init__(self, *args, **kwargs):
super(RegistrationChangeForm, self).__init__(*args, **kwargs)
self.fields['events'].choices = Event.objects.filter(seminar=kwargs.get('instance').seminar).values_list('pk','title')
因此,在添加时我们只是忽略事件(注册是用无效事件保存的)然后,在更改时,可以根据先前定义的研讨会选择事件列表,然后忽略(因为我们无法重新加载)相关事件清单)。