У объекта 'Account' нет атрибута 'products' AND (fields.E301) Поле определяет связь с моделью 'auth.User', которая была заменена. ' - PullRequest
0 голосов
/ 04 февраля 2020

Я следую Django rest_framework, чтобы создать свое приложение, но я использую пользовательскую модель пользователя (Account), которая наследует AbstractBaseUser.

У меня есть другая модель - Product - и каждый продукт принадлежит по учетной записи.

Мой models.py:

from django.db import models
from django.contrib.auth.models import AbstractBaseUser, BaseUserManager
from django.conf import settings

class Product(models.Model):
    owner = models.ForeignKey(Account, related_name='account', on_delete=models.CASCADE, default=1)
    name = models.CharField(max_length=71)
    product = models.CharField(max_length=20, blank=True)
    price = models.IntegerField(null=True, blank=True)
    quantity = models.IntegerField(default=0)
    image = models.ImageField(upload_to='images', blank=True)
    display = models.BooleanField(default=False)
    created = models.DateTimeField('date added', auto_now=True)
    modified = models.DateTimeField('date modified', auto_now_add=True)

    def __str__(self):
        return self.name

class MyAccountManager(BaseUserManager):
    def create_user(self, email, username, password=None):
        if not email:
            raise ValueError("Please enter a valid email address")
        if not username:
            raise ValueError("Please enter a username")

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

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

    def create_superuser(self, email, username, password):
        user = self.create_user(
            email = self.normalize_email(email),
            password = password,
            username = username,
        )
        user.is_admin = True
        user.is_staff = True
        user.is_superuser = True
        user.save(using=self._db)
        return user

class Account(AbstractBaseUser):
    email = models.EmailField(verbose_name='email', max_length=60, unique=True)
    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_add=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)
    is_merchant = models.BooleanField(default=False)

    USERNAME_FIELD = 'email'
    REQUIRED_FIELDS = ['username']

    objects = MyAccountManager()

    def __str__(self):
        return self.email

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

    def has_module_perms(self, app_label):
        return True

Мой файл settings.py содержит:

AUTH_USER_MODEL = 'accounts.Account'

Мой файл serializers.py:

from rest_framework import serializers
from inventory.models import Product
from accounts.models import Account

class AccountSerializer(serializers.ModelSerializer):
    products = serializers.PrimaryKeyRelatedField(many=True, queryset=Product.objects.all())

    password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)

    class Meta:
        model = Account
        fields = ['products', 'email', 'username', 'password', 'password2']
        extra_kwargs = {
            'password': {'write_only': True}
        }

    def save(self):
        account = Account(
            email = self.validated_data['email'],
            username = self.validated_data['username'],
        )
        password = self.validated_data['password']
        password2 = self.validated_data['password2']

        if password != password2:
            raise serializers.ValidationError({'password': 'Passwordss must match.'})
        account.set_password(password)
        account.save()
        return account

class ProductSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
    class Meta:
        model = Product
        fields = [
            'id', 'owner', 'name', 'product', 'price', 'quantity', 'image', 'display'
        ]

Мой views.py:

from accounts.api.serializers import AccountSerializer
from inventory.api.serializers import ProductSerializer
from inventory.models import Product
from accounts.models import Account
from rest_framework import permissions
from rest_framework import generics

class AccountList(generics.ListAPIView):
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

class AccountDetail(generics.RetrieveAPIView):
    queryset = Account.objects.all()
    serializer_class = AccountSerializer

class ProductList(generics.ListCreateAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

class ProductDetail(generics.RetrieveUpdateDestroyAPIView):
    permission_classes = [permissions.IsAuthenticatedOrReadOnly]
    queryset = Product.objects.all()
    serializer_class = ProductSerializer

Я могу просмотреть мой ProductList и ProductDetail, однако при попытке просмотреть AccountList и AccountDetail появляется следующая ошибка:

**Exception Type:** AttributeError
**Exception Value:** 'Account' object has no attribute 'products'

1 Ответ

1 голос
/ 04 февраля 2020

Просто измените свой serailzier следующим образом:

class AccountSerializer(serializers.ModelSerializer):
    products = serializers.SerializerMethodField()
    password2 = serializers.CharField(style={'input_type': 'password'}, write_only=True)

    def get_products(self, instance):
        return Product.objects.all().values_list('id', flat=True)

    class Meta:
        model = Account
        fields = ['products', 'email', 'username', 'password', 'password2']
        extra_kwargs = {
            'password': {'write_only': True}
        }

    def save(self):
        account = Account(
            email = self.validated_data['email'],
            username = self.validated_data['username'],
        )
        password = self.validated_data['password']
        password2 = self.validated_data['password2']

        if password != password2:
            raise serializers.ValidationError({'password': 'Passwordss must match.'})
        account.set_password(password)
        account.save()
        return account

PrimaryKeyRelatedField может использоваться для представления цели отношения с использованием его первичного ключа. Набор запросов, используемый для поиска экземпляров модели при проверке ввода поля. Ваше поле является read_only полем. Вы должны использовать SerializerMethodField для этого.

...