• Как сделать хлебные крошки как в админке?

    можно сделать так. В base.html прописать блок для хлебных крошек.
    {% block breadcrumbs %}
        <div class="breadcrumb"><a href="/">Главная</a></div>
    {% endblock %}

    К примеру есть Каталог Статей и отдельный просмотр Статьи. И шаблоны для них articles.html и article.html
    articles.html
    {% extends 'base.html' %}
    
    {% block breadcrumbs %}
        {{ block.super }}
        <div class="breadcrumb"><a href="{% url 'articles:articles' %}">Каталог статей</a></div>
    {% endblock %}


    article.html
    {% 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 %}
    Ответ написан
    Комментировать
  • NoReverseMatch?

    Для начала, надо внимательнее читать. Тут есть описание polls/urls.py, сравните со своими урлами.
    Ответ написан
    5 комментариев
  • Как загрузить изображение с формы в django?

    Название класса class User_profile в pep8 написано следущее:
    Class names should normally use the CapWords convention.

    По поводу ошибки с urllib ответил Alexander .
    Вторая проблема заключается в магии которая происходит в коде.
    Форму SignupForm лучше не делать полностью ручками, а унаследовать от
    from django.contrib.auth.forms import UserCreationForm

    Так же эту форму лучше разбирь на две, соответственно первая относится к User, а вторая к UserProfile(или User_profile, но так не по pep8)
    Сохранение аватарки оставить на Джангу, для этого надо немного поправить модель
    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()

    Далее сделать привожу две формы, которые получились после разделения SignupForm
    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')

    в settings.py надо добавить пути ко всем медиа файлам
    STATIC_URL = '/static/'
    STATIC_ROOT = os.path.join(PROJECT_DIR, 'static')
    
    MEDIA_ROOT = os.path.join(PROJECT_DIR, 'media')
    MEDIA_URL = '/media/'

    Мда, все сюда выкатывать не хочется.
    Сделал репозиторий, можно посмотреть тут
    Ответ написан
  • Как сохранить из формы в модель несколько картинок?

    В одну модель сохранить несколько кортинок нельзя(если поле для картинок одно).
    Для сохранения картинок нужно создать новую модель.
    models.py
    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/')

    forms.py
    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()

    views.py
    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})
    Ответ написан
    7 комментариев
  • Как загрузить файл в django с кириллическим названием?

    возможно это не самый разумный способ, но для быстрого решения подойдет.
    Смысл в переписывании родных-джанговских upload handlor'ов
    в settings.py
    FILE_UPLOAD_HANDLERS = (
        'название_аппликейшена.uploadhandler.MemoryFileUploadHandler',
        'название_аппликейшена.uploadhandler.TemporaryFileUploadHandler',
    )

    И соответственно uploadhandler.py
    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
            )
    Ответ написан
    Комментировать
  • Как перезагрузить python (DJANGO) на сервере и обновить данные на сервере после push??

    Можно воспользоваться готовым приложением www.fabfile.org/installing.html (https://github.com/fabric/fabric)
    Суть в том, что нужно написать скрипт с поочередным выполнением команд.
    Вот как реализовано у меня.
    На сервере стоит nginx + uwsgi. (установка тут https://habrahabr.ru/post/226419/)
    В файле uwsgi.ini добавлена строка (на хабре из ссылки выше этот файл называется mysite_uwsgi.ini)
    # reload uwsgi
    touch-reload=/opt/sitename/reload.txt

    В директории с проектом лежит файл fabfile.py с содержимым
    #!/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 с параметром выполняемого таска из fabfile
    fab deploy
    Ответ написан
    Комментировать
  • Как менять TEMPLATE_DIRS?

    Для подобного можно добавить middleware.py подобного содержания
    # -*- 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'] = ['новая директория с шаблонами']


    И добавить этот middleware в settings.py в MIDDLEWARE_CLASSES
    Ответ написан
    Комментировать