2017-07-23 34 views
0

我有一个看起来像这样(点是防止重复的用户配置文件)测试用例:如何在django-rest-framework中获取db验证错误后返回状态码?

def test_create_duplicate_profile(self): 
    new_user = models.User(
     username='bobjones', 
     password=';alsdfkj;asoi' 
    ) 
    new_user.save() 
    client = APIClient() 
    client.force_authenticate(new_user) 
    response = client.post(
     path='/api/profiles/' 
    ) 
    self.assertEqual(response.status_code, status.HTTP_201_CREATED) 

    same_user = models.User.objects.get(
     username='bobjones' 
    ) 
    response = client.post(
     path='/api/profiles/' 
    ) 
    self.assertEqual(response.status_code, status.HTTP_409_CONFLICT) 
    client.logout() 

这将导致一个错误(以及失败的测试):

(.virtualenv) nbascoutingdotcom $ python manage.py test profiles 
Creating test database for alias 'default'... 
System check identified no issues (0 silenced). 
E.. 
====================================================================== 
ERROR: test_create_duplicate_profile (profiles.tests.test_api.ProfilesAPITest) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/Users/evanzamir/nbascoutingdotcom/.virtualenv/lib/python3.6/site-packages/django/db/backends/utils.py", line 65, in execute 
    return self.cursor.execute(sql, params) 
    File "/Users/evanzamir/nbascoutingdotcom/.virtualenv/lib/python3.6/site-packages/django/db/backends/sqlite3/base.py", line 328, in execute 
    return Database.Cursor.execute(self, query, params) 
sqlite3.IntegrityError: UNIQUE constraint failed: profiles_profile.user_id 

我模型是这样的:

class Profile(TimestampModerated): 
    id = models.BigAutoField(primary_key=True, db_column='id', null=False) 
    uuid = models.UUIDField(db_index=True, default=uuid_lib.uuid4(), editable=False) 
    user = models.OneToOneField('auth.User', on_delete=models.CASCADE, related_name='profiles', blank=False, 
           unique=True) 
    bio = models.CharField(max_length=140, blank=True, null=True) 
    media_url = models.URLField(blank=True, null=True) 
    dob = models.DateField(blank=True, null=True) 

    class Meta: 
     verbose_name_plural = "profiles" 

这里是串行:

class ProfileSerializer(serializers.ModelSerializer): 
    user = serializers.CharField(source='user.username', read_only=True, 
           validators=[UniqueValidator(queryset=Profile.objects.all())]) 
    email = serializers.CharField(source='user.email', read_only=True) 
    first = serializers.CharField(source='user.first_name', read_only=True) 
    last = serializers.CharField(source='user.last_name', read_only=True) 
    last_login = serializers.DateTimeField(source='user.last_login', read_only=True) 
    date_joined = serializers.DateTimeField(source='user.date_joined', read_only=True) 

    class Meta: 
     model = Profile 
     fields = ('id', 'created', 'moderation_code', 'user', 'updated', 'uuid', 'bio', 'email', 
        'first', 'last', 'last_login', 'media_url', 'dob', 'date_joined') 

这里是我的视图集:

class ProfileViewSet(viewsets.ModelViewSet): 
    """ 
    This viewsetomatically provides `list`, `create`, `retrieve`, 
    `update` and `destroy` actions. 

    """ 
    queryset = Profile.objects.all() 
    serializer_class = ProfileSerializer 
    authentication_classes = (SessionAuthentication,) 
    permission_classes = (permissions.AllowAny, IsOwnerOrReadOnly) 
    lookup_field = 'user' 

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

我希望能够发回一个有效的HTTP状态代码(HTTP_40X_),但我似乎无法能够挂接到验证错误。我试着在perform_create方法中加入一些代码来引发一个ValidationError,但这对我并不起作用。有什么建议么?

+0

如果'self.request.user'的'Profile'已经存在并且可以提前返回错误代码,您可以检查视图吗? – perfect5th

回答

0

你必须创建并返回实际的响应,其中挂钩到ModelViewSet.create(...)

from rest_framework.response import Response 
from rest_framework import status 

def create(self, request, *args, **kwargs): 
    try: 
     return super(ProfileViewSet, self).create(request, *args, **kwargs): 
    except IntegrityError: 
     return Response(status=statusHTTP_409_CONFLICT) 

对于更广泛的项目范围的方法,你也可以阅读drf docs on custom exception handling

相关问题