Использование TastyPie для обновления поля ForeignKey до нуля - PullRequest
6 голосов
/ 14 марта 2012

Можно ли использовать TastyPie для обновления поля ForeignKey до None?

Смежный вопрос: tastypie не удалит ссылку на иностранный ключ во время PUT

Что у меня есть:

class SomeObject(models.Model):
    some_field = models.ForeignKey(SomeOtherObject, null=True)

(и, конечно, соответствующий класс ресурсов TastyPie, который отлично работает для обновления других полей)

Что я хочу:

Чтобы обновить some_field до None с помощью TastyPie.

Что я пробовал (в JavaScript):

$.put('/my/api/model/someobject/42/', { some_field: null });
$.put('/my/api/model/someobject/42/', { some_field: '/my/api/model/someotherobject/null/' });
$.put('/my/api/model/someobject/42/', { some_field: '' });
$.put('/my/api/model/someobject/42/', { some_field: 0 });
$.put('/my/api/model/someobject/42/', { some_field: false });

и так далее.Все это приводит к 404 или 400. Некоторые приводят к 204, но база данных не обновляется.

Считывая код в full_dehydrate(), кажется, что в настоящее время это может быть невозможно.

Я посмотрел последний код на github , и я не уверен, что это возможно.

Ответы [ 4 ]

9 голосов
/ 26 марта 2012

Вот общее решение. Создайте базовый ресурс и расширьте все остальные ресурсы из этого. Это взлом, но это работает.

class MyResource(ModelResource):
    def obj_update(self, bundle, request=None, **kwargs):
        for field_name in self.fields:
            field = self.fields[field_name]

            if type(field) is ToOneField and field.null and bundle.data[field_name] is None:
                setattr(bundle.obj, field_name, None)

        return super(MyResource, self).obj_update(bundle, **kwargs)
2 голосов
/ 14 февраля 2014

Просто добавьте гидратный метод для поля:

def hydrate_some_field(self, bundle):
    some_object = bundle.obj
    some_other_object = bundle.data['some_field']

    if some_other_object == '':
        some_object.some_field = None
        del bundle.data['some_field']

    return bundle

Удачи!

0 голосов
/ 09 октября 2014

Для меня ответ Адама Томаса не сработал. Я должен был изменить условие if.

Таким образом, общий код становится:

def obj_update(self, bundle, request=None, **kwargs):
    super(MyResource, self).obj_update(bundle, **kwargs)
    field_to_update=[]
    for field_name in self.fields:
        field = self.fields[field_name]
        if field.null and (field_name in request.POST):
            if request.POST[field_name] is u'':
                setattr(bundle.obj, field_name, None)
                field_to_update.append(field_name)
    bundle.obj.save(update_fields=field_to_update)
    return bundle

(обратите внимание: я использовал поле update_, чтобы сделать запрос sql более приятным:))

(кстати: это также работает для namespacedmodelresources:))

(я не мог заставить его работать с обратным супер вызовом, тогда он не сохранил для меня)

0 голосов
/ 16 марта 2012

Попробуйте это:

$.put('/my/api/model/someobject/42/', { some_field: 'None' }); //DOES NOT WORK

У меня была похожая проблема, когда я пытался отфильтровать некоторые объекты по пустому внешнему ключу и смог получить их с помощью GET:

http://localhost:8000/api/v1/page/?format=json&next_page=None

Обновление:

Хотя я смог получить совпадающие объекты, передав None, он не работает для PUT.Мне удалось обновить поле внешнего ключа до None с помощью этого вызова:

$.ajax('/api/v1/page/1/',{
    contentType: 'application/json', 
    type: 'put', 
    data: JSON.stringify({"next_page": null})
});

Я думаю, это обходит проблему, передавая ноль как application/json.Вероятно, можно передать ноль как application/x-www-form-urlencoded, но я не знаю как.

Между прочим, application/json - это кодировка, которую ожидает вкусная по умолчанию, тогда как application/x-www-form-urlencoded - это кодировка jquery, и некоторые другие (все?) Библиотеки используют для ajax.Может быть, с кодировкой json по умолчанию вкусная пиция легче работать.

...