Ответы пользователя по тегу Django
  • Не применяются стили в Django. Что не так?

    dunmaksim
    @dunmaksim
    Технический писатель
    1. Измените базовый шаблон, добавив пустой блок в head после подключения всех CSS:
    {% block css %} {% endblock %}
    2. В расширяющем шаблоне заполните этот блок:
    {% block css %}
    <link rel="stylesheet" href="{% static 'path/to/css.css' %}">
    {% endblock %}
    Ответ написан
    Комментировать
  • Как правильно сериализовать объект?

    dunmaksim
    @dunmaksim
    Технический писатель
    Я бы написал так:
    models.py
    from django.db import models
    
    
    class Ingridient(models.Model):
    
        name = models.CharField(
            max_length=30,
            unique=True,
            db_index=True
        )
    
        class Meta:
            db_table = 'ingridient'
            ordering = [ 'name' ]
    
    
    class Recipe(models.Model):
    
        name = models.CharField(
            max_length=30,
            unique=True,
            db_index=True
        )
    
        ingridients = models.ManyToManyField(
            Ingridient
        )
    
        class Meta:
            db_table = 'recipe'
            ordering = [ 'name' ]


    serializers.py
    from rest_framework.serializers import ModelSerializer, PrimaryKeyRelatedField
    from .models import Ingridient, Recipe
    
    
    class IngridientSerializer(ModelSerializer):
    
        class Meta:
            model = Ingridient
    
    
    class RecipeReadListSerializer(ModelSerializer):
    
        class Meta:
            model = Recipe
            exclude = ['ingridients']
    
    
    class RecipeReadDetailSerializer(ModelSerializer):
    
        ingridients = IngridientSerializer(
            many=True
        )
    
        class Meta:
            model = Recipe
    
    
    class RecipeWriteSerializer(ModelSerializer):
    
        ingridients = PrimaryKeyRelatedField(
            queryset=Ingridient.objects.all(),
            many=True,
            default=[]
        )
    
        class Meta:
            model = Recipe


    views.py
    from rest_framework.viewsets import ModelViewSet
    
    from .serializers import IngridientSerializer, RecipeReadListSerializer, RecipeReadDetailSerializer, RecipeWriteSerializer
    from .models import Ingridient, Recipe
    from rest_framework.permissions import AllowAny
    
    
    class IngridientViewSet(ModelViewSet):
    
        queryset = Ingridient.objects.all()
    
        serializer_class = IngridientSerializer
    
        permission_classes = [
            AllowAny
        ]
    
        class Meta:
            model = Ingridient
    
    
    class RecipeViewSet(ModelViewSet):
    
        queryset = Recipe.objects.all()
    
        permission_classes = [
            AllowAny
        ]
    
        def get_serializer_class(self):
            if self.request.method == 'GET':
                if self.action == 'list':
                    return RecipeReadListSerializer
                return RecipeReadDetailSerializer
            return RecipeWriteSerializer


    urls.py
    from rest_framework.routers import SimpleRouter
    from .views import IngridientViewSet, RecipeViewSet
    
    router = SimpleRouter()
    router.register(r'ingridients', IngridientViewSet, base_name='ingridients')
    router.register(r'recipies', RecipeViewSet, base_name='recipe')
    
    urlpatterns = router.urls


    Насчёт использования SlugField не совсем уверен, что они нужны, ведь API в данном случае будет простым, список его URL вообще проще некуда, впрочем, я думаю, добавить их вы сможете в любое нужное время.
    Зачем для сериализации рецептов целых три сериализатора?
    При получении списка всех рецептов как правило не нужно сразу же получать и все ингридиенты. Во всяком случае, в моих приложениях я делаю подгрузку полной копии модели только при детальном просмотре, а в списках часть полей скрыта на уровне API. Надо ли говорить, что при сериализации пользователей несколько сериализаторов просто необходимы, чтобы не выводить пароль при получении объекта, но иметь возможность его обновлять при записи?
    Сериализатор для чтения деталей как раз выдаёт вложенные объекты при получении модели рецепта - в поле ingridients будет массив полностью сериализованных объектов Ingridient.
    Третий сериализатор используется только для создания записей типа Recipe или их обновления. Для заполнения ингридиентов нужно передать список их id. DRF сам проверит существование соответствующих моделей и выполнит все остальные действия.
    Ответ написан
    Комментировать
  • Django. Как изменять отдельные поля в форме?

    dunmaksim
    @dunmaksim
    Технический писатель
    Используйте частичное обновление update() вместо полного save(): https://docs.djangoproject.com/en/1.8/ref/models/q...
    При этом вместо POST лучше установить заголовок запроса в PATCH.
    Ответ написан
    2 комментария
  • Как в Django v1.8 в ClassBasedView установить CSRF-токен?

    dunmaksim
    @dunmaksim Автор вопроса
    Технический писатель
    Решение оказалось на редкость простым: в шаблоне нужно добавить строку:
    {% csrf_token %}
    В этом и только в этом случае cookie с CSRF-токеном будет присутствовать на странице.
    Ответ написан
    Комментировать
  • Django как сделать запрос к профайлу user'a в шаблоне и проверить принадлежность к группе?

    dunmaksim
    @dunmaksim
    Технический писатель
    В статье я написал, как делать расширенную модель пользователя: dunmaksim.blogspot.ru/2015/05/django-18.html
    Для решения Вашей задачи нужно:
    • описать базовую модель User с полем role или полями вида is_user, is_vendor и т.п.
    • унаследовать от неё классы Vendor и PlainUser

    В виде делаем ещё проще (показано для ClassBasedView, так же требуется обязательная авторизация, но Вы можете допилить для себя):
    from os import path
    
    from django.contrib.auth.decorators import login_required
    from django.core.context_processors import csrf
    from django.shortcuts import render_to_response
    from django.template import RequestContext
    from django.views.generic import View
    
    
    class Login(View):
    
        def get(self, request):
            c = {}
            c.update(csrf(request))
                    RequestContext(request, c)
            return render_to_response(
                path.join('login', 'index.html'),
                RequestContext(request, c)
            )
    
    
    class LoginRequiredMixin(object):
    
        @classmethod
        def as_view(cls, **initkwargs):
            view = super(LoginRequiredMixin, cls).as_view(**initkwargs)
            return login_required(view)
    
    
    class Desktop(LoginRequiredMixin, View):
    
        def get(self, request):
            c = {}
            c.update(csrf(request))
            user = request.user
            if user.is_admin:
                return render_to_response(
                    path.join('admin', 'index.html'),
                    RequestContext(request, c)
                )
            if user.is_vendor:
                return render_to_response(
                    path.join('vendor', 'index.html'),
                    RequestContext(request, c)
                )
            return render_to_response(
                path.join('desktop', 'index.html'),
                RequestContext(request, c)
            )
    Ответ написан
    8 комментариев
  • Как создать urlpattern с произвольным числом однотипных параметров?

    dunmaksim
    @dunmaksim Автор вопроса
    Технический писатель
    Товарищи со StackOverflow рекомендуют такое решение вопроса:
    urlpatterns = [
        url(r'^(?P<path>[-\w/]+)/$', TemplateView.as_view()),
    ]
    Ответ написан
  • Откуда начинается отсчёт при указывании STATIC_URL в settings.py в django?

    dunmaksim
    @dunmaksim
    Технический писатель
    STATIC_URL - это часть URL, с которой будет начинаться путь к статике. Допустим,
    STATIC_URL='vendor'
    Теперь при парсинге URL Django будет сразу понимать, что запросы вида
    http://mysite.ru/vendor/...
    относятся к статическому контенту и делать там ничего не надо, нужно просто вернуть файл.
    Кроме этих параметров в settings.py для статики нужно указать ещё параметр PATH_TO_STATIC - это папка, куда Django при выполнении команды
    python manage.py collectstatic
    сложит все статические файлы.
    А вот в каждом приложении я обычно делаю так:
    • создаю папку static
    • в ней создаю папку с именем приложения, чтобы при сборе статики не было каши
    • кладу в папку нужные библиотеки и т.д.
    Вот тут полный разбор данного вопроса (ENG).
    Ну и не забываем в начале шаблонов писать тег:
    {% load staticfiles %}
    Вот тогда ссылки будут работать:
    <link rel="stylesheet" href="{% static 'desktop/libs/bootstrap/css/bootstrap.css' %}"/>
    Ответ написан
    Комментировать
  • Почему при использовании ajax c django появляется ошибка Internal server error 500?

    dunmaksim
    @dunmaksim
    Технический писатель
    1. Вам нужно в Вашего шаблона, который выводится на страницу, включить тег {% csrf token %}
    2. Также нужно, чтобы при загрузке страницы срабатывал вот этот скрипт:
    (function(G) {
    	"use strict";
    	var $ = G.jQuery;
    
    	function csrfSafeMethod(method) {
    		return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
    	}
    	function sameOrigin(url) {
    		var host = document.location.host, // host + port
    		    protocol = document.location.protocol,
    		    sr_origin = '//' + host,
    		    origin = protocol + sr_origin;
    		// Allow absolute or scheme relative URLs to same origin
    		return (url == origin || url.slice(0, origin.length + 1) == origin
    				+ '/')
    				|| (url == sr_origin || url.slice(0, sr_origin.length + 1) == sr_origin
    						+ '/') ||
    				!(/^(\/\/|http:|https:).*/.test(url));
    	}
    	$.ajaxSetup({
    		beforeSend : function(xhr, settings) {
    			if (!csrfSafeMethod(settings.type) && sameOrigin(settings.url)) {
    				xhr.setRequestHeader("X-CSRFToken", $.cookie('csrftoken'));
    			}
    		}
    	});
    }(this));

    3. Комментировать middleware csrf_token не надо. Вы уж будьте последовательны - если делаете CSRF, так делайте до конца.
    4. Ваш вид лучше написать так:
    @csrf_protect #Защищать так защищать
    def email_check(request):
        if request.method == "POST":
            post_email = request.POST.get("email")
            user_by_email = User.objects.get(email=post_email)
            if user_by_email is not None: #Такой email уже использован
                return HttpResponse(json.dumps({"success": False, "error": "Пользователь с таким email уже зарегистрирован"}), content_type="application/json")
            else: #E-mail свободен
                return HttpResponse(json.dumps({"success": True}), "application/json")
    Ответ написан