I have 3 Models:
class FileType(models.Model):
name=models.CharField(max_length=128)
class ManagedFile(models.Model):
type = models.ForeignKey(FileType)
content = models.FileField(upload_to=path_maker)
class Tag(models.Model):
type = models.ForeignKey(FileType)
m_file = models.ForeignKey(ManagedFile)
def clean(self):
if self.m_file is None:
return
if self.type != self.m_file.type:
raise ValidationError("File type does not match Tag type")
When select an m_file for a tag, the m_files type MUST match the Tags type. This is all well and good, but the admin drop down for Tag.m_file shows files of all types, regardless of the Tag's type. This is Confusing to users.
There seem to me a number of ways to filter the drop down statically. So if I wanted to say that we will never let the user see Type.pk=1 in the dropdown, I can to that. But there does not seem to be a way to filter on m_file.Type == Self.Type
It is actually quite easy to create your admin form classes dynamically. Something like this should work:
def tagform_factory(filetype):
class TagForm(forms.ModelForm):
m_file = forms.ModelChoiceField(
queryset=ManagedFile.objects.filter(type=filetype)
)
return TagForm
class TagAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
if obj is not None and obj.type is not None:
kwargs['form'] = tagform_factory(obj.type)
return super(TagAdmin, self).get_form(request, obj, **kwargs)
Note that the get_form
method is responsible for building the form class, not the form instance. It is badly named, IMHO.
However, you still need to decide what to do for forms that are used to add new tags, rather than edit existing ones. In that case you do not yet have a type to which you can restrict the dropdown. Maybe there is actually a data modeling problem lurking here? Do you really need the type
field on the Tag
model? Maybe it should just be removed?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With