Django ORM DateTimeField ExpressionWrapper QuerySet annotation - django

According to the Django documentation here: https://docs.djangoproject.com/en/2.1/ref/models/expressions/#using-f-with-annotations
I can do date calculations using ExpressionWrapper. I tried to use it like this:
sprints = Sprint.objects.annotate(
duration=models.Case(
models.When(
Q(started__isnull=False) &
Q(done__isnull=False),
then=models.Value(
models.ExpressionWrapper(
(models.F('done') - models.F('started')),
output_field=models.DateTimeField()
))
),
models.When(
Q(started__isnull=False) &
Q(done__isnull=True),
then=models.Value(
models.ExpressionWrapper(
(Now() - models.F('started')),
output_field=models.DateTimeField(),
))
),
output_field=models.DateTimeField()
)).values_list('name',
'planned',
'started',
'done',
'duration')
But I get an error from pytz trying to do auto-localisation on the ExpressionWrapper:
Traceback (most recent call last):
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/rest_framework/viewsets.py", line 103, in view
return self.dispatch(request, *args, **kwargs)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/rest_framework/views.py", line 483, in dispatch
response = self.handle_exception(exc)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/rest_framework/views.py", line 443, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/rest_framework/views.py", line 480, in dispatch
response = handler(request, *args, **kwargs)
File "/home/phirt/src/core3/src/backend/portal/views/api/transformation.py", line 766, in get_sprint_data_csv
for sprint in sprints:
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/db/models/query.py", line 272, in __iter__
self._fetch_all()
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/db/models/query.py", line 1179, in _fetch_all
self._result_cache = list(self._iterable_class(self))
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/db/models/sql/compiler.py", line 1011, in apply_converters
value = converter(value, expression, connection)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/db/backends/mysql/operations.py", line 247, in convert_datetimefield_value
value = timezone.make_aware(value, self.connection.timezone)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/django/utils/timezone.py", line 269, in make_aware
return timezone.localize(value, is_dst=is_dst)
File "/home/phirt/local/venv/core3/lib/python3.6/site-packages/pytz/__init__.py", line 226, in localize
if dt.tzinfo is not None:
AttributeError: 'str' object has no attribute 'tzinfo'
And indeed the dt parameter passed to localize in pytz is a string, and it's exactly my ExpressionWrapper expression: ExpressionWrapper(F(done) - F(started))
How can I make this work?
Edit: Here is the sprint model:
class Sprint(BaseModel):
name = models.CharField(max_length=100)
planned = models.DateTimeField(null=True, blank=True)
started = models.DateTimeField(null=True, blank=True)
done = models.DateTimeField(null=True, blank=True)
state = models.CharField(max_length=20, verbose_name='State')
start_planned = models.DateTimeField(blank=True, null=True,
verbose_name='Start Planned')
start_latest = models.DateTimeField(blank=True, null=True,
verbose_name='Start Latest')
enforce_start = models.BooleanField(default=False,
verbose_name='Enforce Start')
class Meta:
ordering = ["name"]
verbose_name = "Sprint"
def __str__(self):
return f'<Sprint name="{self.name}">'

I have made it work by changing the query annotation to the following:
sprints = Sprint.objects.annotate(
duration=models.Case(
models.When(
Q(started__isnull=False) &
Q(done__isnull=False),
then=(models.F('done') - models.F('started')),
),
models.When(
Q(started__isnull=False) &
Q(done__isnull=True),
then=(Now() - models.F('started')),
),
output_field=models.DurationField()
)).values_list('name',
'planned',
'started',
'done',
'duration')

Related

Django invalid literal for int() with save_m2m

I try to integrate vue tags input http://www.vue-tags-input.com/#/ with my project.
Autocomplete works fine, form also. When I save the form, everything except the category(tags) is saved.
I know that with many to many relationship I have to use save_m2m in view, but when I do this, error appear:
invalid literal for int() with base 10: 'e'
My view:
#login_required
def save_embed(request):
interests = RecipeCategory.objects.all()
if request.method == "POST":
form = AddEmbed(request.POST)
if form.is_valid():
new_embed = form.save(commit=False)
new_embed.added_by = request.user
new_embed.save()
form.save_m2m()
else:
form = AddEmbed()
return render(request, 'embed/embedadd.html', {'form': form,
'interests': interests})
Model:
class Embed(models.Model, Activity):
url = models.URLField(max_length=255, verbose_name='Adres przepisu')
title = models.CharField(max_length=255, verbose_name='Tytuł')
description = models.TextField(verbose_name='Opis', blank=True, null=True)
type = models.CharField(blank=True, max_length=200)
thumbnail_url = models.URLField(max_length=255, blank=True, null=True)
image = models.ImageField(upload_to='recipes', blank=True)
html = models.TextField()
votes = GenericRelation(LikeDislike, related_query_name='embedlikes')
added_by = models.ForeignKey(User, on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
category = TreeManyToManyField(RecipeCategory, blank=True, null=True, related_name='embeds', verbose_name='Kategoria')
slug = AutoSlugField(populate_from='title', unique=True)
Edit - Form
class AddEmbed(ModelForm):
url = forms.URLField(label='Adres przepisu', widget=forms.URLInput(attrs={'v-model': 'embed.url', '#paste':'paste', '#input':'input'}))
title = forms.CharField(widget=forms.HiddenInput(attrs={':value':'embedsinfo.title'}))
description = forms.CharField(widget=forms.HiddenInput(attrs={':value':'embedsinfo.description'}))
thumbnail_url = forms.CharField(widget=forms.HiddenInput(attrs={':value':'embedsinfo.thumbnail_url'}))
html = forms.CharField(widget=forms.HiddenInput(attrs={':value':'embedsinfo.html'}))
category = forms.CharField(widget=forms.HiddenInput(attrs={':value': 'tags'}))
class Meta:
model = Embed
fields = ['url','title', 'description', 'thumbnail_url', 'html', 'category']
Traceback:
Traceback (most recent call last):
File "/data/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/data/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/data/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/data/lib/python3.6/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
return view_func(request, *args, **kwargs)
File "/app/recipes/views.py", line 39, in save_embed
form.save_m2m()
File "/data/lib/python3.6/site-packages/django/forms/models.py", line 441, in _save_m2m
f.save_form_data(self.instance, cleaned_data[f.name])
File "/data/lib/python3.6/site-packages/django/db/models/fields/related.py", line 1621, in save_form_data
getattr(instance, self.attname).set(data)
File "/data/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 997, in set
self.add(*new_objs, through_defaults=through_defaults)
File "/data/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 938, in add
through_defaults=through_defaults,
File "/data/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1065, in _add_items
'%s__in' % target_field_name: new_ids,
File "/data/lib/python3.6/site-packages/django/db/models/query.py", line 892, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/data/lib/python3.6/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/data/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1290, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/data/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1318, in _add_q
split_subq=split_subq, simple_col=simple_col,
File "/data/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1251, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/data/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1116, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/data/lib/python3.6/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "/data/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in get_prep_lookup
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/data/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in <listcomp>
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/data/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 972, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'e'
[21/Jun/2020 13:20:22] "POST /recipes/recipe/embed/add/ HTTP/1.1" 500 151931

ValueError: invalid literal for int() with base 10: 'A' while updating M2M

I am trying to update a ManyToMany field in django while doing this I am getting the following error :
Traceback (most recent call last):
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/core/handlers/base.py", line 115, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/core/handlers/base.py", line 113, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/views/generic/base.py", line 71, in view
return self.dispatch(request, *args, **kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/rest_framework/views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/rest_framework/views.py", line 455, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/rest_framework/views.py", line 492, in dispatch
response = handler(request, *args, **kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/rest_framework/decorators.py", line 55, in handler
return func(*args, **kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/tutorialdb/api/views.py", line 94, in tutorials
updateDB.tags.add(t)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 938, in add
through_defaults=through_defaults,
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1065, in _add_items
'%s__in' % target_field_name: new_ids,
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/query.py", line 892, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/query.py", line 910, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1290, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1318, in _add_q
split_subq=split_subq, simple_col=simple_col,
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1251, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1116, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/lookups.py", line 20, in __init__
self.rhs = self.get_prep_lookup()
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in get_prep_lookup
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in <listcomp>
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/home/bhupesh/Desktop/tutorialdb-test/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 966, in get_prep_value
return int(value)
ValueError: invalid literal for int() with base 10: 'A'
Here is my models.py
class tag(models.Model):
name = models.CharField(max_length=100)
created_date = models.DateTimeField(default=timezone.now)
description = models.TextField(blank=True)
def __str__(self):
return self.name
class tutorial(models.Model):
title = models.CharField(max_length=200)
link = models.URLField()
tags = models.ManyToManyField(tag)
category = models.CharField(max_length=200, choices = TUTORIAL_CATEGORIES)
created_date = models.DateTimeField(default=timezone.now)
#cached_property
def __str__(self):
return self.title
I am actually generating title & tags from a custom script that's why the serialzer is incomplete.
I am trying to send the following JSON data :
{
"link":"https://youtu.be/DHvMXvCVQVA",
"category":"video"
}
views.py
#api_view(['GET', 'POST'])
def tutorials(request):
"""
get: Returns all tutorials
post: POST a tutorial
"""
if request.method == 'GET':
tutorials = tutorial.objects.all()
serializer = tutorialSerializer(tutorials, many=True)
return JSONResponse(serializer.data)
elif request.method == 'POST':
postserializer = tutorialPOST(data = request.data)
if postserializer.is_valid():
title, tags = generateTags(request.data['link'])
print(title)
print(tags)
updateDB = tutorial.objects.create(
title = title,
link = request.data['link'],
category = request.data['category'],
created_date = timezone.now
)
for t in tags:
updateDB.tags.set(t)
return JSONResponse({"message " : "submitted" }, status=status.HTTP_202_ACCEPTED)
return JSONResponse({"message":"not_valid"})
Here is serializer.py
class tutorialPOST(serializers.Serializer):
class Meta:
model = tutorial
fields = ('link', 'category')
From what I know it's happening because of the following line in views.py
updateDB.tags.add(t)
You should call timezone.now method, instead of passing the method itself:
updateDB = tutorial.objects.create(
title = title,
link = request.data['link'],
category = request.data['category'],
created_date = timezone.now()
)
You have default value of created_date set correctly:
created_date = models.DateTimeField(default=timezone.now)
so it will be autofilled automatically for you:
updateDB = tutorial.objects.create(
title = title,
link = request.data['link'],
category = request.data['category']
)
Your date fields are giving errors. Just remove all their attributes and add "auto_now=True,auto_now_add=True" to date fields.

Source in Meta.extra_kwargs do not add to fields

I have few django models:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
phone = models.CharField(
_('phone number'), max_length=16,
unique=True, blank=True, null=True,
default=None, validators=[phone_validator]
)
...
class UserExtension(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
class Meta:
abstract = True
class Worker(UserExtension):
# some fields
class Administrator(UserExtension):
# some fields
View:
class AdministratorListView(ListAPIView):
permission_classes = (AllowAny,)
queryset = Administrator.objects.all()
serializer_class = serializers.AdministratorSerializer
And serializer:
class AdministratorSerializer(serializers.ModelSerializer):
class Meta:
model = Administrator
fields = ('network', 'email')
extra_kwargs = {'email': {'source': 'user.email'}}
But this is not working. Following traceback tell about field does not exist for my model:
Traceback (most recent call last):
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 34, in inner
response = get_response(request)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/core/handlers/base.py", line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/views/generic/base.py", line 68, in view
return self.dispatch(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 495, in dispatch
response = self.handle_exception(exc)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 455, in handle_exception
self.raise_uncaught_exception(exc)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/views.py", line 492, in dispatch
response = handler(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/generics.py", line 201, in get
return self.list(request, *args, **kwargs)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/mixins.py", line 48, in list
return Response(serializer.data)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 765, in data
ret = super(ListSerializer, self).data
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 262, in data
self._data = self.to_representation(self.instance)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 683, in to_representation
self.child.to_representation(item) for item in iterable
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 683, in <listcomp>
self.child.to_representation(item) for item in iterable
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 510, in to_representation
fields = self._readable_fields
File "/home/vagrant/v_env/lib/python3.6/site-packages/django/utils/functional.py", line 37, in __get__
res = instance.__dict__[self.name] = self.func(instance)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 376, in _readable_fields
field for field in self.fields.values()
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 363, in fields
for key, value in self.get_fields().items():
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1047, in get_fields
source, info, model, depth
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1192, in build_field
return self.build_unknown_field(field_name, model_class)
File "/home/vagrant/v_env/lib/python3.6/site-packages/rest_framework/serializers.py", line 1304, in build_unknown_field
(field_name, model_class.__name__)
django.core.exceptions.ImproperlyConfigured: Field name `user.email` is not valid for model `Administrator`.
I looked at the source code and realized that the value from 'source' is passed to build_field as field_name argument and rest-framework simply cannot find this field ('user.email') in my model (Administrator)
part of get_fields method
build_field method

django ManyToMany relationship adding objects throws error

I've a UserAnalytics object which has a one-to-one relationship with an User.
class UserAnalytics(models.Model):
user = models.ForeignKey(User, related_name='analytics', on_delete=models.CASCADE, null=True)
uptime = models.IntegerField(null=True)
feeds_viewed = models.IntegerField(null=True)
feeds_shared = models.IntegerField(null=True)
I've a Feed object which has a ManyToMany relationship with the UserAnalytics object.
class Feed(Base):
headline = models.CharField(max_length=255)
link = models.CharField(max_length=255, unique=True)
summary = models.TextField()
thumbnail = models.CharField(max_length=512, null=True)
published_date = models.DateTimeField()
views = models.IntegerField(default=0)
shares = models.IntegerField(default=0)
source = models.ForeignKey(Source, on_delete=models.CASCADE, null=True)
reader = models.ManyToManyField(User, through='Bookmark')
viewers = models.ManyToManyField(UserAnalytics)
When I try to add a feed to a UserAnalytics, using this code,
class ReadFeed(views.APIView):
def get(self, request, **kwargs):
try:
user = User.objects.get(id=kwargs.get('user_id'))
analytics = UserAnalytics.objects.get(id=user.id)
except User.DoesNotExist:
return Response({"Error": "User does not exist"}, status=status.HTTP_404_NOT_FOUND)
try:
feed = Feed.objects.get(id=kwargs.get('feed_id'))
feed.views += 1
feed.viewers.add(analytics)
feed.save()
user.analytics.add(feed)
user.analytics.save()
return Response(FeedSerializer(feed).data, status=status.HTTP_200_OK)
except Feed.DoesNotExist:
return Response({"Error": "Feed does not exist"}, status=status.HTTP_404_NOT_FOUND)
This the error that I get,
Traceback (most recent call last):
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/core/handlers/exception.py", line 35, in inner
response = get_response(request)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 128, in _get_response
response = self.process_exception_by_middleware(e, request)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/core/handlers/base.py", line 126, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/views/decorators/csrf.py", line 54, in wrapped_view
return view_func(*args, **kwargs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/views/generic/base.py", line 69, in view
return self.dispatch(request, *args, **kwargs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/rest_framework/views.py", line 494, in dispatch
response = self.handle_exception(exc)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/rest_framework/views.py", line 454, in handle_exception
self.raise_uncaught_exception(exc)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/rest_framework/views.py", line 491, in dispatch
response = handler(request, *args, **kwargs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/aggregator/api.py", line 28, in get
feed.viewers.add(user.analytics)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 898, in add
self._add_items(self.source_field_name, self.target_field_name, *objs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/fields/related_descriptors.py", line 1045, in _add_items
'%s__in' % target_field_name: new_ids,
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/query.py", line 836, in filter
return self._filter_or_exclude(False, *args, **kwargs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/query.py", line 854, in _filter_or_exclude
clone.query.add_q(Q(*args, **kwargs))
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1253, in add_q
clause, _ = self._add_q(q_object, self.used_aliases)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1277, in _add_q
split_subq=split_subq,
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1215, in build_filter
condition = self.build_lookup(lookups, col, value)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/sql/query.py", line 1085, in build_lookup
lookup = lookup_class(lhs, rhs)
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/lookups.py", line 18, in __init__
self.rhs = self.get_prep_lookup()
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in get_prep_lookup
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/fields/related_lookups.py", line 59, in <listcomp>
self.rhs = [target_field.get_prep_value(v) for v in self.rhs]
File "/Users/mstewart/Dropbox/xdrive/ftb/ftb_core_backend/env/lib/python3.6/site-packages/django/db/models/fields/__init__.py", line 947, in get_prep_value
return int(value)
TypeError: int() argument must be a string, a bytes-like object or a number, not 'RelatedManager'
[28/May/2018 15:55:19] "GET /api/v1/aggregator/read/4/67 HTTP/1.1" 500 18150
TypeError: int() argument must be a string, a bytes-like object or a number, not 'RelatedManager'
What am I doing wrong here?
I think you have edited the error out of your view.
The traceback shows that your file api.py:28 has a line:
feed.viewers.add(user.analytics)
But user.analytics is a one-to-many relation, and thus one user can have several UserAnalytics objects (since many of these can all refer to the same use). As a result user.analytics is not a single object, nor a collection, but a RelatedManager: some sort of manager to manage the related objects.
You can add .all() and perform iterable unpacking to add all the .analytics objects with a single call:
feed.viewers.add(*user.analytics.all())
(notice the asterisk * in the call).
In case every user has at most one UserAnalytics object, you better use a OneToOneField, so:
# only in case a user has *at most* one UserAnalytics object
class UserAnalytics(models.Model):
user = models.OneToOneField(User, related_name='analytics', on_delete=models.CASCADE, null=True)
uptime = models.IntegerField(null=True)
feeds_viewed = models.IntegerField(null=True)
feeds_shared = models.IntegerField(null=True)
In that case a user.analyics will either return the associated UserAnalytics object (given there is one), or - if there is no such object - raise a UserAnalytics.DoesNotExist error.

Serializer results in KeyError after correct data input and save

I'm creating an API endpoint that works and saves data through its API. It works, but my concern is that it throws a KeyError as shown below. I'm not sure if this is an issue with my code. Your help is very much appreciated.
Data:
data = {'title': u'abc', 'career_level': 1}
Serializer:
class JobPostSerializer(serializers.ModelSerializer):
career_level = PrimaryKeyRelatedField(allow_null=True, queryset=CareerLevel.objects.all(), required=False)
title = CharField(allow_blank=True, allow_null=True, max_length=240, required=False)
Model:
class JobPost(models.Model):
career_level = models.ForeignKey(CareerLevel, related_name='jobpost_career', blank=True, null=True)
title = models.CharField(max_length=240, blank=True, null=True)
created_at = models.DateTimeField(db_index=True, auto_now_add=True)
def __str__(self):
return self.title
def __unicode__(self):
return self.title
class Meta:
ordering = ['-created_at']
Error Message:
Internal Server Error: /api/v1/posts/
Traceback (most recent call last):
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 149, in get_response
response = self.process_exception_by_middleware(e, request)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/core/handlers/base.py", line 147, in get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/django/views/decorators/csrf.py", line 58, in wrapped_view
return view_func(*args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/viewsets.py", line 87, in view
return self.dispatch(request, *args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/views.py", line 466, in dispatch
response = self.handle_exception(exc)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/views.py", line 463, in dispatch
response = handler(request, *args, **kwargs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/mixins.py", line 22, in create
headers = self.get_success_headers(serializer.data)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 503, in data
ret = super(Serializer, self).data
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 241, in data
self._data = self.to_representation(self.validated_data)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/serializers.py", line 463, in to_representation
attribute = field.get_attribute(instance)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/relations.py", line 157, in get_attribute
return get_attribute(instance, self.source_attrs)
File "/home/ubuntu/panbecopy/src/penv/local/lib/python2.7/site-packages/rest_framework/fields.py", line 78, in get_attribute
instance = instance[attr]
KeyError: u'career_level'
Your serializer definition makes no sense.
JobPostSerializer(data={'title': u'abc', 'career_level': 1}):
It should instead be:
class JobPostSerializer(serializers.ModelSerializer):
That line of yours is more similar to when you want to instantiate the serializer. Something like when you want to check if the input was valid, for example.
job_serializer = JobPostSerializer(data={'title': u'abc', 'career_level': 1})
job_serializer.is_valid()