我正在使用django-ajax-selects,这是一个免费提供的django应用程序,可提供jquery自动完成功能。
我已经完成了它 - 即它自动填充我想要的表单字段。但是我有一个问题......我在ModelForm中使用它,它将Partnership对象添加到数据库中:
class Skater(models.Model):
name = models.CharField(max_length=64)
surname = models.CharField(max_length=64)
gender = models.CharField(max_length=1, choices=GENDER_CHOICES)
class Partnership(models.Model):
female_partner = models.ForeignKey(Skater, limit_choices_to = {'gender': FEMALE}, related_name='female_partner_set')
male_partner = models.ForeignKey(Skater, limit_choices_to = {'gender': MALE}, related_name='male_partner_set')
我希望用户能够在female_partner和male_partner字段中输入名称和姓氏,即使这样的Skater对象不存在,我也希望创建该对象。我该怎么做呢?我不能将代码放在表单的save方法中,因为该字段不会验证(它不是有效的Skater)。
编辑1: 添加更多代码...
表格:
class PartnershipAddForm(forms.ModelForm):
female_partner = AutoCompleteSelectField('female_skater',required=True)
male_partner = AutoCompleteSelectField('male_skater',required=True)
class Meta:
model = Partnership
settings.py:
AJAX_LOOKUP_CHANNELS = {
'female_skater' : ('skaters.lookups', 'FemaleLookup'),
'male_skater' : ('skaters.lookups', 'MaleLookup'),
}
lookups.py(MaleLookup除了gender = MALE之外是相同的):
class FemaleLookup(object):
def get_query(self,q,request):
""" return a query set. you also have access to request.user if needed """
return Skater.objects.filter(Q(gender=FEMALE) & (Q(name__istartswith=q) | Q(surname__istartswith=q)))
def format_item(self,skater):
""" simple display of an object when it is displayed in the list of selected objects """
return unicode(skater)
def format_result(self,skater):
""" a more verbose display, used in the search results display. may contain html and multi-lines """
return "%s<br/>" % unicode(skater)
def get_objects(self,ids):
""" given a list of ids, return the objects ordered as you would like them on the admin page.
this is for displaying the currently selected items (in the case of a ManyToMany field)
"""
return Skater.objects.filter(pk__in=ids).order_by('name','surname')
答案 0 :(得分:3)
AutoCompleteSelectField保存对象的id而不是文本,这就是我一直有“必需”错误的原因(以及为什么Daniel的解决方案不起作用)。值变量为空,因为不存在的Skater没有id。
我不确定这是最好的方法,但我最终使用的是AutoCompleteField而不是AutoCompleteSelectField。 AutoCompleteField保存文本,但它不会为我创建Skater对象。
代码:
class PartnershipAddForm(forms.ModelForm):
female_partner = AutoCompleteField('female_skater',required=True)
male_partner = AutoCompleteField('male_skater',required=True)
class Meta:
model = Partnership
def save(self):
partners = [self.cleaned_data['female_partner'],
self.cleaned_data['male_partner']]
name = ['','']
surname = ['','']
for i in [0,1]:
name[i],surname[i] = get_name_surname(partners[i])
partners = [None,None]
partners_created = [None,None]
gender = [FEMALE,MALE]
for i in [0,1]:
partners[i],partners_created[i] = Skater.objects.get_or_create(
name=name[i],
surname=surname[i],
gender=gender[i]
)
partnership, created = Partnership.objects.get_or_create(
female_partner=partners[0],
male_partner=partners[1],
)
return partnership
答案 1 :(得分:2)
看起来您需要从ajax选择子类化AutoCompleteSelectField并覆盖其clean
方法。
def clean(self, value):
if value:
lookup = get_lookup(self.channel)
objs = lookup.get_objects( [value] )
if objs:
return objs[0]
else:
firstname, surname = value.split(" ")
gender = self.channel.split("_")[0]
new_skater = Skater(name=firstname, surname=surname, gender=gender)
return new_skater
else:
if self.required:
raise forms.ValidationError(self.error_messages['required'])
return None
答案 2 :(得分:0)
我们能看到你的表格是什么样的吗?我认为您需要覆盖ModelForm中的save()方法,因此首先保存female_partner和male_partner,然后保存表单实例(又名Parntership实例)。