Ответы пользователя по тегу Django
  • Можно ли сделать модели относительно зависимыми друг от друга с обеих сторон?

    @javedimka
    Хочу сока
    Конечно можно сделать, переопредели метод save() на модели Question таким образом, чтобы перед сохранением он получал связанный объект Test и инкрементировал поле questions_amount .

    А лучше забудь эту идею и сделай по-нормальному, через аггрегации:
    https://docs.djangoproject.com/en/dev/topics/db/ag...
    Ответ написан
  • Как реализовать работу парсера на сайте?

    @javedimka
    Хочу сока

    Запустить две программы, в одном будет django проект с сайтом, на втором будет сидеть парсер, который будет получать данные и записывать их в бд. А сайт будет выгружать из бд и показывать их у себя. Но это придется запускать две консоли одновременно.

    Про systemd слышал? Ну или хотя бы про service?
    Или у тебя сайт работает ровно до тех пор пока у тебя ssh сессия открыта до твоего сервера?

    Нужен отдельный демон, который парсит данные и складывает в БД.
    Ответ написан
  • Своя система авторизации в джанго?

    @javedimka
    Хочу сока
    1) Скорее всего есть. Разница в качестве исполнения, скорее всего разница существенна и не в твою пользу.
    2) Так, как того требует проект, если требования у проекта без извращений - то в документации джанги все написано про реализации аутентификаций и авторизаций.
    3) Использовать встроенные в django вьюшки, которые были сделаны специально для этой задачи.

    https://docs.djangoproject.com/en/3.1/topics/auth/...
    https://docs.djangoproject.com/en/3.1/topics/auth/...
    https://docs.djangoproject.com/en/3.1/topics/auth/...
    Ответ написан
  • DRF что по ViewSet?

    @javedimka
    Хочу сока
    Использовать нужно то, что соответствует твоим потребностям. Нужна самая простая и обычная функциональность - используй вью сет. Нужно что-то посложнее - используй то, что лежит на уровне ниже.
    Ответ написан
  • Как вывести дерево категорий на Django?

    @javedimka
    Хочу сока
    Когда-то давно я сделал так. Получив удовлетворение я скачал django-mptt и переделал на mptt

    # Example model
    class Category(models.Model):
        parent = models.ForeignKey('Category',
                                   on_delete=models.CASCADE,
                                   verbose_name=_('Parent'),
                                   related_name='children',
                                   blank=True,
                                   null=True)
        title = models.CharField(_('Title'), max_length=64, unique=True)
        slug = models.SlugField(max_length=50)
        objects = CategoryManager()
    
        
    # Manager with method to build tree using directed graph
    class CategoryManager(models.Manager):
    
        def _traverse(self, hierarchy, graph, items):
            for item in items:
                hierarchy.append(item)
                hierarchy.append(self._traverse([], graph, graph[item.title]))
            return hierarchy
    
        def as_tree(self):
            """Returns FK hierarchy in form of nested lists."""
    
            qs = super().get_queryset().exclude(
                title='Unassigned'
            ).select_related('parent')
    
            roots = []
            children = []
            for item in qs:
                roots.append(item) if item.parent is None else children.append(item)
    
            graph = {item.title: set() for item in qs}
    
            sorted_children = sorted(children, key=lambda x: x.parent.title)
            grouped = groupby(children, key=lambda x: x.parent.title)
    
            for title, group in grouped:
                graph[title].update(group)
    
            return self._traverse([], graph, roots)
        
    
    # To render in template in form of simple nested unordered list use built-in filter:
    # https://docs.djangoproject.com/en/dev/ref/templates/builtins/#unordered-list
    
    {{ tree|unordered_lsit }}
    Ответ написан
  • Перевести символ после дефиса в верхний регистр?

    @javedimka
    Хочу сока
    По ссылке я конечно же переходить не буду, но:
    'санкт-петербург'.title()
    Ответ написан
  • Как исправить ошибку при записи в БД (связанные таблицы)?

    @javedimka
    Хочу сока
    К сожалению не помогло, ошибка та же:

    Вариант раз, подходит для вложенных сериалайзеров

    Пишешь два сериалайзера, один для GET, с твоим, расширенным представлением для связанного Place, другой для POST/PUT с стандартной реализацией которая сериализует связанный объект как его id, потом во вью возвращаешь либо первый либо второй, т.е.:

    class EventGETSerializer(serializers.ModelSerializer):
        place = PlaceSerializer(read_only=True)
        class Meta:
            model = Event
            fields = ('id', 'title', 'description', 'price', 'place', 'link', 'date', 'time')
    
    class EventSerializer(serializers.ModelSerializer):
        class Meta:
            model = Event
            fields = ('id', 'title', 'description', 'price', 'place', 'link', 'date', 'time')

    В вью переопределяешь get_serializer_class метод:
    from rest_framework import permissions
    
    
    class EventList(generics.ListCreateAPIView):
        queryset = Event.objects.all()
    
        def get_serializer_class(self):
            if self.request.method in permissions.SAFE_METHODS:
                return EventGETSerializer
            else:
                return EventSerializer



    update:
    Вариант два, странно работает, но не нарушает принципов DRY и возможно подходит если устраивает стандартное представление данных с depth=1

    Развивая тему с depth, решил попробовать:
    Без блока else не корректно себя ведет, не знаю почему.
    Необходимо использовать дженерики/вьюсеты или самому передавать объект запроса в сериалайзер.
    from rest_framework.permissions import SAFE_METHODS
    
    
    class EventSerializer(serializers.ModelSerializer):
    
        def __init__(self, *args, **kwargs):
            request = kwargs.get('context', {}).get('request')
            if request is not None and request.method not in SAFE_METHODS:
                self.Meta.depth = 0
            else:
                self.Meta.depth = 1
            super().__init__(*args, **kwargs)
    
        class Meta:
            model = Event
            fields = ('id', 'title', 'description', 'price', 'place', 'link',
                      'date', 'time')

    Ответ написан
  • Django: как установить запрет на удаление объекта через админку?

    @javedimka
    Хочу сока
    к тому же delete_model как и save нельзя использовать для блокирования удаления объекта, только для добавления действий до и после удаления.

    Это абсолютно не верно. Модель будет удалена если при переопределении этого метода явно вызвать super().delete_model(request, obj), иначе - нет.
    Можно сделать так чтобы messages framework не захватывал стандартное сообщение об успешном удалении которое посылается админкой с промежуточной страницы и добавить свое:

    from django.contrib import messages
    
    
    def delete_model(self, request, obj):
        """Если какая-то проверка успешна - удалить объект, если нет, то показать сообщение об ошибке."""
        if check_permission(obj):
            return super().delete_model(request, obj)
        # При следующем запросе захватываем только ошибки.
        # Так после нажатия на кнопку удаления не будет захвачено ложное сообщение
        # об успешном удалении.
        messages.set_level(request, messages.ERROR)
        message = "You cant delete this!"
        # Посылаем свое сообщение об ошибке.
        self.message_user(request, message, level=messages.ERROR)


    Ну еще сделать что-то с логированием, потому что "удаление" все равно попадет в "недавние действия" на главной странице админки, хоть объект и не был удален.
    Ответ написан
  • Как вывести таблицу в *.html?

    @javedimka
    Хочу сока
    Подготовить данные во вьюхе чтобы с ними было удобно работать в темплейте, я вот не понимаю зачем и список, и словарь когда можно сделать вложенный список типо такого:
    table = [
        ['header1', 'header2', 'header3', 'header4'],
        ['value1.1', 'value2.1', 'value3.1', 'value4.1'],
        ['value1.2', 'value2.2', 'value3.2', 'value4.2']
    ]


    C моделью даже подготавливать почти ничего не нужно:
    table = [('header1', 'header2', 'header3', 'header4')]
    table += Model.objects.all().values_list('value1', 'value2', 'value3', 'value4')
    context['table'] = table


    А потом в темплейте:
    <table>
    {% for v1, v2, v3, v4 in table %}
        {% if forloop.first %}
            <tr>
                <th>{{ v1 }}</th>
                <th>{{ v2 }}</th>
                <th>{{ v3 }}</th>
                <th>{{ v4 }}</th>
            </tr>
        {% else %}
            <tr>
                <td>{{ v1 }}</td>
                <td>{{ v2 }}</td>
                <td>{{ v3 }}</td>
                <td>{{ v4 }}</td>
            </tr>
        {% endif %}
    {% endfor %}
    </table>
    Ответ написан
  • Как реальные данные подставить в google chart?

    @javedimka
    Хочу сока
    Нужно передать аргументы в функцию
    function drawChart(chartData, lineChartId) {
    
            var data = new google.visualization.DataTable();
            data.addColumn('date', 'Time of Day');
            data.addColumn('number', 'KWR');
            data.addColumn('number', 'BSR');
    
            data.addRows(chartData);
    
    
            var options = {
                colors: ['#000000','#ff9000'],
                hAxis: {
                    format: 'M/d/yy',
                    gridlines: {count: 10}
                },
                vAxis: {
                    direction: -1
                }
            };
    
            var chart = new google.visualization.LineChart(document.getElementById(lineChartId));
    
            chart.draw(data, options);
        }
    Ответ написан
  • Как получить определенное значение из словаря в шаблоне django?

    @javedimka
    Хочу сока
    Чтобы узнать как правильно вытащить значения, надо сначала узнать почему они вообще приходят в таком неудобном виде, а если возможности узнать и исправить нету - преобразовать в более удобный вид, например во вложенные списки:
    def table_view(request):
        data = {'2A':
                ['Name', 'State',
                 'Name2', 'State2',
                 'Name3', 'State3',
                 'Name4', 'State4',
                 'Name5', 'State5']
                }
        data['2A'] = [data['2A'][i:i+2] for i in range(0, len(data['2A']), 2)]
        return render(request, 'app/template.html', {'students_data': data})


    И тогда в шаблоне:
    {% for student in data %}
    <tr>
        <input type="hidden" name="stud" value="{{ student.0 }}" />
        <td>{{student.0 }}</td>
        <input type="hidden" name="state" value="" class="state"/>
        <td id="editable">{{ student.1 }}</td>
    </tr>
    {% endfor %}

    или как вариант - использовать namedtuple, но что там по скорости будет не знаю.
    Ответ написан
  • Кто-то использовал prefix_default_language=False для удаления префикса языка?

    @javedimka
    Хочу сока
    У Джанго есть багтрекер ->
    https://code.djangoproject.com
    В форму поиска, prefix_default_language ->
    https://code.djangoproject.com/search?q=prefix_def...
    Можно приступать к изучению возможных проблем.
    Ответ написан
  • Проблемы в юнит тесте (Entry matching query does not exist)?

    @javedimka
    Хочу сока
    см. update
    Ошибка возникает при обработке сигнала pre_save. В тесте test_article_sorting() создается объект статьи, перед сохранением в бд посылается сигнал pre_save и выполняется функция delete_old_article_image, где в строчке
    article = Article.objects.get(pk=instance.pk)
    .get() метод пытается получить несуществующий объект статьи из бд и после этого рэйсит ошибку DoesNotExist
    Одно из нескольких возможных решений - обернуть в блок try/except:
    @receiver(pre_save, sender=Article)
    def delete_old_article_image(sender, instance, *args, **kwargs):
        if instance.pk:
            try:
                article = Article.objects.get(pk=instance.pk)
                if instance.image and article.image != instance.image:
                    slide.image.delete(False)
            except Article.DoesNotExist:
                pass

    Ну и естественно все это тоже надо покрыть тестами, тут их будет как минимум 3.

    UPDATE:

    Сегодня что-то вспомнил этот вопрос, еще раз открыл, понял почему на "продакшене" работало, а в тестах нет:
    Как я уже говорил, в тестах, ты создаешь объекты статьи с помощью шортката .create() который внутри себя создает объект obj с указанными тобою параметрами и вызывает save() для его сохранения в базу данных, отправляется сигнал pre_save, в хэндлер передается твой объект с имеющимся pk, выполняется твой код, условие if instance.pk срабатывает и начинается попытка получить несуществующий объект из базы, что оканчивается ошибкой.

    Почему работало на живом сайте? Вот почему:

    На "живом" сайте, когда ты создаешь новый объект, при его сохранении в хэндлер сигнала pre_save() передается instance с pk == None, так как primary key вешается самой базой данных после всех джанговских штучек, поэтому на этом этапе if instance.pk возвращало False и вложенный код не выполнялся.

    Когда же ты редактировал уже существующий объект при сохранении в хэндлер pre_save() передавался "уже имеющийся" в базе объект у которого есть pk и у которого, возможно, теперь слегка измененные данные (раз уж редактируем то что-то да меняем) что приводило к выполнению условия if instance.pk и выполнению вложенного кода который успешно получал уже существующий базе объект.

    Поэтому, решить проблему с тестами можно было просто убрав явное вешание pk из тестов, оставив эту работу бд:
    first_article = Article.objects.create(
        # pk=150,
        ...   
        )
    
    second_article = Article.objects.create(
        # pk=160,
        ...   
        )
    
    third_article = Article.objects.create(
       # pk=170,
       ...
       )
    
    data = {first_article.pk: 2, second_article.pk: 0, third_article.pk: 1}


    И instance.pk проверять следует так:
    @receiver(pre_save, sender=Article)
    def delete_old_article_image(sender, instance, *args, **kwargs):
        if instance.pk is not None:
                article = Article.objects.get(pk=instance.pk)
                if instance.image and article.image != instance.image:
                    slide.image.delete(False)
    Ответ написан
  • Как реализовать поиск по полному имени, имея два раздельных поля в базе (first_name, last_name)?

    @javedimka
    Хочу сока
    from django.db.models import Q 
    
    def find_user_by_name(query_name):
       qs = User.objects.all()
       for term in query_name.split():
         qs = qs.filter( Q(first_name__icontains = term) | Q(last_name__icontains = term))
       return qs

    stackoverflow.com/questions/9009635/django-queryse...

    Q objects

    Но вообще, если еще не поздно, я бы сделал одно поле full_name, first_name и last_name получал бы через методы модели, а поиск через icontains и проблем бы не было.
    Ответ написан
  • Как переопределить стиль форм в джанго?

    @javedimka
    Хочу сока
    Чтобы изменить стандартный вид отрисовки формы на твой собственный, можно переопределить метод __str__() формы:
    def __str__(self):
        return self.as_div()


    Второй вопрос какой-то очень не очень.
    html_class_attr - это строка которая генерируется в методе _html_output() на основе каких-то данных, каких - не знаю, надо копать глубже в сорцы, такое в доках не пишут.
    Ответ написан
  • При сохранении в админке записывать id юзера?

    @javedimka
    Хочу сока
    В общем дошел до дома, подробнее напишу. Если у тебя определено поле для юзера в модели, то ты его можешь вообще вручную выбрать, а если лень это делать то можно так.
    Допустим у тебя есть приложение для публикации статей "articles", в articles/models.py есть модель статьи, в которой есть поле с пользователем который ее добавил, можно добавить еще одно поле для пользователя который ее последний раз редактировал, а можно и не добавлять если нужен только пользователь добавивший статью:
    # остальные импорты опущены 
    from django.conf import settings
    
    
    class Article(models.Model):
        ...
        added_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
                                     related_name="articles_added")
        last_edited_by = models.ForeignKey(settings.AUTH_USER_MODEL, blank=True, null=True,
                                           related_name="articles_edited")
        ...

    Так как два поля ссылаются на одну модель, нужно определить для них related_name чтобы потом с помощью него можно было работать с ORM, типо чтобы получить все статьи добавленные пользователем:
    *объект_нужного_пользователя*.articles_added.all()

    Потом в файле articles/admin.py определяешь новую модель для "администратирования" этого объекта:

    from django.contrib import admin 
    from .models import Article
    
    
    class ArticleAdmin(admin.ModelAdmin):
        readonly_fields = ("last_edited_by",) # делаем полем рид онли, чтобы нельзя было его отредактировать
    
        def save_model(self, request, obj, form, change):
            if change: # True если изменяется уже существующий объект, False если добавляется новый
                # определяем и записываем пользователя если изменяется существующий объект
                obj.last_edited_by = request.user 
            else:
                # определяем и записываем пользователя если добавляется новый объект
                obj.added_by = request.user 
            super(ArticleAdmin, self).save_model(request, obj, form, change)
    
    
    admin.site.register(Article, ArticleAdmin)

    Все, пробуй. Если не нужен юзер редактировавший статью, то, надеюсь, разберешься что удалить надо?

    Подробнее о save_model():
    https://docs.djangoproject.com/en/1.10/ref/contrib...
    Подробнее о request:
    https://docs.djangoproject.com/en/1.10/ref/request...
    Ответ написан