Allow empty list in serializers.ListField - django

I am using Django REST framework 3.3 and am trying to serialize a list that could be empty with the provided serializers.ListField class that is included in the framework. My current instantiation of the field looks like this
countrypreferences = serializers.ListField(child=serializers.IntegerField(),
source='country_preference_ids',
allow_null=True)
When testing the API I always seem to get a 400 response if I let the field be an empty list. It would seem like this kind of functionality would be pretty common but I can't find a way to allow the empty list. Thanks!

You should set:
child=serializers.IntegerField(required=False)

In addition to that you can also provide a default value to the ListField in the serializers
field = serializers.ListField(default = [])
This will set the field as an empty list if u send None or no value.

I would rather use
field = serializers.ListField(child=serializers.CharField(), allow_empty=True)

Related

filter queryset for multiple models in Django

I'm implementing a search feature where I'm matching keys from the description. and also matching media if description and media type of ['mp4','mkv','mov','avi'] match so the condition is satisfied.
So I have tried many methods but didn't find an efficient way. to make it possible without for loop.
I want to use those together.
description and media type ['mp4','mkv','mov','avi']
postinlang_queryset = PostInLanguages.objects.filter(description__contains=search_name)
media_type_query_set = LanguageMedia.objects.filter(content_type__contains ['mp4','mkv','mov','avi'])
yes, it's possible without for loop.Just follow the following script:
postinlang_queryset = PostInLanguages.objects.filter(description__contains=search_name)
media_type_query_set = LanguageMedia.objects.filter(content_type__in=['mp4','mkv','mov','avi'])
N.B: content_type__in=['mp4','mkv','mov','avi'] If we pass an empty list then it will never throw exceptions but return empty queryset

Django forms without widgets

I understand that Django want to generate forms automatically so you don't have to do so in your template, and I do understand that many people find it cool.
But I have specific requirements and I have to write my forms on my own. I just need something to parse the data, be it a form submitted using a user interface, or an API request, or whatever.
I tried to use ModelForm, but it doesn't seem to work as I want it to work.
I'd like to have something with the following behavior:
possibility to specify the model of the object I am going to create/update
possibility to specify an object in case of an update
possibility to provide new data in a dictionary
if I am creating a new object, missing fields in my data should be replaced by their default values as specified in my model definition
if I am updating an existing object, missing fields in my data should be replaced by the current values of the object I am updating. Another way of saying is, do not update values that are missing in my data dictionary.
data validation should be performed before calling save(), and it should throw a ValidationError with the list of erroneous fields and errors.
Currently, I prefer to do everything manually :
o = myapp.models.MyModel() # or o = myapp.Models.MyModel.objects.get(pk = data['pk'])
o.field1 = data['field1']
o.field2 = data['field2']
…
o.full_clean()
o.save()
It would be nice to have a shortcut :
o = SuperCoolForm(myapp.models.MyModel, data)
o.save()
Do you know if Django does provide a solution for this or am I asking too much?
Thank you!

Some troubles while converting authors id to User model

My Post model have list of authors id
class Post(Document):
authors_id = ListField(IntField(required=True), required=True)
But sometime I need to use default Django User class. How most rapidly I can do it?
(I'm using sqlite for users and sessions and MongoDB (mongoengine ODM) for other. Don't ask why:))
I was tried to write it:
def get_authors(self):
authors = list()
for i in self.authors_id:
authors.append(get_user(IntField.to_python(self.authors_id[i])))
return authors
...and it raises 'list index out of range' exception. (authors id not empty, really). What I'm doing wrong?
Not sure about the to_python method but since you are looping through the authors_id, there is no need to do
authors.append(get_user(IntField.to_python(self.authors_id[i])))
You should be good with
authors.append(get_user(IntField.to_python(i)))
Instead of
IntField.to_python(self.authors_id[i]))
I think you just need to do:
IntField.to_python(i)
In Python the 'for i in some_list' construction gives you elements of the list, not integer indexes.
You said that you were getting this error:
and unbound method to_python() must be called with IntField instance as first argument (got int instance instead)
I got a similar error from MongoEngine. In my case the problem was that I defined the field like this:
foo_id = IntField
The correct way to define it is:
foo_id = IntField()
When I added the parenthesis, the problem went away.

