initial
This commit is contained in:
parent
739e472a22
commit
a098b95670
0
__init__.py
Normal file
0
__init__.py
Normal file
7
admin.py
Normal file
7
admin.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from django.contrib import admin
|
||||
|
||||
from .models import Post
|
||||
|
||||
admin.site.register(Post
|
||||
)
|
||||
# Register your models here.
|
7
apps.py
Normal file
7
apps.py
Normal file
|
@ -0,0 +1,7 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ImagehostConfig(AppConfig):
|
||||
name = 'imagehost'
|
15
forms.py
Normal file
15
forms.py
Normal file
|
@ -0,0 +1,15 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django import forms
|
||||
from .models import Post
|
||||
|
||||
class PostForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = ('name', 'file')
|
||||
class DeleteForm(forms.ModelForm):
|
||||
|
||||
class Meta:
|
||||
model = Post
|
||||
fields = []
|
0
imagehost/__init__.py
Normal file
0
imagehost/__init__.py
Normal file
135
imagehost/settings.py
Normal file
135
imagehost/settings.py
Normal file
|
@ -0,0 +1,135 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
"""
|
||||
Django settings for mysite project.
|
||||
|
||||
Generated by 'django-admin startproject' using Django 1.9.7.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.9/ref/settings/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
|
||||
# Quick-start development settings - unsuitable for production
|
||||
# See https://docs.djangoproject.com/en/1.9/howto/deployment/checklist/
|
||||
|
||||
# SECURITY WARNING: keep the secret key used in production secret!
|
||||
SECRET_KEY = '1a+3jmf#g!q_gj66$^v9_&8uoev=%k49=j(%lp%!kvv$6x3bn^'
|
||||
|
||||
# SECURITY WARNING: don't run with debug turned on in production!
|
||||
DEBUG = True
|
||||
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
|
||||
# Application definition
|
||||
|
||||
INSTALLED_APPS = [
|
||||
'django.contrib.admin',
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.sessions',
|
||||
'django.contrib.messages',
|
||||
'django.contrib.staticfiles',
|
||||
'imagehosting'
|
||||
]
|
||||
|
||||
MIDDLEWARE_CLASSES = [
|
||||
'django.middleware.security.SecurityMiddleware',
|
||||
'django.contrib.sessions.middleware.SessionMiddleware',
|
||||
'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',
|
||||
]
|
||||
|
||||
ROOT_URLCONF = 'imagehosting.urls'
|
||||
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [],
|
||||
'APP_DIRS': True,
|
||||
'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',
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
WSGI_APPLICATION = 'mysite.wsgi.application'
|
||||
|
||||
|
||||
# Database
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#databases
|
||||
|
||||
DATABASES = {
|
||||
'default': {
|
||||
'ENGINE': 'django.db.backends.sqlite3',
|
||||
'NAME': os.path.join(BASE_DIR, '../db.sqlite3'),
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
# Password validation
|
||||
# https://docs.djangoproject.com/en/1.9/ref/settings/#auth-password-validators
|
||||
|
||||
AUTH_PASSWORD_VALIDATORS = [
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
|
||||
},
|
||||
{
|
||||
'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
# Internationalization
|
||||
# https://docs.djangoproject.com/en/1.9/topics/i18n/
|
||||
|
||||
LANGUAGE_CODE = 'ru-RU'
|
||||
USE_I18N = True
|
||||
|
||||
TIME_ZONE = 'Europe/Moscow'
|
||||
|
||||
|
||||
USE_I18N = True
|
||||
|
||||
USE_L10N = True
|
||||
|
||||
USE_TZ = True
|
||||
|
||||
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.9/howto/static-files/
|
||||
|
||||
PROJECT_ROOT = os.path.dirname(os.path.abspath(__file__))
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.join(BASE_DIR, 'static')
|
||||
|
||||
ADMIN_TOOLS_MENU = 'myproject.menu.CustomMenu'
|
||||
ADMIN_TOOLS_INDEX_DASHBOARD = 'myproject.dashboard.CustomIndexDashboard'
|
||||
ADMIN_TOOLS_APP_INDEX_DASHBOARD = 'myproject.dashboard.CustomAppIndexDashboard'
|
||||
|
||||
MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
|
||||
MEDIA_URL = '/media/'
|
28
imagehost/urls.py
Normal file
28
imagehost/urls.py
Normal file
|
@ -0,0 +1,28 @@
|
|||
"""mysite URL Configuration
|
||||
|
||||
The `urlpatterns` list routes URLs to views. For more information please see:
|
||||
https://docs.djangoproject.com/en/1.9/topics/http/urls/
|
||||
Examples:
|
||||
Function views
|
||||
1. Add an import: from my_app import views
|
||||
2. Add a URL to urlpatterns: url(r'^$', views.home, name='home')
|
||||
Class-based views
|
||||
1. Add an import: from other_app.views import Home
|
||||
2. Add a URL to urlpatterns: url(r'^$', Home.as_view(), name='home')
|
||||
Including another URLconf
|
||||
1. Import the include() function: from django.conf.urls import url, include
|
||||
2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls'))
|
||||
"""
|
||||
from django.conf.urls import url, include, patterns
|
||||
from django.contrib import admin
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
from django.views.generic.base import TemplateView
|
||||
urlpatterns = patterns('',
|
||||
url(r'^admin/', admin.site.urls),
|
||||
url(r'^$', TemplateView.as_view(template_name='main.html')),
|
||||
url(r'^blog/', include('blog.urls')),
|
||||
url(r'^polls/', include('polls.urls', namespace="polls")),
|
||||
url(r'^imagehost/', include('imagehost.urls')),
|
||||
url(r'^pfm/', include('pfm.urls')),
|
||||
) + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
|
17
imagehost/wsgi.py
Normal file
17
imagehost/wsgi.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""
|
||||
WSGI config for mysite project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.9/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
|
||||
|
||||
application = get_wsgi_application()
|
10
manage.py
Normal file
10
manage.py
Normal file
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env python
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "mysite.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
41
models.py
Normal file
41
models.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
from __future__ import unicode_literals
|
||||
from django.db import models
|
||||
from django.utils import timezone
|
||||
from ih import images
|
||||
import os
|
||||
|
||||
class Post(models.Model):
|
||||
name = models.CharField(max_length=30, blank=True)
|
||||
file = models.FileField(upload_to='images')
|
||||
# thumb = models.CharField(max_length=32, null=True, blank=True)
|
||||
|
||||
def publish(self):
|
||||
self.published_date = timezone.now()
|
||||
print(self.__dict__)
|
||||
self.save()
|
||||
|
||||
def __unicode__(self):
|
||||
return self.name
|
||||
|
||||
def thumb_name(self):
|
||||
x = str(self.file)
|
||||
t = x.split('/')
|
||||
|
||||
return '/thumb_' + t[1]
|
||||
|
||||
thumb_name = property(thumb_name)
|
||||
|
||||
def orig_name(self):
|
||||
x = str(self.file)
|
||||
return x.split('/')[1]
|
||||
orig_name = property(orig_name)
|
||||
|
||||
'''def resize_image(self.file):
|
||||
path, file_long = os.path.split(self.file)
|
||||
|
||||
im=image.open(file_long)
|
||||
size = 128, 128
|
||||
im.thumbnail(size)
|
||||
im.save(thumb_name)
|
||||
property(resize_image)'''
|
18
templates/imagehost/all.html
Normal file
18
templates/imagehost/all.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% load pagination_tags %}
|
||||
|
||||
{% block content%}
|
||||
<div style="display: flex; width: 101%; flex-wrap: wrap; justify-content: space-between; ">
|
||||
{% for image in all %}
|
||||
<div class="block" style="margin-bottom: 1em; width: 20em; height: 20em; padding: 0.5em; float: left; position:relative; flex-wrap: wrap; ">
|
||||
<a href="{% url 'image_detail' pk=image.pk %}"><img style="position: absolute; bottom: 1em; right: 1em; " src="/media/images{{ image.thumb_name }}" padding=3%></a>
|
||||
<span style="display:inline-block; position:absolute;top:30px; left:0px; background-color:rgba(230, 230, 230,.4); padding:10px 30px;" >
|
||||
<a href="{% url 'image_detail' pk=image.pk %}">{{ image.name }}</a></span>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
|
||||
{% endblock content %}
|
||||
|
||||
|
38
templates/imagehost/base.html
Normal file
38
templates/imagehost/base.html
Normal file
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<link href="https://fonts.googleapis.com/css?family=Open+Sans" rel="stylesheet">
|
||||
<link href="https://fonts.googleapis.com/css?family=Josefin+Sans:600" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.3.0/css/font-awesome.min.css">
|
||||
|
||||
<style>
|
||||
body {margin: 0}
|
||||
.header {dispaly: block;
|
||||
color: black ;
|
||||
background: linear-gradient(#f3f3f3, #e0e0e0);
|
||||
//height: 50px;
|
||||
padding: 10px 25px;
|
||||
font-size: 30px
|
||||
}
|
||||
.menu-icon {
|
||||
display: inline-block;
|
||||
float: right;
|
||||
//color: #696969;
|
||||
color: black;
|
||||
padding: 1px;
|
||||
}
|
||||
.logo {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
color: #696969;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class='header'> <span class='logo'>LOGO </span> <a class='menu-icon' href =""><i class="fa fa-bars"></i></a> </div>
|
||||
{% block content %}
|
||||
{% endblock%}
|
||||
</body>
|
||||
</html>
|
62
templates/imagehost/carousel.html
Normal file
62
templates/imagehost/carousel.html
Normal file
|
@ -0,0 +1,62 @@
|
|||
{% load staticfiles %}
|
||||
<html>
|
||||
<head>
|
||||
<title>Gallery</title>
|
||||
</head>
|
||||
<body>
|
||||
<nav>
|
||||
<div class="nav-wrapper teal lighten-2">
|
||||
<a class="brand-logo" href="/">Gallery</a>
|
||||
</div>
|
||||
<div class="nav-wrapper teal lighten-2">
|
||||
|
||||
<ul class="right">
|
||||
<li><a href="/pfm">PFM</a>
|
||||
<li><a class="dropdown-button" href="#1" data-activates="dropdown1">Notes</a><ul id="dropdown1" class="dropdown-content"></li> <li> <a href="{% url 'blog.views.post_new' %}">new post</a></li> <li><a href="/blog/1">all notes</a></li></ul>
|
||||
<li><a class="dropdown-button" href="#2" data-activates="dropdown2">Imagehost</a><ul id="dropdown2" class="dropdown-content"></li><li> <a href="{% url 'imagehost.views.image_new' %}">new image</a></li> <li> <a href="{% url 'imagehost.views.all_posts' %}"><span>all images</span></a></li></ul>
|
||||
<li><a href="/admin">/admin</a></li>
|
||||
|
||||
</ul></div></nav>
|
||||
|
||||
|
||||
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.0/jquery-ui.js"></script>
|
||||
<script type="text/javascript" src="/js/materialize.min.js"></script>
|
||||
<script type="text/javascript">
|
||||
$(document).ready(function(){
|
||||
$('.carousel').carousel({ shift: 20 });
|
||||
$('.materialboxed').materialbox();
|
||||
$(".dropdown-button").dropdown();
|
||||
|
||||
});
|
||||
</script>
|
||||
<!--Import Google Icon Font>
|
||||
<link href="http://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"-->
|
||||
<!--Import materialize.css-->
|
||||
<link type="text/css" rel="stylesheet" href="/css/materialize.min.css" media="screen,projection">
|
||||
|
||||
<!--Let browser know website is optimized for mobile-->
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<div class="card-panel teal lighten-5">
|
||||
|
||||
<div class="carousel">
|
||||
{% for image in all %}
|
||||
<a href="{% url 'image_detail' pk=image.pk %}"--> <a class="carousel-item"><img width="650" src="/media/images{{ image.thumb_name }}" ></a>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-panel teal lighten-5">
|
||||
<div class="row" style="display: flex; flex-wrap: wrap;">
|
||||
{% for image in all %}
|
||||
<div class="col s12 m6 l3">
|
||||
<div class="card blue-grey darken-1"> <div class="card-content"> <img class="thumbnail" src="/media/images{{ image.thumb_name }}" ></a> </div>
|
||||
<div class="card-action white-text"><a href="{% url 'image_detail' pk=image.pk %}">{{ image.name }}</a></div>
|
||||
</div>
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="card-panel s1 teal lighten-5">1</div>
|
||||
</div>
|
10
templates/imagehost/delete.html
Normal file
10
templates/imagehost/delete.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div> <h1>Delete</h1>
|
||||
<form method="POST">{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<button type="submit" class="save btn btn-default">delete</button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
13
templates/imagehost/image.html
Normal file
13
templates/imagehost/image.html
Normal file
|
@ -0,0 +1,13 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="block" style="position: relative; ">
|
||||
|
||||
<p><a href="/media/{{post.file}}"><img src="/media/images{{ post.thumb_name }}" padding=3%></a></p>
|
||||
<p><a href="/media/{{post.file}}" download> {{ post.name }} скачать </a></p>
|
||||
|
||||
<spam class="edit" style="position: absolute; bottom: 20px; right: 20px;"><a href="{% url 'delete_post' pk=post.pk %}">удалить</a></span>
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
|
10
templates/imagehost/index.html
Normal file
10
templates/imagehost/index.html
Normal file
|
@ -0,0 +1,10 @@
|
|||
{% extends 'base.html' %}
|
||||
|
||||
{% block content %}
|
||||
<div class="block">
|
||||
<form method="POST" class="post-form" enctype="multipart/form-data" action="" >{% csrf_token %}
|
||||
{{ form.as_p }}
|
||||
<input type="submit" value="send" class="save btn btn-default"></button>
|
||||
</form>
|
||||
</div>
|
||||
{% endblock %}
|
3
tests.py
Normal file
3
tests.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
13
urls.py
Normal file
13
urls.py
Normal file
|
@ -0,0 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.conf.urls import url
|
||||
from . import views
|
||||
from django.conf import settings
|
||||
from django.conf.urls.static import static
|
||||
urlpatterns = [
|
||||
url(r'^$', views.image_new, name='image_new'),
|
||||
url(r'^post/(?P<pk>[0-9]+)/$', views.image_detail, name='image_detail'),
|
||||
url(r'^all/$', views.all_posts, name='all_posts'),
|
||||
url(r'^carousel/$', views.carousel, name='carousel'),
|
||||
url(r'^delete/(?P<pk>[0-9]+)/$', views.delete_post, name='delete_post')
|
||||
]
|
93
views.py
Normal file
93
views.py
Normal file
|
@ -0,0 +1,93 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
|
||||
from django.shortcuts import render, get_object_or_404, HttpResponseRedirect
|
||||
from .models import Post
|
||||
from .forms import PostForm, DeleteForm
|
||||
from django.shortcuts import redirect
|
||||
from ih import files, images
|
||||
from django.views.decorators.csrf import requires_csrf_token
|
||||
|
||||
'''def create_thumbnail(request):
|
||||
# Get file from <InMemoryUploadedFile>
|
||||
file_l, filename = files.get_file_from_request(request, 'file')
|
||||
fh = files.write_to_shm(file_l, filename)
|
||||
file_l = None
|
||||
|
||||
# Create thumbnail
|
||||
thumb_name = images.resize_image(fh, {
|
||||
'name': filename,
|
||||
'size': (100, 100),
|
||||
'dest': 'mysite/media/images'
|
||||
}
|
||||
|
||||
)
|
||||
print(thumb_name)
|
||||
# Remove file from shm
|
||||
e = files.rm_from_shm(filename)
|
||||
if e is not True:
|
||||
print "WARNING: " + e
|
||||
|
||||
return thumb_name'''
|
||||
|
||||
|
||||
def create_thumb_from_file(filename):
|
||||
orig_file = 'mysite/media/images/' + str(filename)
|
||||
|
||||
print(filename)
|
||||
# Create thumbnail
|
||||
print("DEBUG: Resizing image " + orig_file)
|
||||
thumb_name = images.resize_image(orig_file, {
|
||||
'name': filename,
|
||||
'size': [300, 300],
|
||||
'dest': 'mysite/media/images'
|
||||
}
|
||||
|
||||
)
|
||||
|
||||
return thumb_name
|
||||
|
||||
|
||||
|
||||
def image_new(request):
|
||||
if request.method == "POST":
|
||||
form = PostForm(request.POST, request.FILES)
|
||||
if form.is_valid():
|
||||
# thumb_name = create_thumbnail(request)
|
||||
post = form.save(commit=False)
|
||||
post.save()
|
||||
print("FILE: ", post.file)
|
||||
create_thumb_from_file(post.orig_name)
|
||||
return redirect('imagehost.views.image_detail', pk=post.id)
|
||||
else:
|
||||
form = PostForm()
|
||||
return render(request, 'imagehost/index.html', {'form': form})
|
||||
|
||||
|
||||
def image_detail(request, pk):
|
||||
post = get_object_or_404(Post, pk=pk)
|
||||
print(post)
|
||||
return render(request, 'imagehost/image.html', {'post': post})
|
||||
|
||||
|
||||
def all_posts(request):
|
||||
all = Post.objects.order_by('-pk')
|
||||
page = request.POST.get("page")
|
||||
return render(request, 'imagehost/all.html', {'all': all})
|
||||
|
||||
def carousel(request):
|
||||
return render(request, 'imagehost/carousel.html', {'all': Post.objects.all()})
|
||||
|
||||
@requires_csrf_token
|
||||
def delete_post(request, pk):
|
||||
post_to_delete = get_object_or_404(Post, pk=pk)
|
||||
if request.method == 'POST':
|
||||
form = DeleteForm(request.POST, instance=post_to_delete)
|
||||
if form.is_valid(): # checks CSRF
|
||||
if not request.user.is_authenticated():
|
||||
return HttpResponseRedirect('/admin')
|
||||
post_to_delete.delete()
|
||||
return redirect('imagehost.views.all_posts')
|
||||
else:
|
||||
form = DeleteForm(instance=post_to_delete)
|
||||
|
||||
return render(request, 'imagehost/delete.html', {'form': form})
|
Loading…
Reference in New Issue
Block a user