Обратное отношение "ToManyField" в tastypie и obj_create ошибке

109
15

У меня возникают проблемы с добавлением ресурсов, связанных с ApiKey User, проблема в том, что это именно "такси", когда я комментирую, что "create_object" работает нормально.
Существует ресурс


ресы


class LocationResource(ModelResource):
user = fields.ForeignKey(AccountResource, 'user', full=True)
taxi = fields.ToManyField(TaxiResource, attribute=lambda bundle: Taxi.objects.filter(user=bundle.obj.user), full=True, null=True)

class Meta:
queryset = Location.objects.all().order_by('-id')
resource_name = 'location'
list_allowed_methods = ['post', 'get']
authentication = ApiKeyAuthentication()
authorization = Authorization()
filtering = {'user': ALL_WITH_RELATIONS}

def obj_create(self, bundle, **kwargs):
if bundle.request.method == 'POST':
return super(LocationResource, self).obj_create(bundle, user=bundle.request.user)


Модели


from django.contrib.auth.models import User

class Taxi(models.Model):
STATUS_CHOICES = (
('Av', 'Available'),
('NA', 'Not Available'),
('Aw', 'Away'),
)
user = models.OneToOneField(User)
license_plate = models.TextField(u'Licence Plate',max_length=6,blank=True,null=True)
status = models.CharField(u'Status',max_length=2,choices=STATUS_CHOICES)
device = models.OneToOneField(Device, null=True)
def __unicode__(self):
return "Taxi %s for user %s" % (self.license_plate,self.user)

class Location(models.Model):
user = models.ForeignKey(User)
latitude = models.CharField(u'Latitude', max_length=25, blank=True, null=True)
longitude = models.CharField(u'Longitude', max_length=25, blank=True, null=True)
speed = models.CharField(u'Speed', max_length=25, blank=True, null=True)
timestamp = models.DateTimeField(auto_now_add=True)
def __unicode__(self):
return "(%s,%s) for user %s" % (self.latitude, self.longitude,self.user)


И ошибка при попытке создать некоторые ресурсы:


{"error_message": "'QuerySet' object has no attribute 'add'", "traceback": "Traceback (most recent call last):\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 217, in wrapper\n    response = callback(request, *args, **kwargs)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 459, in dispatch_list\n    return self.dispatch('list', request, **kwargs)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 491, in dispatch\n    response = method(request, **kwargs)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 1357, in post_list\n updated_bundle = self.obj_create(bundle, **self.remove_api_resource_names(kwargs))\n\n  File \"/Users/phantomis/Memoria/smartaxi_server/geolocation/api.py\", line 111, in obj_create\n    return super(LocationResource, self).obj_create(bundle, user=bundle.request.user)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 2150, in obj_create\n    return self.save(bundle)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 2301, in save\n    self.save_m2m(m2m_bundle)\n\n  File \"/Users/phantomis/Virtualenvs/django-memoria/lib/python2.7/site-packages/tastypie/resources.py\", line 2432, in save_m2m\n    related_mngr.add(*related_objs)\n\nAttributeError: 'QuerySet' object has no attribute 'add'\n"}

Я понятия не имею, что происходит, но обратная связь "такси" - большая проблема.

спросил(а) 2021-01-25T16:45:04+03:00 5 месяцев назад
1
Решение
77

Короткий ответ:


Поскольку поле такси не является реальным полем в местоположении, я бы добавил параметр "readonly = false" в поле вашего такси в определении LocationResource.


Кроме того, вы можете просто удалить поле такси и добавить его в метод обезвоживания


def dehydrate(self, bundle):
""" LocationResource dehydrate method.

Adds taxi urls
"""
taxi_resource = TaxiResource()
bundle.data['taxi'] = []

for taxi in Taxi.objects.filter(user=bundle.obj.user):
taxi_uri = taxi_resource.get_resource_uri(taxi)
bundle.data['taxi'].append(taxi_uri)

return bundle


Длинный ответ:


Проблема в том, что вы говорите, что у вашего LocationResource есть поле ToManyField, называемое такси. Так как это ModelResource, tastypie переведет, что ваша модель местоположения имеет поле такси типа ManyToManyField.


В django, когда вы создаете новое отношение в отношении ManyToMany, оно выполняется следующим образом:

location.taxis.add(taxi)

Теперь в настройке Ресурса вы разместили следующее:


taxi = fields.ToManyField(
TaxiResource,
attribute=lambda bundle: Taxi.objects.filter(user=bundle.obj.user),
full=True, null=True
)

Это означает, что когда tastypie пытается создать новый объект Location и вы заполните поле такси, он попытается сделать следующее:


Taxi.objects.filter(user=bundle.obj.unser).add(taxi)

Очевидно, что объект Queryset не имеет метода "add", поскольку это просто запрос, а не отношение ManyToMany.

ответил(а) 2021-01-25T16:45:04+03:00 5 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема