Не удается ограничить редактирование владельцем профиля в Django при использовании пользовательской модели пользователя - PullRequest
0 голосов
/ 15 марта 2020

Итак, я решил go с пользовательской моделью пользователя, чтобы я мог настроить страницу регистрации и потребовать, чтобы пользователи отправляли фотографию во время регистрации. Я не уверен, что мне нужно было go пройти через все это только для этого, и я обнаружил, что управлять пользовательским классом пользователя сложнее. Сейчас я пытаюсь разрешить редактировать свою информацию только текущему зарегистрированному пользователю, а не кому-либо еще. Я полностью знаю, как сделать это через обычную модель User, но я не могу понять, как сделать это через путь пользовательской модели пользователя. Единственный способ, которым я знаю, как это сделать, - это создать отдельную модель, которая имеет внешний ключ к моей модели профиля, «владелец», и сравнить два идентификатора, когда текущий пользователь пытается отредактировать чужой профиль. Я осмотрел пару разных связанных вопросов, и не смог найти решение. Лучше всего я получал «settings.Auth_User_Model» вместо «User» для владельца, но это тоже не работает.

Ошибка:

django.core.management.base.SystemCheckError: SystemCheckError: System check identified some issues:

ERRORS:
dating_app.Profile.owner: (fields.E301) Field defines a relation with the model 'auth.User', which has been swapped out.
    HINT: Update the relation to point at 'settings.AUTH_USER_MODEL'.

models.py

from django.db import models
from django.contrib.auth.models import AbstractBaseUser,BaseUserManager, User
class ProfileManager(BaseUserManager):

def create_user(self, username, email,description,photo, password=None):
    if not email:
        raise ValueError("You must creat an email")
    if not username:
        raise ValueError("You must create a username!")
    if not description:
        raise ValueError("You must write a description")
    if not photo:
        raise ValueError("You must upload a photo")

    user = self.model(
            email=self.normalize_email(email),
            username = username, 
            description= description,
            photo= photo,

        )

    user.set_password(password)
    user.save(using=self._db)
    return user 


def create_superuser(self, username, email,description,photo, password):
    user = self.create_user(
            email=self.normalize_email(email),
            password=password,
            username=username,
            description=description,
            photo=photo,

        )

    user.is_admin=True
    user.is_staff=True
    user.is_superuser=True
    user.save(using=self._db)
    return user
class Profile(AbstractBaseUser):

email                       = models.EmailField(verbose_name="email")
username                    = models.CharField(max_length=30, unique=True)
date_joined                 = models.DateTimeField(verbose_name='date joined', auto_now_add=True)
last_login                  = models.DateTimeField(verbose_name='last login', auto_now=True)
is_admin                    = models.BooleanField(default=False)
is_active                   = models.BooleanField(default=True)
is_staff                    = models.BooleanField(default=False)
is_superuser                = models.BooleanField(default=False)
#what I added
description                 = models.TextField()
photo                       = models.ImageField(upload_to='profile_photo',blank=False, height_field=None, width_field=None, max_length=100)
owner                       = models.ForeignKey(User, on_delete=models.CASCADE)


USERNAME_FIELD = 'username'
REQUIRED_FIELDS = ['description','photo','email']


objects = ProfileManager()


def __str__(self):
    return self.username


def has_perm(self, perm, obj=None):
    return self.is_admin


def has_module_perms(self,app_label):
    return True

Views.py для update_account и владельца

def update_account(request, profile_id):
    #Edit an existing profile 
    profile = get_object_or_404(Profile,id=profile_id)
    update_form = ProfileUpdateForm(request.POST, request.FILES)
    check_profile_owner(profile.owner,request.user)

    if request.method != 'POST':
        #Initial request; prefil form with current entry
        update_form = ProfileUpdateForm(instance=profile)
    else:
        #POST data submitted;process data. 
        update_form = ProfileUpdateForm(instance=profile, data=request.POST, files=request.FILES)
        if update_form.is_valid():
            update_form.save()
            return HttpResponseRedirect(reverse('dating_app:profile', args=[profile.id]))

    context = {'profile' : profile, 'update_form' : update_form}
    return render(request, 'dating_app/update.html', context)

"""Checks to see if the current user is also the profile owner"""
def check_profile_owner(user):

     if owner != user:
        raise Http404 

settings.py

#For Custom Model 
AUTH_USER_MODEL = 'dating_app.Profile'

Ответы [ 2 ]

0 голосов
/ 15 марта 2020

Кажется, вы проделали гораздо больше работы, чем необходимо. Django пользовательские модели (в различных формах в зависимости от того, используете ли вы ALLAUTH) включают в себя почти все, что вам нужно, кроме профиля. По моему ограниченному опыту, самое простое, что можно сделать, это создать подкласс пользовательского пользователя в модели пользователей:

class CustomUser(AbstractUser):
   pass

Хотя это может быть ненужным, если вы никогда не добавляете новые поля, это обеспечивает лучшую масштабируемость в будущем. , Затем создайте класс Profile, который имеет внешнюю ссылку на вашего CustomerUser. В этом профиле вы можете поместить все те вещи, которые вам нравятся ... картинки, биографии, предпочтения и т. Д. c.

class Profile(models.Model):
    user = models.OneToOneField(CustomUser, on_delete=models.CASCADE)
    biography = models.TextField(max_length=255, default='', null=True, blank=True)
    image = models.ImageField(default='default.jpg', upload_to='profile_pics/%Y/%m/%d')
    nativelanguage = models.ManyToManyField(Language, related_name='user_native_language')
    likedobjects = models.ManyToManyField(LearningObject, related_name='liked_objects')
    savedobjects = models.ManyToManyField(LearningObject, related_name='saved_objects')
    updated = models.DateTimeField(auto_now_add=True)

Иногда это может быть утомительно, но помогает изолировать код из встроенных Django пользовательских моделей.

Чтобы гарантировать, что правильный пользователь меняет профиль, это должно быть так же просто, как проверить request.user и вытянуть профиль для этого пользователя. в новую форму. Пользователь должен только иметь доступ к форме или обновлению своего профиля. Никогда не следует разрешать другому пользователю доступ к форме для обновления профиля другого.

РЕДАКТИРОВАТЬ: Одним из преимуществ добавления пользовательской модели пользователя (например, «CustomUser») является возможность добавлять дополнительные методы, не связываясь с Django Пользовательская система. Например, вчера я нашел этот код, не помню, кто его опубликовал:

from django.contrib.auth.models import AbstractUser, UserManager
class CustomUserManager(UserManager):
    def get_by_natural_key(self, username):
        return self.get(username__iexact=username)

class CustomUser(AbstractUser):
    objects = CustomUserManager()
    def add_email_address(self, request, new_email):
        # Add a new email address for the user, and send email confirmation.
        # Old email will remain the primary until the new one is confirmed.
        return EmailAddress.objects.add_email(request, self, new_email, confirm=True)

Добавление этого позволяет моим пользователям изменить свой адрес электронной почты, а затем дождаться подтверждения по электронной почте, прежде чем полностью удалить свой старый адрес. .

0 голосов
/ 15 марта 2020

Попробуйте, в ваших views.py:

from django.contrib.auth import get_user_model

User = get_user_model()

и удалите следующее (если существует):

from django.contrib.auth.models import User
...