Django: Querying comments based on object field

I've been using the built-in Django comments system which has been working great. On a particular page I need to list the latest X comments which I've just been fetching with:
latest_comments =
Comment.objects.filter(is_public=True, is_removed=False)
.order_by('submit_date').reverse()[:5]
However I've now introduced a Boolean field 'published' into the parent object of the comments, and I want to include that in the query above. I've tried using the content_type and object_pk fields but I'm not really getting anywhere. Normally you'd do something like:
Comment.objects.filter(blogPost__published=True)
But as it is not stored like that I am not sure how to proceed.
posts_ids = BlogPost.objects.filter(is_published=True).values_list('id', flat=True) #return [3,4,5,...]
ctype = ContentType.objects.get_for_model(BlogPost)
latest_comments = Comment.objects.filter(is_public=True, is_removed=False, content_type=ctype, content_object__in=posts_ids).order_by('-submit_date')[:5]
Comments use GenericForeignKey to store the relation to parent object. Because of the way generic relations work related lookups using __<field> syntax are not supported.
You can accomplish the desired behaviour using the 'in' lookup, however it'll require lot of comparisons when there'll be a lot of BlogPosts.
ids = BlogPost.objects.filter(published=True).values_list('id', flat=True) # Get list of ids, you would probably want to limit number of items returned here
content_type = ContentType.objects.get_for_model(BlogPost) # Becasue we filter only comments for BlogPost
latest_comments = Comment.objects.filter(content_type=content_type, object_pk__in=ids, is_public=True, is_removed=False, ).order_by('submit_date').reverse()[:5]
See the Comment model doc for the description of all fields.
You just cannot do that in one query. Comments use GenericForeignKey. Documentation says:
Due to the way GenericForeignKey is implemented, you cannot use such
fields directly with filters (filter() and exclude(), for example) via
the database API.

How can I get access to a Django Model field verbose name dynamically?

I'd like to have access to one my model field verbose_name.
I can get it by the field indice like this
model._meta._fields()[2].verbose_name
but I need to get it dynamically. Ideally it would be something like this
model._meta._fields()['location_x'].verbose_name
I've looked at a few things but I just can't find it.
For Django < 1.10:
model._meta.get_field_by_name('location_x')[0].verbose_name
model._meta.get_field('location_x').verbose_name
For Django 1.11 and 2.0:
MyModel._meta.get_field('my_field_name').verbose_name
More info in the Django doc
The selected answer gives a proxy object which might look as below.
<django.utils.functional.__proxy__ object at 0x{SomeMemoryLocation}>
If anyone is seeing the same, you can find the string for the verbose name in the title() member function of the proxy object.
model._meta.get_field_by_name(header)[0].verbose_name.title()
A better way to write this would be:
model._meta.get_field(header).verbose_name.title()
where header will be the name of the field you are interested in. i.e., 'location-x' in OPs context.
NOTE: Developers of Django also feel that using get_field is better and thus have depreciated get_field_by_name in Django 1.10. Thus I would suggest using get_field no matter what version of Django you use.
model._meta.get_field_by_name('location_x')[0].verbose_name
You can also use:
Model.location_x.field.verbose_name
Model being the class name. I tested this on my Animal model:
Animal.sale_price.field.verbose_name
Animal.sale_price returns a DeferredAttribute, which has several meta data, like the verbose_name
Note: I'm using Django 3.1.5
If you want to iterate on all the fields you need to get the field:
for f in BotUser._meta.get_fields():
if hasattr(f, 'verbose_name'):
print(f.verbose_name)
# select fields for bulk_update : exclude primary key and relational
fieldsfields_to_update = []
for field_to_update in Model._meta.get_fields():
if not field_to_update.many_to_many and not field_to_update.many_to_one and not field_to_update.one_to_many and not field_to_update.one_to_one and not field_to_update.primary_key and not field_to_update.is_relation :
fields_to_update = fields_to_update + [field_to_update.name]
Model.objects.bulk_update(models_to_update , fields_to_update)