Questions about Django's internationalization framework - django

When developing apps for use in multiple languages, I see a real benefit to using localization over trying to build some ad hoc localization library specific to your application. I'm working on a website that will have 16 languages, and each language will have different images in various places, as well as full text translations for each page's content, each language residing on a different URL (www.example.com/en/, etc). Django's internationalization framework seems very magical, and tricky. My idea was to do something basic, like:
class Language(models.Model):
name = models.CharField(max_length=50)
code = models.CharField(max_length=2) # (e.g. "FR")
class ContentSection(models.Model):
page = models.ForeignKey('mysite.Page')
name = models.CharField(max_length=50) # (e.g. ("main body text")
content = models.TextField(max_length=5000)
class Meta:
unique_together = (('name', 'page'),)
class ContentTranslation(models.Model):
content_section = models.ForeignKey(ContentSection)
language = models.ForeignKey(Language)
content = models.TextField(max_length=5000)
class Meta:
unique_together = (('content_section', 'language'),)
I would use middleware to set the current language based on the first URL segment, and in my views I would pull the content for a given page in a view with something like:
# In views.view_page
left_content = ContentSection.objects.filter(page=current_page, name='left column text')
if not request.language.code == 'EN':
left_content = ContentTranslation.objects.get(content_section=left_content, language=request.language)
Of course, in production I'd probably create a template tag that gets a content (with the correct language) by name, instead of explicitly pulling each content area in the view.
Does this seem so ridiculous to do this instead of using i18n? Am I missing the bigger picture with internationalization?
(keep in mind: the site will be browsed by users in other languages, but all admin stuff, including inserting translations, will be done in the US)

This is a sound approach if what you need is to be able to have your users change the content in all the different languages. You also get to create a nice interface for everything.
However, you are not using the Django i18n framework. So what is your question? :)
I have tried both using the i18n framework for content and using your approach. Storing translations in po-files is great for "system" text as you can use all your tools, like version control, bug tracking, etc. However, it is a pain in the ass if you have users who actually want to change the content all the time, which I believe is the case for almost any web site of some size.
As a side note, including the language in the URL makes it easier to cache the pages on the front end varnish proxy that everybody should be using, so +1 for that decision.

Related

Illustrated texts in Django model

I am trying to make one Blog using Django 2.0 and I have already created a primitive one. It has a Post model which is as follows:
class Post(models.Model):
PriKey = models.CharField(max_length=255,primary_key=True)
Heading = models.CharField(max_length=100)
DateOfPost = models.DateField(default=datetime.date.today())
Content = models.TextField()
As it can be seen, the content area is only textual and as of now, I can't add any special style or pictures inside my content.
I thought of using HTML tags inside the text content but they are appearing unchanged when the web page is rendered.
So my question is, is there any way of storing pictures along with the text in the content field of the Post model? I want to make something like this
Is there any way of showing the pictures in their respective positions using Django model? If no, is there any other way of doing this?
Also, is there any way of storing HTML codes inside django models and render them as it is when the website is run?
You can store html tags inside the field.
while rendering, to template mark it as safe
{{ post.content|safe }}
This will render all the html tags.
But this is not a good way as it makes you vullerable to cross site scripting attacks
A better method is to use something like a ckeditor
It provides a RichTextField and RichTextUploading Field and using this you can upload pictures, videos, code snippets, style your text and a lot more inside one field.
There are many other optons, but I prefer ckeditor
Ckeditor is a cross platform editor, django-ckeditor is a library containing django implementation of ckeditor which gives you full backend and frontend combined
ckeditor
django-ckeditor
django-pagedown A django app that allows the easy addition of Stack Overflow's "PageDown" markdown editor to a django form field, whether in a custom app or the Django Admin
I think you should give it a try
Cheers :)

How can Django handle big dropdown list without front end scripts?

Problem is simple, dropdown fields based on foreign key eventually can become very big and it is difficult to select needed value for end user.
Of course it is possible to manage those using front end scripts, however is there anything in django "batteries included" that can solve this without going into Javascript too much ?
If you end up with large drop down lists you could look to Select2 as a solution as it offers a text field with auto completion, amongst other widgets.
The auto complete type widget I mention works like this;
class MyForm(forms.Form):
my_choice = forms.ChoiceField(
widget=ModelSelect2Widget(
model=MyOtherModel,
search_fields=['title__icontains']
)
)

