且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

更新与Django Rest中的外键相关的记录

更新时间:2023-02-27 13:11:58

您确实有一个限制条件,使用户名无法重新创建。
您需要通过更改验证器 UserSerializer.username 来删除它。
确保您不要通过打印序列化程序来除去其他约束:

 >>> print(UserSerializer())
>>> UserSerializer():
id = IntegerField(label ='ID',read_only = True)
first_name = CharField(allow_blank = True,max_length = 30,required = False)
username = CharField help_text ='必需30个字符或更少字母,数字和@ /。/ + / - / _ only',max_length = 30,validators = [< django.core.validators.RegexValidator object&gt,< UniqueValidator queryset = User.objects.all())>])
email = EmailField(allow_blank = True,label ='Email address',max_length = 254,required = False)
is_active = BooleanField ='指定该用户是否应该被视为活动的,取消选择而不是删除帐户',label ='Active',required = False)

你可以注意到,我们在用户名上有一个 UniqueValidator 以及一个 RegexValidator



您需要更改类:

  from django.core import validators 
from django.utils.transl ation import ugettext_lazy as _

class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields =(
'id'
'first_name',
'username',
'email',
'is_active',

extra_kwargs = {
'username ':{
'validators':[
validators.RegexValidator(
r'^ [\w。@ + - ] + $',
_('输入有效用户名。此值可能只包含'
'字母,数字'和@ /。/ + / - / _字符')
),]
}
}

请注意,这里的验证器是从该字段的Django定义中删除的( https://github.com/django/django/blob/master/django/contrib /auth/models.py#L309



现在,如果再次打印序列化程序,您应该会看到唯一的约束被删除:

 >>> print(UserSerializer())
>>> UserSerializer():
id = IntegerField(label ='ID',read_only = True)
first_name = CharField(allow_blank = True,max_length = 30,required = False)
username = CharField help_text ='必需的30个字符或更少字母,数字和@ /。/ + / - / _ only。',max_length = 30,validators = [< django.core.validators.RegexValidator object>])
email = EmailField(allow_blank = True,label ='Email address',max_length = 254,required = False)
is_active = BooleanField(help_text ='指定此用户是否应被视为活动状态取消选择而不是删除帐户。',label ='Active',required = False)


I want to update records that are related with foreign Keys or related by any means. I know how to update single model records but I am not able to do the same in case of related models.

My Models :

class UserProfile(models.Model):
    user = models.OneToOneField(User)
    subject = models.ManyToManyField('Subjects')
    phone = models.CharField(max_length=20)
    address = models.TextField()

    def __unicode__(self):
        return self.user.username

class Subjects(models.Model):
    name = models.CharField(max_length=100)
    code = models.IntegerField()


    def __unicode__(self):
        return self.name

My serializers :

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = (
                'id',
                'first_name',
                'username',
                'email',
                'is_active',
            )

class SubjectSerializer(serializers.ModelSerializer):
    class Meta:
        model = Subjects
        fields = (
                'name',
                'code',
            )

class UserProfileSerializer(serializers.ModelSerializer):
    user = UserSerializer()
    subject = SubjectSerializer(many=True)

    class Meta:
        model = UserProfile
        fields = (
                'user',
                'subject',
                'phone',
                'address',
            )

Views :

class UserProfileList(viewsets.ModelViewSet):
    serializer_class = UserProfileSerializer

    queryset = UserProfile.objects.all()

urls

router.register(r'api/user/profile', UserProfileList)

I can see the first record as /api/user/profile/1/ But when I'll try to update record from Browsable Rest Api it gives me the error user with same username already exist.

Edit :

I want to update UserProfile Model using UserProfileSerializer . Simple create new records , Update existing one and delete.

You do have a constraint the username that makes it impossible to create again. You need to remove it by altering validators UserSerializer.username. Make sure you don't remove others constraints by printing the serializer:

>>> print(UserSerializer())
>>> UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    first_name = CharField(allow_blank=True, max_length=30, required=False)
    username = CharField(help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, validators=[<django.core.validators.RegexValidator object>, <UniqueValidator(queryset=User.objects.all())>])
    email = EmailField(allow_blank=True, label='Email address', max_length=254, required=False)
    is_active = BooleanField(help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', label='Active', required=False)

As you can notice, we do have a UniqueValidator on the username as well as a RegexValidator

You'll need to alter the class:

from django.core import validators
from django.utils.translation import ugettext_lazy as _

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = User
        fields = (
            'id',
            'first_name',
            'username',
            'email',
            'is_active',
        )
        extra_kwargs = {
            'username': {
                'validators': [
                    validators.RegexValidator(
                        r'^[\w.@+-]+$',
                        _('Enter a valid username. This value may contain only '
                        'letters, numbers ' 'and @/./+/-/_ characters.')
                ),]
            }
        }

Note that the validator here is taken out of the Django definition of that field (https://github.com/django/django/blob/master/django/contrib/auth/models.py#L309)

Now if you print again the serializer you should see that the unique constraint is removed:

>>> print(UserSerializer())
>>> UserSerializer():
    id = IntegerField(label='ID', read_only=True)
    first_name = CharField(allow_blank=True, max_length=30, required=False)
    username = CharField(help_text='Required. 30 characters or fewer. Letters, digits and @/./+/-/_ only.', max_length=30, validators=[<django.core.validators.RegexValidator object>])
    email = EmailField(allow_blank=True, label='Email address', max_length=254, required=False)
    is_active = BooleanField(help_text='Designates whether this user should be treated as active. Unselect this instead of deleting accounts.', label='Active', required=False)