Localization of Date formats in Django - django

I am working on an app that should support different languages and flavours such as American, British and German.
Now looking at the documentation, e.g. there seem to be no direct support for American date format. It seems this part needs to be done by hand.
So I kept digging into the documentation and found this:
{{ value|date:"D d M Y" }}
This doesn't seem to work well with forms though, when I tried this in my code:
{{form.birth_date|date:"D d M Y"}}
It seems the formatting needs to be set right at the form field itself.
More research showed a similar question was asked in Stackoverflow in 2009:
This solution could work, but it looks quite engaging for such a simple problem. Django has come a long way since 2009, so I wonder if there is a better way of doing it right into ModelForm?
Let say we have the following code:
Model:
class ConversationHistory(models.Model):
contact_date = models.DateField(_(u"Conversation Date"))
Form:
class ConversationForm(ModelForm):
class Meta:
model = ConversationHistory
Could I just add the following to ModelForm:
widgets = { 'contact_date': forms.DateInput(format='M d, Y') }
is this the right way of localization? What if I wanted to change the format to Brtish English or German? So I have the feeling I am missing here something...
Many Thanks,
UPDATE:
I have now tried this:
widgets = { 'contact_date': forms.DateInput(format='SHORT_DATE_FORMAT') }
But the date shows as SHORT_DATE_FORMAT.
What am I missing?

You're looking for the x format. Or worst case you just I18Nize the format and let the translator figure it out.

