{% block breadcrumbs %}
<div class="breadcrumb"><a href="/">Главная</a></div>
{% endblock %}
{% extends 'base.html' %}
{% block breadcrumbs %}
{{ block.super }}
<div class="breadcrumb"><a href="{% url 'articles:articles' %}">Каталог статей</a></div>
{% endblock %}
{% extends 'articles.html' %}
{% block breadcrumbs %}
{{ block.super }}
<div class="breadcrumb"><a href="{% url 'articles:article_view' article_id=article.id %}">{{ article.title }}</a></div>
{% endblock %}
Class names should normally use the CapWords convention.
from django.contrib.auth.forms import UserCreationForm
import os
from django.contrib.auth.models import User
from django.db import models
def avatar_upload_to(instance, filename):
return os.path.join('uploads', instance.user.username + os.path.splitext(filename)[1])
class UserProfile(models.Model):
user = models.OneToOneField(User, unique=True)
avatar = models.ImageField(upload_to=avatar_upload_to)
info = models.TextField()
from django import forms
from django.contrib.auth.forms import UserCreationForm
from django.contrib.auth.models import User
from accounts.models import UserProfile
class SignupForm(UserCreationForm):
username = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'login', }),
max_length=30, label=u'Логин'
)
email = forms.EmailField(
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Ваша почта', }),
required=True, max_length=254, label=u'E-mail',
)
password1 = forms.CharField(
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '*****'}),
min_length=6, label=u'Пароль'
)
password2 = forms.CharField(
widget=forms.PasswordInput(attrs={'class': 'form-control', 'placeholder': '*****'}),
min_length=6, label=u'Повторите пароль'
)
class Meta:
model = User
fields = ('username', 'email')
class UserProfileSignupForm(forms.ModelForm):
info = forms.CharField(
widget=forms.TextInput(attrs={'class': 'form-control', 'placeholder': u'Молод и горяч',}),
required=False, label=u'Пара слов о себе'
)
avatar = forms.FileField(
widget=forms.ClearableFileInput(attrs={'class': 'ask-signup-avatar-input',}),
required=False, label=u'Аватар'
)
def clean_avatar(self):
avatar = self.cleaned_data.get('avatar')
if avatar is None:
raise forms.ValidationError(u'Добавьте картинку')
if 'image' not in avatar.content_type:
raise forms.ValidationError(u'Неверный формат картинки')
return avatar
class Meta:
model = UserProfile
fields = ('info', 'avatar')
STATIC_URL = '/static/'
STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
MEDIA_URL = '/media/'
class Advert(models.Model):
category = models.TextField()
title = models.CharField(max_length=64)
description = models.CharField(max_length=900)
date = models.DateTimeField(auto_now_add=True, null=True)
class AdvertImage(models.Model):
advert = models.ForeignKey(Advert)
photo = models.ImageField(upload_to='uploads/')
class AddAdvertForm(ModelForm):
class Meta:
model = Advert
fields = '__all__'
class AdvertImagesForm(forms.Form):
photos = forms.FileField(widget=widgets.FileInput(attrs={'multiple': True}))
def __init__(self, *args, **kwargs):
if 'request' in kwargs:
self.request = kwargs.pop('request')
super(AdvertImagesForm, self).__init__(*args, **kwargs)
def clean_photos(self):
# Остаются только картинки
photos = [photo for photo in self.request.FILES.getlist('photos') if 'image' in photo.content_type]
# Если среди загруженных файлов картинок нет, то исключение
if len(photos) == 0:
raise forms.ValidationError(u'Not found uploaded photos.')
return photos
def save_for(self, advert):
for photo in self.cleaned_data['photos']:
AdvertImage(photo=photo, advert=advert).save()
class CreateAdvertView(View):
template_name = 'bulletinboard/add_advert.html'
form_class = AddAdvertForm
form_images_class = AdvertImagesForm
model = Advert
def get(self, request):
form = self.form_class()
form_images = self.form_images_class()
return render(request, self.template_name, {'form': form, 'form_images': form_images})
def post(self, request):
form = self.form_class(request.POST)
form_images = self.form_images_class(request.POST, request.FILES, request=request)
if form.is_valid() and form_images.is_valid():
advert = form.save()
form_images.save_for(advert)
return HttpResponseRedirect('/')
return render(request, self.template_name, {'form': form, 'form_images': form_images})
FILE_UPLOAD_HANDLERS = (
'название_аппликейшена.uploadhandler.MemoryFileUploadHandler',
'название_аппликейшена.uploadhandler.TemporaryFileUploadHandler',
)
from io import BytesIO
import os
from django.core.files.uploadedfile import TemporaryUploadedFile, InMemoryUploadedFile
from django.core.files.uploadhandler import FileUploadHandler, StopFutureHandlers
from django.conf import settings
import pytils
import re
def translify(value):
value = pytils.translit.translify(u"%s" % value)
value = re.sub("[\W]", "_", value.strip())
return value
def transliteration_file_name(file_name):
name, ext = os.path.splitext(file_name)
return '{0}{1}'.format(translify(name), ext)
class TemporaryFileUploadHandler(FileUploadHandler):
"""
Upload handler that streams data into a temporary file.
"""
def __init__(self, *args, **kwargs):
super(TemporaryFileUploadHandler, self).__init__(*args, **kwargs)
def new_file(self, field_name, file_name, content_type, content_length, charset=None, content_type_extra=None):
file_name = transliteration_file_name(file_name)
super(TemporaryFileUploadHandler, self).new_file(field_name, file_name, content_type,
content_length, charset, content_type_extra)
self.file = TemporaryUploadedFile(self.file_name, self.content_type, 0, self.charset, self.content_type_extra)
def receive_data_chunk(self, raw_data, start):
self.file.write(raw_data)
def file_complete(self, file_size):
self.file.seek(0)
self.file.size = file_size
return self.file
class MemoryFileUploadHandler(FileUploadHandler):
"""
File upload handler to stream uploads into memory (used for small files).
"""
def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
"""
Use the content_length to signal whether or not this handler should be in use.
"""
# Check the content-length header to see if we should
# If the post is too large, we cannot use the Memory handler.
if content_length > settings.FILE_UPLOAD_MAX_MEMORY_SIZE:
self.activated = False
else:
self.activated = True
def new_file(self, field_name, file_name, content_type, content_length, charset=None, content_type_extra=None):
file_name = transliteration_file_name(file_name)
super(MemoryFileUploadHandler, self).new_file(field_name, file_name, content_type,
content_length, charset, content_type_extra)
if self.activated:
self.file = BytesIO()
raise StopFutureHandlers()
def receive_data_chunk(self, raw_data, start):
"""
Add the data to the BytesIO file.
"""
if self.activated:
self.file.write(raw_data)
else:
return raw_data
def file_complete(self, file_size):
"""
Return a file object if we're activated.
"""
if not self.activated:
return
self.file.seek(0)
return InMemoryUploadedFile(
file=self.file,
field_name=self.field_name,
name=self.file_name,
content_type=self.content_type,
size=file_size,
charset=self.charset,
content_type_extra=self.content_type_extra
)
# reload uwsgi
touch-reload=/opt/sitename/reload.txt
#!/usr/bin/python
# -*- coding: UTF-8 -*-
from fabric.api import env, run, cd
env.hosts = ['user@host', ]
#Структура такая
# /
# + opt/
# + sitename/
# + env/ тут virtualenv
# + source/ тут лежит код
project_path = '/opt/sitename/'
source_path = '/opt/sitename/source/'
branch = ''
# Скрипт деплоя
def deploy():
# выполняются комманды для загрузки данных из репозитория
with cd(source_path):
run('mkdir -p tmp/')
run('hg pull')
run('hg update %s' % branch)
# после загрузки репозитория
# устанавливаются пакеты перечисленные в req.txt
# производятся миграции
# собирается статика
# теребим файл reload.txt, чтобы оповестить uwsgi об обновлении
with cd(project_path):
run('env/bin/pip install -r %sreq.txt' % source_path)
run('env/bin/python %smanage.py migrate' % source_path)
run('env/bin/python %smanage.py collectstatic --noinput' % source_path)
# run('env/bin/python %smanage.py compress' % source_path)
run('touch reload.txt')
fab deploy
# -*- coding: UTF-8 -*-
from django.conf import settings
class NewStyleTemplateDir(object):
@staticmethod
def process_request(request):
if request.GET.get('new_style'):
settings.TEMPLATES[0]['DIRS'] = ['новая директория с шаблонами']