@Hideo002

Как пользователю удалять только свои объекты в Django?

как реализовать возможность пользователю взаимодействовать только с теми объектами, которые он сам загрузил, как в моем случае изображения. Например, страница с общими изображениями, но при авторизации пользователь мог "Удалить" и "Отредактировать" только те изображения, которые он сам и загрузил, а админ мог взаимодействовать так, с любым залитым объектом.

Моя рабочая реализация удаления и редактирования.
views.py
@login_required(redirect_field_name='my_redirect_field')
def delete(request, img_id):
    img = get_object_or_404(Image, id=img_id)
    img.delete()
    return redirect('index')


@login_required(redirect_field_name='my_redirect_field')
def image_edit(request, img_id):
    img = get_object_or_404(Image, id=img_id)
    form = ImageForm(request.POST or None, request.FILES or None, instance=img)   # , request.FILES,
    if form.is_valid():
        image = form.save()
        tags = form.cleaned_data['tags_']
        if tags:
            for tag in tags.split(' '):
                tag, created = Tag.objects.get_or_create(name=tag)
                image.tags.add(tag)
            for tag in image.tags.all():
                if tag.name not in tags:
                    image.tags.remove(tag)
        else:
            image.tags.clear()

        return redirect('index')
    context = {
        'form': form,
        'img': img,
        'tags': [tag.name for tag in img.tags.all()]
    }
    return render(request, 'main/image_edit.html', context)


Моя URL.
urls.py
from django.urls import path
from .views import *


urlpatterns = [
...
    path('delete/<int:img_id>', delete, name='delete'),
    path('image_edit/<int:img_id>', image_edit, name='image-edit'),
...
]


Моя форма.
form.py
from django import forms
from django.contrib.auth.forms import UserCreationForm, AuthenticationForm
from django.contrib.auth.models import User
from captcha.fields import CaptchaField, CaptchaTextInput

from .models import *


class ImageForm(forms.ModelForm):
    tags_ = forms.CharField(label='Тeги', required=False,
                            widget=forms.TextInput(
                                attrs={
                                    'class': 'form-control',
                                    'id': 'floatingInput',
                                    'placeholder': 'Тeги',
                                }))
    image = forms.ImageField(label='Изображение',
                             widget=forms.ClearableFileInput(
                                 attrs={
                                     'class': 'form-control-lg',
                                     'placeholder': 'Изображение',
                                 }
                             ))
    title = forms.CharField(
        label='Название',
        widget=forms.TextInput(
            attrs={
                'placeholder': 'Название',
                'class': 'form-control',
                'id': 'floatingInput',
            }
        ))

    class Meta:
        model = Image
        fields = ('title', 'image', 'tags_')

    def __init__(self, *args, **kwargs):
        instance = kwargs.get('instance')
        super().__init__(*args, **kwargs)
        if instance:
            tags = instance.tags.values_list('name', flat=True)
            self.fields['tags_'].initial = ' '.join(tags)


class SearchForm(forms.Form):
    query = forms.CharField(
        label='Поиск',
        widget=forms.TextInput(
            attrs={
                'placeholder': 'Поиск по тегу',
                'class': 'form-control form-control-lg',
                'id': 'floatingInput',
            }
        )
    )


class RegisterUserForm(UserCreationForm):
    username = forms.CharField(label='Логин',
                               widget=forms.TextInput(
                                   attrs={'class': 'form-control',
                                          'id': 'floatingInput',
                                          'placeholder': 'Логин'}))
    email = forms.EmailField(label='Email',
                             widget=forms.TextInput(attrs={'class': 'form-control',
                                                           'placeholder': 'Email'}))
    password1 = forms.CharField(label='Пароль',
                                widget=forms.PasswordInput(attrs={'class': 'form-control',
                                                                  'placeholder': 'Пароль'}))
    password2 = forms.CharField(label='Повтор пароля',
                                widget=forms.PasswordInput(attrs={'class': 'form-control',
                                                                  'placeholder': 'Повтор пароля'}))
    captcha = CaptchaField(label='', widget=CaptchaTextInput(attrs={'placeholder': 'Captcha',
                                                                    'id': 'floatingInput'}))

    class Meta:
        model = User
        fields = ('username', 'email', 'password1', 'password2')
        widget = {
                'username': forms.TextInput(attrs={'class': 'form-control'}),
                'email': forms.TextInput(attrs={'class': 'form-control'}),
                'password1': forms.PasswordInput(attrs={'class': 'form-control'}),
                'password2': forms.PasswordInput(attrs={'class': 'form-control'}),
        }


Вот пример как у меня это реализовано.
Изображение страницы без авторизации.
6313a39d4a912240788326.png

Я, к примеру, загрузил изображение через аккаунт User111 с возможностью изменения, авторизовавшись через другого пользователя все еще могу изменить данный объект.
6313a73f20b71272804968.png
6313a7469be6b094173677.png
Подскажите как это исправить на нужный мне вариант?
  • Вопрос задан
  • 171 просмотр
Решения вопроса 2
fox_12
@fox_12 Куратор тега Django
Расставляю биты, управляю заряженными частицами
Само собой у вашего объекта должно быть поле которое указывает на пользователя - владельца. К примеру автора:
@login_required(redirect_field_name='my_redirect_field')
def delete(request, img_id):
    img = get_object_or_404(Image, id=img_id)
    if img.author != request.user:
         return ...  # мы не автор объекта - на выход...
    # ... дальше логика работы с объектом
    img.delete()
    return redirect('index')
Ответ написан
@Hideo002 Автор вопроса
Решил таким образом.
Добавил в модельке автора.
from django.contrib.auth.models import User
from django.db import models


class Image(models.Model):
    title = models.CharField('Название', max_length=200)
    image = models.ImageField(upload_to='images')
    tags = models.ManyToManyField('Tag')
    author = models.ForeignKey(User, related_name='author', on_delete=models.CASCADE)


При загрузке изображения сохраняем автора.
@login_required(redirect_field_name='my_redirect_field')
def image_upload(request):
    form = ImageForm(request.POST, request.FILES)
    if request.method == 'POST':
        if form.is_valid():
            img_user = form.save(commit=False)
            img_user.author = request.user
            img_user.save()
            image = form.save()
            tags = form.cleaned_data['tags_']
            if tags:
                for tag in tags.split(' '):
                    tag, created = Tag.objects.get_or_create(name=tag)
                    image.tags.add(tag)
            return redirect('index')
    else:
        return render(request, 'main/image_upload.html', context_func())


В HTML шаблоне проверка на заход админа или на заход автора поста.
{% if request.user.is_superuser or img_obj.author == request.user %}
                        {% if request.user.is_authenticated %}
                          <div class="btn-group">
                            <a class="btn btn-sm btn-outline-secondary" href="{% url 'delete' img_obj.id request.user.id %}">Удалить</a>
                            <a class="btn btn-sm btn-outline-secondary" href="{% url 'image-edit' img_obj.id  request.user.id %}">Редактировать</a>
                          </div>                        
                        {% endif %}
                      {% endif %}


Спасибо всем за помощь.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
Mi11er
@Mi11er
A human...
Нууу, проверять авторизованного юзера, есои это он добавил картинку, то выводить кнопки, так же сделать с is_superuser
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы