今天的review,请收下

1.别人看不明白的代码要加注释

class Sample(TimedModel):

TODO = 'todo'

DOING = 'doing'

DONE = 'done'

上面的代码,别人看不懂状态的函数,于是加注释

class Sample(TimedModel):

TODO = 'todo' # origin state

DOING = 'doing' # this sample has been notified to superbox

DONE = 'done' # superbox uploaded related event generated from this sample

2.接收前端传过来的数据时,要判断哪些字段可以写入db中

class Meta:

model = RawEvent

read_only_fields = ('mark',)

fields = ('id', 'created_at', 'updated_at', 'uuid', 'camera', 'site', 'types', 'mediums') + read_only_fields

created_at字段不希望被前端设置,这样前端可能伪造创建时间

class Meta:

model = RawEvent

read_only_fields = ('mark', 'created_at', 'updated_at')

fields = ('id', 'uuid', 'camera', 'site', 'types', 'mediums') + read_only_fields

3.精简代码,规避多余的sql查询

chaxun

查询条件合并

qs = NotifyInfo.objects.filter(Q(camera=camera.pk) | Q(box=camera.box_id)).all()

for notify_obj in qs:

users.append(notify_obj.user)

if len(users) <= 0:

but,这两个查询其实不能合并哦,故意这样设计的,你发现原因了吗?

4.serializer不只是验证数据,还净化数据

serial = self.get_serializer(data=request.data)

if serial.is_valid():

EventService.r_create(request, serial, result)

uuid = request.data.get('uuid')

这时uuid不应该从request.data中拿,而应该从serializer.validated_data中拿

serial = self.get_serializer(data=request.data)

if serial.is_valid():

EventService.r_create(request, serial, result)

uuid = serial.validated_data['uuid']

5.race condition问题的规避

@detail_route(methods=('get', 'put'), permission_classes=(IsAuthenticated,))

def verified(self, request, *args, **kwargs):

...

raw_evt.mark = RawEvent.VERIFIED

raw_evt.user = request.user

raw_evt.save()

这是个响应http请求的函数,对raw_evt字段的更新希望是被原子执行的,要么加锁,要么用下面方法

@detail_route(methods=('get', 'put'), permission_classes=(IsAuthenticated,))

def verified(self, request, *args, **kwargs):

result = Result()

raw_evt = self.get_object()

if raw_evt.mark != RawEvent.UNKNOWN:

result.put_forbid_error(extra='already marked')

return result.get_response()

RawEvent.objects.filter(pk=raw_evt.pk, mark=RawEvent.UNKNOWN).update(mark=RawEvent.VERIFIED, user=request.user)

raw_evt.refresh_from_db()

...

6.接口最小暴露原则

from rest_framework.viewsets import ModelViewSet

class EventViewSet(ModelViewSet):

...

业务要求对Event只能创建,不允许更新,这时使用ModelViewSet范围就有点大了

from rest_framework import mixins

from rest_framework.viewsets import GenericViewSet

class EventViewSet(mixins.CreateModelMixin,

mixins.RetrieveModelMixin,

mixins.DestroyModelMixin,

mixins.ListModelMixin,

GenericViewSet):

...

7.serializer.choiceField,就是省力用的

class SampleSerializer(serializers.Serializer):

mark = serializers.CharField(required=True)

def validate_mark(self, value):

if value not in ['misreport', 'verified']:

raise serializers.ValidationError('not a valid mark value')

return value

serializer.choiceField就是用来干这事儿的,让代码更简洁,降冗余

class SampleSerializer(serializers.Serializer):

mark = serializers.ChoiceField(choices=[('misreport', 'misreport'), ('verified', 'verified')], required=True)

8.去除冗余代码

sample = Sample.objects.filter(Q(pk=data['sample_id']) & ~Q(status=Sample.DONE)).first()

if not sample or not sample.camera_id or not sample.camera.box_id:

result.put_logic(Error.logic(cls.DM_SAMPLE_NOT_SUPPORTED, cls.EM_SAMPLE_NOT_SUPPORTED % dict(code=cls.DM_SAMPLE_NOT_SUPPORTED)))

result.send_channel(message)

return

now = Utils.utc_now()

if sample.user is not None and (now - sample.updated_at).seconds < 60:

result.put_logic(Error.logic(cls.DM_SAMPLE_NOT_SUPPORTED, cls.EM_SAMPLE_NOT_SUPPORTED % dict(code=cls.DM_SAMPLE_NOT_SUPPORTED)))

result.send_channel(message)

return

发现两个if中有两行相同的代码,一种做法是将if条件合并,我觉得更合理的方式是让两个if中返回不同的信息,毕竟是两种不同的异常。

9.返回客户端的string都要注意国际化

def validate_sample_id(self, value):

if not Sample.objects.filter(pk=value).exists():

raise serializers.ValidationError(f'sample_id:{value} not exist in db')

改成下面

def validate_sample_id(self, value):

if not Sample.objects.filter(pk=value).exists():

raise serializers.ValidationError(_("The specified sample %(sample_id)s doesn't exist.") % dict(sample_id=value))

return value

10.django template的国际化写法

xief

下面更好

{% load i18n %}{% autoescape off %} {% blocktrans %} Camera {{ rawevent.camera_id }} generated new event {% endblocktrans %}{% endautoescape %}


分享到:


相關文章: