Setting a preferred item of a many-to-one in Django
I'm trying to create a Django model that handles the following:
- An
Item
can have severalName
s. - One of the
Name
s for anItem
is its primaryName
, i.e. theName
displayed given anItem
.
(The model names were changed to protect the innocent.)
The models.py
I've got looks like:开发者_如何转开发
class Item(models.Model):
primaryName = models.OneToOneField("Name", verbose_name="Primary Name",
related_name="_unused")
def __unicode__(self):
return self.primaryName.name
class Name(models.Model):
item = models.ForeignKey(Item)
name = models.CharField(max_length=32, unique=True)
def __unicode__(self):
return self.name
class Meta: ordering = [ 'name' ]
The admin.py
looks like:
class NameInline(admin.TabularInline):
model = Name
class ItemAdmin(admin.ModelAdmin):
inlines = [ NameInline ]
admin.site.register(Item, ItemAdmin)
It looks like the database schema is working fine, but I'm having trouble with the admin, so I'm not sure of anything at this point. My main questions are:
- How do I explain to the admin that
primaryName
needs to be one of theName
s of the item being edited? - Is there a way to automatically set
primaryName
to the firstName
found, ifprimaryName
is not set, since I'm using inline admin for the names?
EDIT: Dang, I forgot this was still open. Anyway, I wound up redoing the model, replacing primaryName
with just name (a CharField
) in Item
and renaming Name
to Alias
. This can't do what I wanted to (just search one table for a name), but I couldn't make the primaryName
work if it didn't have null=True
, since Item
gets saved before any Name
s were created, meaning that any attempt to auto-assign a Name
would see an empty QuerySet
and fail.
The only way I could see it working was to have Name
's save routine auto-set itself as its parent's primaryName
if primaryName
was NULL
, which just didn't sit well with me.
i think you will want to take a look here.
http://docs.djangoproject.com/en/dev/ref/contrib/admin/#adding-custom-validation-to-the-admin
define your own form to take care of any custom validation that might be required.
- How do I explain to the admin that primaryName needs to be one of the Names of the item being edited?
Check out formfield_for_foreignkey()
in the ModelAdmin docs.
class ItemAdmin(admin.ModelAdmin):
def formfield_for_foreignkey(self, db_field, request, **kwargs):
if db_field.name == "primaryName":
# tweak the filter to your liking.
kwargs["queryset"] = Name.objects.filter(item=...)
return db_field.formfield(**kwargs)
return super(ItemAdmin, self).formfield_for_foreignkey(db_field, request, **kwargs)
- Is there a way to automatically set primaryName to the first Name found, if primaryName is not set, since I'm using inline admin for the names?
You could do this in your model's save
method, something like:
class Item(models.Model):
...(snip)...
def save(self,force_insert=False,force_update=False):
if self.primaryName is None:
self.primaryName = self.name_set.all()[0]
# will want to handle the case that no names are set, etc
super(Item,self).save(force_insert,force_update)
精彩评论