django - get field via verbose name - django

suppose I have this field in Foo model
field1 = CharField(max_length=10, verbose_name='Bar')
Is there a way to return field1 via its verbose_name?
Here is my visualization for it but it throws a TypeError
Foo._meta.get_field(verbose_name='Bar')

You can manually filter on these, and return the first one that matches:
my_field = next(
field for field in Foo._meta.get_fields() if field.verbose_name='Bar'
)
This will raise a StopIteration in case no such field exists.
It is possible that there are multiple such fields. We can for example generate a list of these fields with a similar list comprehension:
all_bar_fields = [
field for field in Foo._meta.get_fields() if field.verbose_name='Bar'
]

Related

Use django_filters to query a list that contains any item in query params

I'm having a Django model that contains a JSON field to store a list, like so:
class Movie(models.Model):
tags = JSONField()
As such, a movie mymovie contains a list of tags, such as:
mymovie.tags = ["horror", "love", "adventure"].
And now, I want a query to fetch all movies having at least one tag of a list of tags, like so:
GET /movies?tags=horror,cowboy
In my previous example, the query will get mymovie, because it has horror in its tag, even if it doesn't have cowboy.
Using *django_filters, I managed to do it with the following implementation:
class CharInFilter(BaseInFilter, CharFilter):
pass
class MovieFilter(FilterSet):
class Meta:
model = Movie
fields = ["tags"]
tags = CharInFilter(method="tags_filter")
def tags_filter(self, queryset, name, value):
# value will contain a list of tags, and we want any movie that at least one of
# its tag is in the list of provided tags
query = Q()
for tag in value:
query |= Q(
tags__icontains=tag
)
if query:
queryset = queryset.filter(query)
return queryset
It works, but it feels very hacky, and I won't be surprised if an ad hoc implementation of this exists.
Does someone have a better idea ?
Thank youuuu ^^

Django IntegrityError manytomany field

I'm trying to implement hashtags in my django app
I have a message model with a field like this
hash_tags = models.ManyToManyField(HashTag, related_name='message_hash_tags')
And this is the HashTag model
hash_tag = models.CharField(max_length=140, primary_key=True)
And I'm setting the hashtags to the message like this
hash_tags_list = Functions.extract_hashtags(message["message"])
hash_tags = [HashTag.objects.get_or_create(hash_tag=ht) for ht in hash_tags_list]
messageObj.hash_tags.set(hash_tags)
messageObj.save()
But this errors out
django.db.utils.IntegrityError: insert or update on table "messaging_message_hash_tags" violates foreign key constraint "messaging_message_ha_hashtag_id_068959e9_fk_messaging"
DETAIL: Key (hashtag_id)=((<HashTag: HashTag object (skills)>, True)) is not present in table "messaging_hashtag".
Tho I can find the HashTag object (skills) in my messaging_hashtag table:
SELECT * FROM messaging_hashtag;
hash_tag
----------
skills
get_or_create returns a tuple which contains the object and a flag on whether the object was created or not, so something like: (obj, created)
To fix this, just extract the obj from the tuple. For example using [0] on the result:
hash_tags = [ HashTag.objects.get_or_create(hash_tag=ht)[0] for ht in hash_tags_list ]

Django filter empty fields

Currently I am filtering empty fields in all entries of the queryset like this:
data_qs = DataValue.objects.filter(study_id=study.id) #queryset
opts = DataValue._meta # get meta info from DataValue model
field_names = list([field.name for field in opts.fields]) # DataValue fields in a list
field_not_empty = list() # list of empty fields
for field in field_names:
for entry in data_qs.values(field):
if entry.get(field) is not None:
field_not_empty.append(field)
break
It works but not sure if it is an appropriate solution....
Does anyone know how to filter empty values in all the queryset? The table have more than 30 fields, so depending on the study ID some querysets may contain the field1 all empty, other study ID may contain all the field2 empty.
Does the Django ORM provide an easy an clean solution to do this?
Thanks in advance
To check if some value in a QuerySet is empty, say the values name is "title".
This will exclude all empty fields
DataValue.objects.filter(study_id=study.id).exclude(title__exact='')
If you only want the empty fields, just filter it
DataValue.objects.filter(study_id=study.id, title__exact='')
Hope it helped.

Django: Values_list returns id from choice field instead of name

I have two models
class Model1:
my_Choices = ((1, val1), (2, val2))
field1 = choice_field(my_Choices)
field2 = charfield
and another model which has ManyToMany field
class Model2:
field1 = ManytoMany(Model1, related_name='rel_model2')
field2 = Charfield
Now I have a list of objects(queryset) of Model2.(or for sake of simplicity assume I have an object of second model )
now I do reverse filtering
Model2_obj.rel_model2.all()
OR (In my case)
Model2_obj.rel_model2.values_list('field1', flat=True)
this will return the list of ids from choices available in Model1(right?)
e.g. [1L, 2L]
instead if this I want name/value (I mean list of values from choices)
e.g.
['val1', 'val2'],
I can do this by iterating over both id list and choice_list but can we do in a single ORM query/Pythonic way/efficient way?
if you choose to use the values_list() function, then you'll have to do the lookup/conversion yourself. (That's because Django is storing the number in the database, and not the string, and values_list() says "get me what is in the database".) Doing the lookup is not hard -- you can create a dictonary as
my_choices_dict = dict(my_choices)
and use that.
Alternatively, if you get the full object, you can use the get_field1_display() method that is built into your model class. See https://docs.djangoproject.com/en/1.8/topics/db/models/ and search for "get_FOO_display"

Django Haystack - Search on non-indexed many to many field

Is there a way of having only a filtered part of a model as a SeachQuerySet?
Something like:
query = SearchQuerySet().models(Entry.filter(categories__name='something'))
instead of
query = SearchQuerySet().models(Entry)
The field I want to filter by is a manytomany field and non indexed.
The search index doesn't store any relations, it is therefore 'flat'. You can only add your categories' IDs to the index for Entry (note that you have to use a prepare_-method for this):
class EntryIndex(indexes.SearchIndex, indexes.Indexable):
# your other fields
categories = MultiValueField()
def prepare_categories(self, obj):
return [category.pk for category in obj.categories.all()]
The you can do something like:
category = Category.objects.get(name='something')
sqs = SearchQuerySet().models(Entry).filter(categories=category.pk)