Django Translations Not Working - html

I am working in a Django 1.9 / python3.5 application, and trying to make use of Django's translation utility. I have a locale directory which has an 'es' directory for spanish translations that I created a .po file in. I set it up to have a couple translations just to test it out.
msgid "Sign In"
msgstr "Registrarse"
msgid "Create an Account"
msgstr "Crea una cuenta"
I have my setting file correctly configured as well
MIDDLEWARE_CLASSES = (
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'webapp.middleware.LanguageSwitchMiddleware',
)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'APP_DIRS': True,
'DIRS': [os.path.join(BASE_DIR, 'templates'), ],
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'webapp.context_processors.detail_context',
'django.template.context_processors.i18n'
],
},
},
]
# Internationalization
# https://docs.djangoproject.com/en/dev/topics/i18n/
LOCALE_PATHS = (
os.path.join(PROJECT_ROOT, 'locale/'),
)
from django.utils.translation import ugettext_lazy as _
LANGUAGES = (
('en', _('English')), # first language is the default used by modeltranslations
('es', _('Spanish')),
)
LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'America/Chicago'
USE_I18N = True
In my template I use the Django 'trans' template tag for the words sign in, and create an account. A select box will edit the Content-Language http response header from the application, which I have tested, and it successfully does so. However the headers sign up, and create and account, do not translate to Spanish. Is there some step I'm missing ?
HTML
{% load i18n %}
<ul class="list-inline-xxs">
{% if customer %}
<li>
Welcome,
<a href='{% url "customer:dashboard" %}'>
{{ customer.first_name }}
</a>
</li>
<li>
<a href='{% url "customer:logout" %}'>
{% trans 'Logout' %}
</a>
</li>
{% else %}
<li>
<a href='{% url "customer:login" %}'>
{% trans 'Sign In' %}
</a>
</li>
<li>
<a href='{% url "subscription:customer-subscribe" %}'>
{% trans 'Create an Account' %}
</a>
</li>
{% endif %}
</ul>

I have a locale directory which has an 'es' directory for spanish
translations that I created a .po file in.
That ^^^ line suggests you are creating translation files manually. Let Django create translation files for you:
django-admin makemessages -a
Then put in your translations, save the file and compile with
django-admin compilemessages
Restart your app and it should work.
I've put together a simple example how to do translations with Django: https://github.com/DusanMadar/Django-multilang-demo
EDIT
As django django-admin makemessages -h suggests --ignore PATTERN, -i PATTERN is what you need to use to ignore third party directories. So something like django-admin makemessages -a -i 3rdparty_dir

Related

fetch is returning html rather than JSON response

I am working on the cs50 web development project Network. Basically building a twitter copycat.
It is still in process but so far I have two fetch requests for a JSON response. Once works perfectly but the other, which is a very similar request, returns html instead of JSON, causing an error. Can't figure out why this one doesn't work. Code snippets below:
Here is the one that is returning html for my profile.html file for some reason. The commented out parts are the actual fetch JSON request but I temporarily changed it to show me in the console what is was returning.
profile.js:
function load_posts_profile() {
console.log("load_posts_profile running");
document.querySelector('#prof-posts').style.display = 'block';
fetch(`/profile_posts`)
//.then(response => response.json())
.then(response => response.text())
.then(text => console.log(text))
//.then(posts => {
// Print posts
//console.log(posts);
//posts.forEach(post => show_posts_profile(post));
//});
}
profile.html:
{% extends "network/layout.html" %}
{% load static %}
{% block body %}
{% if user.is_authenticated %}
<!--insert profle name below in h3-->
<h2 id="profile-name"></h2>
<br>
<h4 id="followers"></h4>
<br>
<h4 id="following"></h4>
<!--add js to load user's posts only-->
<div id="prof-posts">
</div>
{% else %}
<strong> Login To See Profile</strong>
{% endif %}
{% endblock %}
{% block script %}
<script src="{% static 'network/profile.js' %}"></script>
{% endblock %}
urls.py:
from django.urls import path
from . import views
urlpatterns = [
path("", views.index, name="index"),
path("login", views.login_view, name="login"),
path("logout", views.logout_view, name="logout"),
path("register", views.register, name="register"),
path("all_posts", views.all_posts, name="all_posts"),
path("<str:poster>", views.profile, name="profile"),
path("profile_posts", views.profile_posts, name="profile_posts")
]
views.py snippet:
def all_posts(request):
posts = Post.objects.all()
posts = posts.order_by("-timestamp").all()
return JsonResponse([post.serialize() for post in posts], safe=False)
def profile_posts(request, poster):
posts = Post.objects.get(poster=poster)
posts = posts.order_by("-timestamp").all()
return JsonResponse([post.serialize() for post in posts], safe=False)
def profile(request, poster):
return render(request, "network/profile.html", {
"poster": poster,
})
And here is the js file with the similar fetch request that works perfectly. Why would this one work(ie return JSON) but the other returns html?:
function load_posts() {
console.log("load_posts running");
document.querySelector('#all-posts').style.display = 'block';
fetch(`/all_posts`)
.then(response => response.json())
.then(posts => {
// Print posts
console.log(posts);
posts.forEach(post => show_posts(post));
});
}
When in debug mode django returns an html response when an error occures, usually this is the problem, I think you're passing a parameter poster to the view function but you're not excepting one in the url path
In the future there are a few things to remember, when you get a different response then the one you expected, you should check your logs in the terminal or check the response code in the console client side, if it starts with 5 ot is a server error, of ot Starts with 4 it wasn't found or similar and you should check the logs
Here is how you should modify your code:
Add str:poster to the url path and modify the fetch request to include this in your url

Django doesn't accept image submission, method and enctype included in form tag but browser console claims it is missing

I'm following along with a tutorial to build a Django project. Part of the project is being able to upload an image to the test cdn directory. This is what my form looks like currently:
<form method='POST' action="." enctype='multipart/form-data'> {% csrf_token %}
{{ form.as_p }}
<button type="submit">Send</button>
</form>
The method and enctype are very clearly defined.
I've also set up my settings.py
STATIC_URL = '/static/'
LOCAL_STATIC_CDN_PATH = os.path.join(os.path.dirname(BASE_DIR), 'static_cdn_test')
STATIC_ROOT = os.path.join(LOCAL_STATIC_CDN_PATH, 'static')
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'staticfiles')
]
MEDIA_ROOT = os.path.join(LOCAL_STATIC_CDN_PATH, 'media')
MEDIA_URL = '/media/'
set up the files to be received in the view:
form = BlogPostModelForm(request.POST or None, request.FILES or None)
set up the model use ImageField:
image = models.ImageField(upload_to='image/', blank=True, null=True)
and the url patterns:
if settings.DEBUG:
# test mode
from django.conf.urls.static import static
# display images/files saved in the test cdn
urlpatterns += static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
But even with all this, the console informs me:
Form contains a file input, but is missing method=POST and enctype=multipart/form-data on the form. The file will not be sent.
This is the tutorial in case it helps https://www.youtube.com/watch?v=-oQvMHpKkms&list=PLM39hJgCef42hVok8ZRRE4LpLD-5bOxBh&index=20&t=13385s the part in question starts at 3:48:00.

Crisp keeps on throwing error 'BoundWidget' object has no attribute 'field'

Using crisp tags for creating a user registration form in Django application.
Here are codes in few my files to help:
Settings.py
INSTALLED_APPS = [
'blog.apps.BlogConfig',
'users.apps.UsersConfig',
'crispy_forms',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
HTML File
{% extends "blog/base.html" %}
{% load crispy_forms_tags %}
{% block content %}
{% csrf_token %}
{{form.first_name|crispy}}
{{form.last_name|crispy}}
{{form.username|crispy}}
{{form.email}}
{{form.password1|crispy}}
{{form.password2|crispy}}
other statements are CSS and HTML which i feel are not the concerned part for this question. However I will like to add that I do have done some styling for the Input tags (the form input fields).
Form.py
from django import forms
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm
class UserRegisterForm(UserCreationForm):
first_name = forms.CharField()
last_name = forms.CharField()
email = forms.EmailField()
username = forms.TextInput(attrs={'placeholder': 'Username'})
class Meta:
model = User
fields = ['first_name','last_name', 'username', 'email', 'password1', 'password2']
I have added the screenshot of errors thrown when webpage is requested:
The other part of the question or the reason I am using crisp is I need to authenticate input information and want to display warnings accordingly in short i want to customize the wrong input warnings for the registration form a referral to that kind of article is appreciated as i am unable to find one.
I had the same issue ,try this , it worked for me:
in the html file use:
{{form.first_name| as_crispy_field }}
In HTML file, just put either this{{form|crispy}} or {{form.fieldname|as_crispy_field}}

How do I scrape page content with a generator?

I have a blog where each post has a bunch of images and videos. I would like to be able to tag each of them with some keywords, and then populate a set of pages based on the tags. For example going to /photos/car/ would list all images tagged with car.
I include images and videos using a simple plugin right now, that essentially only has a render function. I figure I could add the tags there.
But how can I make Jekyll 'scrape' my pages and populate pages with images?
Short answer is : this is tricky.
But why ?
A custom imgWithTags-tag liquid tag like {% img cookie-monster.png tag2,tag3 %} can do two things :
render the html tag
store tag -> image associations in a site.taggedImage variable
As this tag can be used on any post, page or collection document, the site.taggedImage variable will only be complete after the render process.
Once the render process is finished, we can grab the :site, :post_render hook to process our datas and create Tags pages.
But here, we can no longer rely on things like {% for p in tagPages %}...{% endfor %} to automatically generate links to our pages : rendering is finished.
The trick can be to maintain a link data file by hand, in order to be able to generate links with loops like this {% for p in site.data.tagPages %}...{% endfor %}
Let's give it a try
NOTE : this works only with Jekyll version 3.1.x (not 3.0.x)
_plugins/imgWithTags-tag.rb
module Jekyll
class ImgWithTags < Liquid::Tag
# Custom liquid tag for images with tags
# syntax : {% img path/to/img.jpg coma, separated, tags %}
# tags are optionnal
#
# This plugin does two things :
# it renders html tag <a href='url'><img src='url' /></a>
# it stores tags -> images associations in site.config['images-tags']
Syntax = /^(?<image_src>[^\s]+\.[a-zA-Z0-9]{3,4})\s*(?<tags>[\s\S]+)?$/
def initialize(tag_name, markup, tokens)
super
if markup =~ Syntax then
#url = $1
#tags = $2.split(",").collect!{|tag| tag.strip } if !$2.nil?
else
raise "Image Tag can't read this tag. Try {% img path/to/img.jpg [coma, separated, tags] %}."
end
end
def render(context)
storeImgTags(context) if defined?(#tags) # store datas if we have tags
site = context.registers[:site]
imgTag = "<a href='#{ site.baseurl }/assets/#{#url}'><img src='#{ site.baseurl }/assets/#{#url}' /></a>"
end
def storeImgTags(context)
# store tagged images datas in site config under the key site.config['images-tags']
imagesTags = context.registers[:site].config['images-tags'] || {}
#tags.each{|tag|
slug = Utils.slugify(tag) # My tag -> my-tag
# create a tag.slug entry if it doesn't exist
imagesTags[slug] = imagesTags[slug] || {'name' => tag, 'images' => [] }
# add image url in the tag.images array if the url doesn't already exist
# this avoid duplicates
imagesTags[slug]['images'] |= [#url.to_s]
}
context.registers[:site].config['images-tags'] = imagesTags
end
end
end
Liquid::Template.register_tag('img', Jekyll::ImgWithTags)
At this point : all tagged images links are rendered and all tags->images associations are stored.
_plugins/hook-site-post-render-imagesTagsPagesGenerator.rb
Jekyll::Hooks.register :site, :post_render do |site, payload|
puts "++++++ site post_render hook : generating Images Tags pages"
imagesTags = site.config['images-tags'] # datas stored by img tag
linksDatas = site.data['imagesTagsLinks'] # tags pages link in data file
pagesFolder = 'tag'
imagesTags.each do |slug, datas|
tagName = datas['name']
tagImages = datas['images']
pageDir = File.join(pagesFolder, slug)
tagPage = Jekyll::ImageTagPage.new(site, site.source, pageDir, tagName, tagImages)
# as page rendering has already fired we do it again for our new pages
tagPage.output = Jekyll::Renderer.new(site, tagPage, payload).run
tagPage.trigger_hooks(:post_render)
site.pages << tagPage
# verbose check to see if we reference every tag url in out data file
if !linksDatas.key?(tagName) # check if tag is in imagesTagsLinks data file
puts "Warning ---------> #{tagName} not in data file"
puts "Add : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
else
if tagPage.url != linksDatas[tagName] then # check if url is correct in imagesTagsLinks data file
puts "Warning ---------> incorrect url for '#{tagName}'"
puts "Replace : #{tagName}: #{linksDatas[tagName]}"
puts "by : #{tagName}: #{tagPage.url}"
puts "in data/imagesTagsLinks.yml"
puts
end
end
end
puts "++++++ END site post_render hook"
end
module Jekyll
class ImageTagPage < Page
def initialize(site, base, dir, tag, images)
#site = site
#base = base
#dir = dir
#name = 'index.html'
self.process(#name)
self.read_yaml(File.join(base, '_layouts'), 'tag_index.html')
self.data['tag'] = tag
self.data['images'] = images
self.data['title'] = "Images for tag : #{tag}"
end
end
end
And the Tag layout page
_layouts/tag_index.html
---
layout: default
---
<h2>{{ page.title }}</h2>
{% for i in page.images %}
<img src="{{ site.baseurl }}/assets/{{ i }}" alt="Image tagged {{ page.tag }}">
{% endfor %}
Here, everything is in place to generate tags page.
We can now do a jekyll build and see the verbose output just tell us what to add in _data/imagesTagsLinks.yml
_data/imagesTagsLinks.yml
tag1: /tag/tag1/
tag2: /tag/tag2/
...
We can now link to our tag page from everywhere with a simple
{% for t in site.data.imagesTagsLinks %}
<li>{{ t[0] }}</li>
{% endfor %}
I've told you : it's tricky. But It does the job.
Note: the img tag can be improved, and why not a figure tag ?

Error msg to user in django

I have an html page where user insert data and click on ok button.
When button click a python function is checking if everything is ok and in that case update my DB.
In one of the cases when a check is false I want to pop up a msg to the user letting him know the operation faild.
What I did is:
if a<b:
return render(request, 'main/error.html')
and in error.html I puted the error details.
However this is extrimly inconvinet as the page is changing to error.html.
I want to give this error msg as Messege box or something like that... so that it stays on the same page.
The thing is that from views.py I can't access the html page and ask it to pop a msg.
How can I pop up a msg when a condition is false?
You can use the messaging framework in order to display a message on your page:
Quite commonly in web applications, you need to display a one-time notification message (also known as “flash message”) to the user after processing a form or some other types of user input.
For this, Django provides full support for cookie- and session-based messaging, for both anonymous and authenticated users. The messages framework allows you to temporarily store messages in one request and retrieve them for display in a subsequent request (usually the next one). Every message is tagged with a specific level that determines its priority (e.g., info, warning, or error).
There is extensive documentation and examples on the link provided.
EDIT: Example
Summary of settings (settings.py):
INSTALLED_APPS = (
...
'django.contrib.sessions',
'django.contrib.messages',
...
)
MIDDLEWARE_CLASSES = (
...
'django.contrib.sessions.middleware.SessionMiddleware',
...
'django.contrib.messages.middleware.MessageMiddleware',
...
)
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [
os.path.join(BASE_DIR, 'templates'),
],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
...
'django.contrib.messages.context_processors.messages',
],
'debug': True,
},
},
]
In a view:
from django.contrib import messages
if a < b:
messages.warning("a is less than b.")
In a template (example using bootstrap3):
{% if messages %}
<div class="messages">
{% for message in messages %}
<div class="alert alert-{{ message.tags }} alert-dismissible" role="alert">
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
{{ message }}
</div>
{% endfor %}
</div>
{% endif %}