Edit css files from django admin

My client wants to edit the css files of the site from django admin.
Is there any way to do it ? .
Basically what they want is,to be able to change the color,font etc of the data in the front end from django admin interface.
The best thing would be to just let him edit the css file itself. CSS is, in essence, a rather flexible tool, so writing a way to manage it is rather tough (and really, overkill). It's already easy to pick-up, and any nice editor like sublime or notepad++ would probably be easier and more natural than whatever you'll build using the admin site. Also, by building a simple way to control css, your client will probably start asking for more and more flexibility until you find yourself building an entire cms (trust me, I've been there myself).
What's more, your client probably only wants to manage small aspects or details of the site. Recently I had a project where I allowed my users to style their display of my application. The way I did it was to create a UserDesign model which extended the base User model and kept very specific css data. Something like this:
class UserDesign(models.Model):
user = models.OneToOneField(User)
background_color = models.CharField(max_length=15)
font_color = models.CharField(max_length=20, choices=COLORS)
theme = models.CharField(max_length=20, choices=THEMES)
Meaning, they didn't control the entirety of the css, but they did get to choose the background color and some other information. It's a very neat addition to any website. However, if you are bent over doing it the hard way, I'd do something like this:
class Selector(models.Model):
name = models.CharField(max_length=30)
def get_template(self):
attrs = [a.join() for a in self.attr_set.all()]
return """ %s { %s } """ % ( self.name, ';'.join(attrs) )
class Attr(models.Model):
key = models.CharField(max_length=30)
value = models.CharField(max_length=30)
selector = models.ForeignKey(Selector)
def join(self):
return ': '.join(self.key, self.value)
I chose 30 as the max_length completely arbitrarily (you might need it longer), and you can use a TabularInline to make each selector easy to manage. Then you can easily use different css definitions inside your templates themselves:
<style>
{% for selector in selectors %}
{{ selector.get_template }}
{% endfor %}
</style>
Of course, the Selector model would probably need another field called 'template' or 'view' or something, to link it to a certain html file, though at this point it quickly start devolving into building your own cms (which, as mentioned before, is quite a headache that not wanting to edit a text file just doesn't justify)
A third viable option is to create a view with a code-editor, and just let your client edit his css through the web page. There's more than enough client-side plugins out there, like ace or codemirror (and of course, limit that view to administrators, which very simple to do).

Alternative form for Django's `ChoiceField` that can handle thousands of entries

I have a form with a ChoiceField in it. It is rendered to the user as a dropdown box.
Problem is, I have thousands of entries in this field, which is causing the page to (a) load very slowly and (b) be sluggish.
I want an alternative widget, instead of Select, that could handle more than 10,000 choices.
Something like the admin's raw_id_fields would be good (if only it were usable in general forms...) but I'm open to ideas.
If autocomplete is an option for your UI you can take a look to django-simple-autocomplete:
App enabling the use of jQuery UI autocomplete widget for
ModelChoiceFields with minimal configuration required.
EDITED (reply OP comment)
I have not tested this solution, but digging documentation and source it seems that not all data is loaded at a time:
The ability to specify an URL for the widget enables you to hook up to
other more advanced autocomplete query engines if you wish.
Source code:
def get_json(request, token):
"""Return matching results as JSON"""
...
di = {'%s__istartswith' % fieldname: searchtext} # <- look here!
items = queryset.filter(**di).order_by(fieldname)[:10]
Widget source code
$("#id_%(name)s_helper").autocomplete({
source: function(request, response){
$.ajax({ # <-- look here
url: "%(url)s",
data: {q: request.term},
success: function(data) {
I don't know what is the raw_id_fields but why not use a model to store all your choices ?
class Choice(models.Model):
value = models.CharField()
class MyModel(models.Model):
choice = models.ForeignKey(Choice)
It would then be easy to select it if you want to display only 20 at a time for example.
Based on this comment (which really, you should have included in your question):
Let me clarify my task: I have 10,000 users. I have a form in which
you choose a user. You need to be able to choose any user you want.
You can't just load 20, because then you won't be able to choose the
other 9,980 users.
If you want something built-in, you can use the FilteredSelectMultiple widget from django.contrib.admin.widgets, which puts a filter on your select.
You should also cache the results of the 10,000 users so you don't hit your db everytime. This is what is causing your delay, not the number of users (which is tiny, for practical performance problems).

is there a way to use django generic views and some smart urlpatterns for quick ordering/sorting of queries?

let's assume I have a django model like this:
class Event(CommonSettings) :
author = models.ForeignKey(User)
timestamp = models.DateTimeField(auto_now_add=True)
event_type = models.ForeignKey(Event_Type, verbose_name="Event type")
text_field = models.TextField()
flag_box = models.BooleanField()
time = models.TimeField()
date = models.DateField()
project = models.ForeignKey(Project)
now, by default, I have a view where I sort all events by time & date:
event_list = Event.objects.filter().order_by('-date', '-time')
however, maybe the user wants to sort the events by time only, or by the date, or maybe in ascending order instead of descending. I know that I can create urlpatterns that match all these cases and then pass on the these options to my view, however I feel like I'm reinventing the wheel here. the django admin site can do all of this out of the box.
So here's my question: is there a clever, easy way of getting this done in a generic way, or do I have to hard code this for my models / views / templates?
and yes, I did find solutions like this (https://gist.github.com/386835) but this means you use three different projects to achieve one thing - this seems to be a too complicated solution for such a simple thing.
EDIT1:
how do I have to change the template so that I can combine multiple filters? Right now I have
Desc
Asc
but I want to allow the user to also change number of entries that get displayed. So I have:
order by date
order by name
This works all fine, but if I click on 'order by date' and then I click on 'Asc', then my previously selected order disappears. That's not what I want. I want the user to be able to combine some options but not others.
EDIT2:
unfortunately your solution doesn't work with
from django.views.generic.list_detail import object_list
and it's
paginate_by
option.
I tried:
prev
{% trans "next" %}
but the links then just don't work (nothing happens). maybe you need to do something special with "object_list"?
I don't think it's as much work as you're making it out to be - you can use variables instead of explicitly creating separate url patterns. If you look at how the django admin handles it, they tack on request variables to the url like ?ot=asc&o=2 This corresponds to sort in ascending order in by the 2nd column. Of course, if you designing a particular page, you might as well use more readable naming. So instead of numbering the categories, i'd do ?sort=desc&order_by=date and then put a regular expression in the view to match the different possibilities. Something like:
order = re.match(r"(?:date|time|name)$", request.GET['order_by'])
if request.GET['sort'] == 'desc':
order = '-' + order
results = Event.objects.filter().order_by(order)
You could instead use the regexp as a url pattern matcher as you suggested, but it's more common to let the url itself represent which part of the site you're at (i.e. website.com/events/) and the url request variables represent how that content is being displayed (i.e. ?order_by=date&sort=desc).
Hope that helps!
EDIT: For the second part of your question, use Django's templating system (which reads variables) instead of just html. There are several ways I can think of to do this, depending on personal preference and how exactly you want the UI to function (i.e. page loads with new variables anytime the user chooses a filter, or the user chooses all filter options in a form and then submits it so the page only has to reload once, etc). In this case, you could just do:
Ascending
Descending
Name
Date
Then in the view make sure your render_to_response arguments include a dictionary that looks like: {'order': request.GET['order_by'], 'sort': request.GET['sort_by'], }
Unfortunately, (and someone please correct me if I'm wrong) I don't think there's a template tag to generate a url with request.GET parameters - the url tag {% url name_of_view order_by=name sort_by=desc %} would generate "path/to/name_of_view/name/desc/", but I don't think there's a tag to generate "path/to/name_of_view?order_by=name&sort_by=desc". It would be pretty easy to write a custom tag for this though (I wouldn't be surprised if there's already one on django-snippets or something, although I just did a quick google search and didn't find anything).