желательно, из коллекций Google Font
Какой рукописный шрифт использовать
Причём интересует не только кириллица, но и латиница (даже без поддержки русского). Ещё, желательно, из коллекций Google Font.
Ожидаемая нагрузка, например, +1500 активных уников в месяцэто не большие нагрузки
User
+ свою модель Profile
, подключённую через OneToOneField
. В ней можно собирать все необходимые свойства. Что мешает модератору сайта одновременно быть покупателем футболочек? Собственно ничего.is_staff
. Посмотрите django-braces
. Вам достаточно использовать class based views и подключать нужные mixins, - и вы забудете об этих проверках: большая их часть будет выполняться в mixins, а не в бизнес-логике предметной области. Вы можете и свои классы для этого дела написать. django.contrib.auth.models.AbstractUser
, а различие между пользователями определять либо по группе/разрешениям, либо добавить поле в свою модель типа is_moderator
. Это будет во много раз (на порядок точно) проще реализовать и поддерживать, будет совместимость со всем стандартным кодом Django и сторонними библиотеками, любому просто войти в проект и внести изменения.window.VK = {Share:{}}
class Vkontakte {
constructor(url = document.location.href) {
this.url = encodeURIComponent(url);
}
getCounter() {
let count_url = 'https://vk.com/share.php?act=count&index=1&url=' + this.url;
window.VK.Share.count = (_, counter) => {
console.log(counter)
script.parentNode.removeChild(script)
}
let script = document.createElement('script')
script.src = count_url
document.body.appendChild(script)
};
}
new Vkontakte().getCounter();
class Tumblr {
constructor(url = document.location.href) {
this.url = encodeURIComponent(url);
}
getCounter() {
let callback = ('cb_' + Math.random()).replace('.', '')
let count_url = 'https://api.tumblr.com/v2/share/stats?url=' + this.url +
'&callback=' + callback;
window[callback] = function(counter) {
console.log(counter.response.note_count)
script.parentNode.removeChild(script)
}
let script = document.createElement('script')
script.src = count_url
document.body.appendChild(script)
};
}
new Tumblr().getCounter();
getCounter(cb) {
let xhr = new XMLHttpRequest();
let api = 'https://vk.com/share.php?act=count&index=1&url=' + encodeURIComponent(this.url);
xhr.open('GET', api, true);
xhr.send();
xhr.onreadystatechange = () => {
if (this.readyState != 4) return;
if (this.status != 200) {
console.log('Vkontakte provider error: ' + (this.status ? this.statusText : 'response not send!'));
return;
}
let obj = this.responseText.match(/^VK\.Share\.count\(\d, (\d+)\);$/)[1] / 1;
cb(obj);
}
}
new Vkontakte().getCounter(count => console.log(count));
getCounter() {
return new Promise((resolve, reject) => {
let xhr = new XMLHttpRequest();
let api = 'https://vk.com/share.php?act=count&index=1&url=' + encodeURIComponent(this.url);
xhr.open('GET', api, true);
xhr.send();
xhr.onreadystatechange = () => {
if (this.readyState != 4) return;
if (this.status != 200) {
console.log('Vkontakte provider error: ' + (this.status ? this.statusText : 'response not send!'));
return;
}
let obj = this.responseText.match(/^VK\.Share\.count\(\d, (\d+)\);$/)[1] / 1;
resolve(obj);
}
});
}
new Vkontakte().getCounter().then(count => console.log(count));
deleteArticle: function (url) {
let self = this;
swal({
title: "Are you sure?",
text: "You will not be able to recover this imaginary file!",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!",
closeOnConfirm: false
}, function () {
self.$http.delete(url, function () {
swal("Deleted!", "Your imaginary file has been deleted.", "success");
});
});
}
<a href="#"
v-on:click="deleteArticle()">Удалить</a>
window.Laravel = <?= json_encode([
'base_url' => url(),
'article' => isset($article) ? $article->toArray() : null,
]); ?>
var article_form = new Vue({
el: '#article_form',
data: {
delete_url: window.Laravel.base_url + '/article/' + window.Laravel.article.id + '/delete'
},
methods: {
deleteArticle: function () {
var self = this;
swal({
title: "Are you sure?",
text: "You will not be able to recover this imaginary file!",
type: "warning",
showCancelButton: true,
confirmButtonColor: "#DD6B55",
confirmButtonText: "Yes, delete it!",
closeOnConfirm: false
}, function () {
self.$http.delete(self.delete_url, function () {
swal("Deleted!", "Your imaginary file has been deleted.", "success");
});
});
}
}
});
window.$ = document.querySelectorAll.bind(document)