今天的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 %}


分享到:


相關文章: