Related
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
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.
I'm building an API as part of a project for university, However, I have become stuck when working out how to make updates to my custom user model. At present I have a serializer for updating the profile, but when I try to update the table using the serializer, it falls over with error 1406: "Data too long for column 'title' at row 1". I'm not sure how to resolve this at present and was wondering if someone could point me in the right direction
update:
So it seems that I was getting the Data too long for column errors because The code I have is appending to the columns instead of just either altering them if the JSON contains data for the field, or leaving them if it does not. So once I'd tinkered with column lengths I was getting the following database row:
(None, 'Anthony'), (None, (None, 'Anthony')), 1, 0, 1, 1, 2019-01-01, ('a
test address', 'hello'), (None, None), (None, None), edd, (None,
'boy'), (None, 'there'), (None, None), (None, '282')
model in question:
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(_('email address'), unique=True)
title =models.CharField(_('Title'), max_length=8, null=True, blank=True)
first_name=models.CharField(_('first name(s)'), max_length=100, blank =True)
last_name=models.CharField(_('last name'), max_length=100, blank = True)
is_active=models.BooleanField(_('account active'), default=False)
is_driver = models.BooleanField(_('driver status'), default=False)
is_staff = models.BooleanField(_('staff status'), default =False)
is_admin = models.BooleanField(_('admin status'), default =False)
dob = models.DateField(auto_now_add= True, blank=True)
address_1=models.CharField(_('address line 1'),max_length=60, null=False, blank=False)
address_2=models.CharField(_('address line 2'),max_length=60, null=True, blank=True)
address_3=models.CharField(_('address line 3'),max_length=60, null=True, blank=True)
city = models.CharField(_('city'),max_length=60, null=False, blank=False)
county = models.CharField(_('county'),max_length=60, null=False, blank=False)
postcode = models.CharField(_('postcode'),max_length=8, blank=False, null=False)
phone_no = models.CharField(_('phone number'),max_length=50, null=True, blank=True)
mobile_no = models.CharField(_('mobile Number'),max_length=50,null=False, blank=False)
drivers_licence_number = models.CharField(max_length=30, null=True, blank=True)
taxi_licence_number=models.CharField(max_length=30, null=True, blank=True)
driver_photo=models.ImageField(blank=True)
date_joined=models.DateField(auto_now_add=True, blank=True)
last_update=models.DateField(auto_now_add=True, blank=True)
serializer in question:
class UserProfileSerializer (serializers.ModelSerializer):
model = User
id = serializers.IntegerField(read_only=True)
dob = serializers.DateField(read_only=True)
title=serializers.CharField(max_length=8, required=False)
first_name=serializers.CharField(max_length=80,required=False)
last_name=serializers.CharField(max_length=80,required=False)
address_1 = serializers.CharField(max_length=100, required=False)
address_2 = serializers.CharField(max_length=100,required=False)
address_3 = serializers.CharField(max_length=100,required=False)
postcode = serializers.CharField(max_length=10, required=False)
county = serializers.CharField(max_length=50, required=False)
city = serializers.CharField(max_length=50, required=False)
phone_no = serializers.CharField(required=False)
mobile_no = serializers.CharField(required=False)
def update (self, instance, validated_data):
instance.title= validated_data.get('title'), instance.title
instance.first_name = validated_data.get('first_name'), instance.first_name
instance.last_name = validated_data.get('last_name'), instance.first_name
instance.address_1 = validated_data.get('address_1'), instance.address_1
instance.address_2 = validated_data.get('address_2'), instance.address_2
instance.address_3 = validated_data.get('address_3'), instance.address_3
instance.postcode = validated_data.get('postcode'), instance.postcode
instance.county = validated_data.get('county'), instance.county
instance.phone_no = validated_data.get('phone_no'),instance.phone_no
instance.mobile_no = validated_data.get('mobile_no'), instance.mobile_no
instance.last_update = datetime.now()
instance.save()
return instance
View in question:
class UpdateProfile(APIView):
permission_classes=[permissions.IsAuthenticated]
def post(self, request, format=None):
user=request.user
print (user.id)
query_set=User.objects.get(id=user.id)
print("we got a queryset")
print(query_set)
serializer=UserProfileSerializer(query_set, data=request.data)
if serializer.is_valid():
profile = serializer.save()
if profile:
return Response(user.data, status=status.HTTP_200_OK)
else:
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
Trace from the server console:
Internal Server Error: /editprofile/ Traceback (most recent call
last): File
"C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 85, in _execute
return self.cursor.execute(sql, params) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\mysql\base.py",
line 71, in execute
return self.cursor.execute(query, args) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 250, in execute
self.errorhandler(self, exc, value) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\connections.py",
line 50, in defaulterrorhandler
raise errorvalue File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 247, in execute
res = self._query(query) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 412, in _query
rowcount = self._do_query(q) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 375, in _do_query
db.query(q) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\connections.py",
line 276, in query
_mysql.connection.query(self, query)
_mysql_exceptions.DataError: (1406, "Data too long for column 'title' at row 1")
The above exception was the direct cause of the following exception:
Traceback (most recent call last): File
"C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\core\handlers\exception.py",
line 34, in inner
response = get_response(request) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\core\handlers\base.py",
line 126, in _get_response
response = self.process_exception_by_middleware(e, request) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\core\handlers\base.py",
line 124, in _get_response
response = wrapped_callback(request, *callback_args, **callback_kwargs) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\views\decorators\csrf.py",
line 54, in wrapped_view
return view_func(*args, **kwargs) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\views\generic\base.py",
line 68, in view
return self.dispatch(request, *args, **kwargs) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\rest_framework\views.py",
line 495, in dispatch
response = self.handle_exception(exc) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\rest_framework\views.py",
line 455, in handle_exception
self.raise_uncaught_exception(exc) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\rest_framework\views.py",
line 492, in dispatch
response = handler(request, *args, **kwargs) File "C:\Users\clini\git\net302API\Test1\api\views.py", line 68, in post
profile = serializer.save() File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\rest_framework\serializers.py",
line 209, in save
self.instance = self.update(self.instance, validated_data) File "C:\Users\clini\git\net302API\Test1\api\serializers.py", line 137, in
update
instance.save() File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\contrib\auth\base_user.py",
line 73, in save
super().save(*args, **kwargs) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\base.py",
line 718, in save
force_update=force_update, update_fields=update_fields) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\base.py",
line 748, in save_base
updated = self._save_table(raw, cls, force_insert, force_update, using, update_fields) File
"C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\base.py",
line 812, in _save_table
forced_update) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\base.py",
line 861, in _do_update
return filtered._update(values) > 0 File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\query.py",
line 712, in _update
return query.get_compiler(self.db).execute_sql(CURSOR) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\sql\compiler.py",
line 1383, in execute_sql
cursor = super().execute_sql(result_type) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\models\sql\compiler.py",
line 1065, in execute_sql
cursor.execute(sql, params) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 100, in execute
return super().execute(sql, params) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 68, in execute
return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File
"C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 77, in _execute_with_wrappers
return executor(sql, params, many, context) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 85, in _execute
return self.cursor.execute(sql, params) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\utils.py",
line 89, in exit
raise dj_exc_value.with_traceback(traceback) from exc_value File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\utils.py",
line 85, in _execute
return self.cursor.execute(sql, params) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\django\db\backends\mysql\base.py",
line 71, in execute
return self.cursor.execute(query, args) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 250, in execute
self.errorhandler(self, exc, value) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\connections.py",
line 50, in defaulterrorhandler
raise errorvalue File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 247, in execute
res = self._query(query) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 412, in _query
rowcount = self._do_query(q) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\cursors.py",
line 375, in _do_query
db.query(q) File "C:\Users\clini\MYDOCU~1\LICLIP~1\NET302~1\lib\site-packages\MySQLdb\connections.py",
line 276, in query
_mysql.connection.query(self, query) django.db.utils.DataError: (1406, "Data too long for column 'title' at row 1")
Did you maybe update the max_length of the title and did not migrate yet?
So To close this issue down, I found the solution. When I wrote the update method for my serializer i was writing them as
instance.fieldname =validated.data.get('input_name'),instance.fieldname
When they should have been
instance.fieldname =validated.data.get('input_name',instance.fieldname)
Thank you all for the help :)
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')
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.