Приложение django-ajax-select: Как создать новый объект, если его еще нет в базе данных? - PullRequest
3 голосов
/ 25 января 2010

Я использую django-ajax-selects , которое является свободно доступным приложением django с функцией автозаполнения jquery.

У меня все работает - то есть автозаполнение полей формы, которое я хочу. Но у меня есть проблема ... Я использую его в ModelForm, который добавляет объекты партнерства в базу данных:

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 не существует, и я хочу, чтобы этот объект был создан. Как мне это сделать? Я не могу поместить код в метод сохранения формы, потому что поле не будет проверено (это не допустимый 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 такой же, за исключением того, что пол = 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')

Ответы [ 3 ]

3 голосов
/ 31 января 2010

AutoCompleteSelectField содержит идентификатор объекта, а не текст, именно поэтому у меня все время была ошибка "required" (и почему решение Дэниела не работает). Переменная value была пустой, поскольку Skater, который не существует, не имеет идентификатора.

Я не уверен, что это лучший способ сделать это, но в итоге я использовал 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
2 голосов
/ 30 января 2010

Похоже, вам нужно создать подкласс AutoCompleteSelectField из ajax-selects и переопределить его 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
0 голосов
/ 25 января 2010

Можем ли мы увидеть, как выглядит ваша форма? Я думаю, вам нужно что-то вроде переопределения метода save () в вашей ModelForm, чтобы он сначала сохранял female_partner и male_partner, а затем сохранял экземпляр формы (он же экземпляр Parntership).

...