I have been working on a solution for this with dojo for 2YRS!!! And I finally manged to find the the following works if you are using the dojango intergration.
someDate = DateField(widget=DateInput(attrs={'constraints':'{datePattern:\'dd/MM/yyyy\', strict:true}'))
forms.py
I don't know if that helps

Related

Generate url for Django Simple History historical object

Given an model called Stuff, I want the url to a HistoricalStuff object.
In other words, how does one implement get_historical_url in the below code snippet?
stuff = Stuff.objects.first()
stuff.pk
-> 100
historical_stuff = stuff.history.first() # we want to get url for this
historical_stuff.pk
-> 1
get_historical_url(historical_stuff)
-> /path/to/admin/stuff/100/history/1
Obviously the dumb solution would be to use a format string but I'd rather use urlresolvers
After much digging around, I found in the simple history source code that the url name is similar to the admin change names, namely admin_%s_%s_simple_history.
With this knowledge, get_historical_url looks like
def get_simplehistory_url(history_obj):
parent_obj = history_obj.history_object
return urlresolvers.reverse('admin:{}_{}_simple_history'.format(
parent_obj._meta.app_label, parent_obj._meta.model_name), args=(parent_obj.id, history_obj.pk))

ElasticSearch - bulk indexing for a completion suggester in python

I am trying to add a completion suggester to enable search-as-you-type for a search field in my Django app (using Elastic Search 5.2.x and elasticseach-dsl). After trying to figure this out for a long time, I am not able to figure yet how to bulk index the suggester. Here's my code:
class SchoolIndex(DocType):
name = Text()
school_type = Keyword()
name_suggest = Completion()
Bulk indexing as follows:
def bulk_indexing():
SchoolIndex.init(index="school_index")
es = Elasticsearch()
bulk(client=es, actions=(a.indexing() for a in models.School.objects.all().iterator()))
And have defined an indexing method in models.py:
def indexing(self):
obj = SchoolIndex(
meta = {'id': self.pk},
name = self.name,
school_type = self.school_type,
name_suggest = {'input': self.name } <--- # what goes in here?
)
obj.save(index="school_index")
return obj.to_dict(include_meta=True)
As per the ES docs, suggestions are indexed like any other field. So I could just put a few terms in the name_suggest = statement above in my code which will match the corresponding field, when searched. But my question is how to do that with a ton of records? I was guessing there would be a standard way for ES to automatically come up with a few terms that could be used as suggestions. For example: using each word in the phrase as a term. I could come up something like that on my own (by breaking each phrase into words) but it seems counter-intuitive to do that on my own since I'd guess there would already be a default way that the user could further tweak if needed. But couldn't find anything like that on SO/blogs/ES docs/elasticsearch-dsl docs after searching for quite sometime. (This post by Adam Wattis was very helpful in getting me started though). Will appreciate any pointers.
I think I figured it out (..phew)
In the indexing function, I need to use the following to enable to the prefix completion suggester:
name_suggest = self.name
instead of:
name_suggest = {'input': something.here }
which seems to be used for more custom cases.
Thanks to this video that helped!

How to create circular relationships in django-filter

Using django-filters, I have judgements written by judges. The models are roughly:
app1: models.py:
from app2.models import Judge
class Judgement(model.Models):
judges = models.ManyToManyField(Judge, related_name="judgements")
topic = models.TextField(help_text="The topic the judgement is about."
app2: models.py
class Judge(models.Models):
name = CharField(max_length=100)
race = CharField(max_length=5, choices=RACES)
I want to be able to filter Judgements or Judges by one or the other, so my filters should be:
class JudgementFilter(filters.FilterSet):
# THIS DOESN'T WORK.
judges = RelatedFilter('JudgeFilter', name='judges')
class JudgeFilter(filters.FilterSet):
judgements = RelatedFilter(JudgementFilter, name='judgements')
If that worked, I'd be able to ask the API for Judges filtered by attributes of the judgements they wrote (For example: "all judges writing a judgement about race"), or I'd be able to filter for Judgements filtered by the Judges that wrote them (For example, "all judgements written by black judges").
Unfortunately, this doesn't work and I get an error about trying to import the string value instead of something else. Is there a way to accomplish this?
I regret to answer my own question this way, but this information was in the readme and I totally missed it.
The solution is to use full paths:
class JudgementFilter(filters.FilterSet):
judges = RelatedFilter('path.to.my.app.JudgeFilter', name='judges')
class JudgeFilter(filters.FilterSet):
judgements = RelatedFilter(JudgementFilter, name='judgements')
And then life is good.

django polymorphic model, filter on subclass field

I have some models using django-polymorphic-model
eg.
class Article(PolymorphicModel):
...
class Blog(Article):
tags = ...
class Story(Article):
publish = ...
Normally if I get all articles, I just do Article.objects.all(), however what if I want to get all articles that tags are empty? If I do Articles.objects.filter(tags__isnull=True) it will break because other models don't have this field, I would like to include Story entries too, do I really have to split into 2 different queries and combine again?
OK After some digging for the documentation through issues, here is how to do it
Articles.objects.filter(Blog___tags__isnull=True)
Hope you found an answer before.
Articles.objects.filter(Q(Blog___tags__isnull=True)|Q(Story__tags__isnull=True))

How do I do a partial field match using Haystack?

I needed a simple search tool for my django-powered web site, so I went with Haystack and Solr. I have set everything up correctly and can find the correct search results when I type in the exact phrase, but I can't get any results when typing in a partial phrase.
For example: "John" returns "John Doe" but "Joh" doesn't return anything.
Model:
class Person(models.Model):
first_name = models.CharField(max_length=50)
last_name = models.CharField(max_length=50)
Search Index:
class PersonIndex(SearchIndex):
text = CharField(document=True, use_template=True)
first_name = CharField(model_attr = 'first_name')
last_name = CharField(model_attr = 'last_name')
site.register(Person, PersonIndex)
I'm guessing there's some setting I'm missing that enables partial field matching. I've seen people talking about EdgeNGramFilterFactory() in some forums, and I've Googled it, but I'm not quite sure of its implementation. Plus, I was hoping there was a haystack-specific way of doing it in case I ever switch out the search backend.
You can achieve that behavior by making your index's text field an EdgeNgramField:
class PersonIndex(SearchIndex):
text = EdgeNgramField(document=True, use_template=True)
first_name = CharField(model_attr = 'first_name')
last_name = CharField(model_attr = 'last_name')
In addition to the EdgeNgramField hint that others mentioned in this page (and of course NgramField, if you work with Asian languages), I think it is worth to mention that in Django_haystack you can run raw queries on Solr via following command:
from haystack.query import SearchQuerySet
from haystack.inputs import Raw
SearchQuerySet().filter(text=Raw(query))
where text is the field you want to search, and the query can be anything based on Query Parser Syntax (version 3.6, or 4.6) of Lucene.
In this way you can easily set the query to ABC* or ABC~ or anything else which fits to the syntax.
I had a similar issue while searching for non english words, for instance:
ABC
ABCD
If I want to search for keywords ABC, I will expect the above two results. I was able to achieve the following by converting the keyword to lowercase and using startswith:
keywords = 'ABC'
results.filter(code__startswith=keywords.lower())
I had the same problem and the only way to get the results I wanted was to modify the solr configuration file to include ngram filtering as the default tokenizer is based on white space. So use NGramTokenizer instead. I'd love to know if there was a haystack way of doing the same thing.
I'm not at my machine right now but this should do the trick.
<tokenizer class="solr.NGramTokenizerFactory" minGramSize="3" maxGramSize="15" />
#riz I can't comment yet or I would and I know it's an old comment but in case anyone else runs past this: Make sure to manage.py update_index
Blockquote #Liarez how did you get this to work? I'm using haystack/elastic search and I wasn't able to get it to work.