Django 限制访问频率

最近做了一个系统由于部分接口需要进行耗时操作,因而不希望用户进行频繁访问,需要进行访问频率限制。如果要自己实现一个访问限制功能相对来说也不会太复杂,并且网上有各种代码可以参考。如果自己不想实现这个代码可以使用 Django Ratelimit

Django Ratelimit is a ratelimiting decorator for Django views.

https://travis-ci.org/jsocol/django-ratelimit.png?branch=master
Code: https://github.com/jsocol/django-ratelimit
License: Apache Software License
Issues: https://github.com/jsocol/django-ratelimit/issues
Documentation: http://django-ratelimit.readthedocs.org/

使用方法也相对来说比较简单:

@ratelimit(key='ip', rate='5/m')
def myview(request):
    # Will be true if the same IP makes more than 5 POST
    # requests/minute.
    was_limited = getattr(request, 'limited', False)
    return HttpResponse()

@ratelimit(key='ip', rate='5/m', block=True)
def myview(request):
    # If the same IP makes >5 reqs/min, will raise Ratelimited
    return HttpResponse()

@ratelimit(key='post:username', rate='5/m', method=['GET', 'POST'])
def login(request):
    # If the same username is used >5 times/min, this will be True.
    # The `username` value will come from GET or POST, determined by the
    # request method.
    was_limited = getattr(request, 'limited', False)
    return HttpResponse()

@ratelimit(key='post:username', rate='5/m')
@ratelimit(key='post:tenant', rate='5/m')
def login(request):
    # Use multiple keys by stacking decorators.
    return HttpResponse()

@ratelimit(key='get:q', rate='5/m')
@ratelimit(key='post:q', rate='5/m')
def search(request):
    # These two decorators combine to form one rate limit: the same search
    # query can only be tried 5 times a minute, regardless of the request
    # method (GET or POST)
    return HttpResponse()

Continue Reading

Django admin Foreignkey ManyToMany list_display展示

class Ghost(models.Model):
    create = models.DateTimeField(default=timezone.now, help_text='创建时间')
    update = models.DateTimeField(auto_now=True, help_text='修改时间')
    speed = models.IntegerField(default=0, help_text='速度')
    name = models.CharField(max_length=64, help_text='名称')


class InstanceTask(models.Model):
    create = models.DateTimeField(default=timezone.now, help_text='创建时间')
    update = models.DateTimeField(auto_now=True, help_text='修改时间')
    name = models.CharField(max_length=64, help_text='副本名称')

class InstanceTaskMap(models.Model):
    create = models.DateTimeField(default=timezone.now, help_text='创建时间')
    update = models.DateTimeField(auto_now=True, help_text='修改时间')
    name = models.CharField(max_length=64, help_text='地图名称')
    ghosts = models.ManyToManyField(Ghost, help_text='Ghost')
    instance_task = models.ForeignKey(InstanceTask, related_name='instancetask_instancetaskmap', blank=True, null=True,
                                      help_text='副本任务', on_delete=models.SET_NULL)

对于上面的model,如果要在django admin中展示ghosts信息,那么在list_display中直接加入’ghosts’ 会报下面的错误:The value of ‘list_display[1]’ must not be a ManyToManyField.

如果要解决这个问题可以使用下面的代码来展示:

class InstanceTaskMapAdmin(admin.ModelAdmin):
    list_display = ('name', 'instance_task', 'id', 'index', 'get_ghost_name', 'introduction')

    # https://blog.csdn.net/weixin_42134789/article/details/83686664
    def get_ghost_name(self, obj):
        ghost_list = []
        for g in obj.ghosts.all():
            ghost_list.append(g.ghost.name)
        return ','.join(ghost_list)

    get_ghost_name.short_description = "Ghosts" 

如果需要更丰富的信息可以参考上面代码注释中的链接。

Continue Reading

DS File + XMPlayer > DS Video

群晖的系统其实已经用了好几年了,以前都是用投影仪看电影,但是自从有了小朋友之后投影仪不方便使用了。于是多数时候该用电视来投屏,虽然如此但是在使用的过程中多有不便。需要在电脑上打开网页然后选择投屏位置进行投屏。并且有的视频没有声音。这个貌似主要的原因是群晖的video station没有对应的解码器导致的,网上搜索这个问题的人貌似也蛮多的

对于上面的状况,晚上也有解决方案,安装ffmpeg解码器,https://tieba.baidu.com/p/5606311062?red_tag=2162405148 但是在实际的时候效果并不是十分力量,依然有一些视频没有声音。

后来想到用DS file来解决问题,因为平时有时候用手机浏览视频都是用的DS file。所以果断安装DS file, 在电视上安装DS file还是比较容易的,但是在登陆界面就比较蛋疼,输入地址 用户名和密码之后,无法用遥控器定位到登陆按钮无法登陆,如果要解决这个问题可以选择记住密码。并且输入过程可以在电视上插个无线鼠标键盘解决,当然,没有无线插个有线的键盘鼠标也是ok的。

Continue Reading

Django REST framework foreignkey 序列化

Django REST framework is a powerful and flexible toolkit for building Web APIs.

Some reasons you might want to use REST framework:

之前虽然也用了Django REST framework 但是序列化函数基本都是自己写的,并没有用框架带的序列化函数。这次不想在搞的那么麻烦,于是使用Django REST framework带的序列化函数。

但是在序列化foreignkey的时候却发现只有id,其余的数据没有。

model定义:

class PlayerGoodsItem(models.Model):
    create = models.DateTimeField(default=timezone.now, help_text='创建时间')
    update = models.DateTimeField(auto_now=True, help_text='修改时间')
    goods_item = models.ForeignKey(GoodsItem, related_name='goodsitem_playergoodsitem', help_text='商品信息',
                                   on_delete=models.CASCADE)

序列化代码:

class PlayerGoodsItemSerializer(serializers.ModelSerializer):
    class Meta:
        model = PlayerGoodsItem
        fields = "__all__"

Continue Reading

阿里云 EC2 CentOS 6.0 系统分区扩容

阿里云的虚拟主机磁盘空间满了,这个主要是用来放blog的,所以并没有其他的数据盘。所有的数据都是直接放到/dev/vda1磁盘下的,数据库也是在这个盘下。从阿里云的后台扩容了磁盘发现还需要登陆进行扩容,于是开始按照教程操作,事实证明给出的文档(https://help.aliyun.com/document_detail/25452.html?spm=a2c4g.11186623.6.788.666a3f87QwRXFB)里面方法比较蛋疼,对于扩展系统分区不大适用。 

后来发现貌似看的文档有问题,如果要扩展系统盘应该看这个https://help.aliyun.com/document_detail/111738.html?spm=5176.2020520101.0.0.44d34df5aZCEKE。 这个就尴尬了 smile ,没看好文档。

安装growpart

yum install cloud-utils-growpart

然后对系统分区进行扩容:

growpart /dev/vda 1

Continue Reading

阿里云 安卓push无法收到消息

官方给的demo代码如下:

    request = PushMessageToAndroidRequest.PushMessageToAndroidRequest()
    request.set_AppKey(appKey)
    request.set_Target('ALL')
    request.set_TargetValue('ALL')
    request.set_Title("PushMessageToAndroid title")
    request.set_Body("Message from ali push Open Api2.0 : PushMessageToAndroid")

    request.add_query_param('AndroidNotificationChannel', '1')

    result = clt.do_action(request)
    print result

这个代码有两个问题,如果和另外一份demo代码中的:

clt = client.AcsClient(properties.accessKeyId,properties.accessKeySecret,properties.regionId)

request = PushMessageToAndroidRequest.PushMessageToAndroidRequest()
request.set_AppKey(properties.appKey)
request.set_Target('ALL')
request.set_TargetValue('ALL')
request.set_Title("PushMessageToAndroid title")
request.set_Body("Message from ali push Open Api2.0 : PushMessageToAndroid")
result = clt.do_action(request)

很可能会出现下面的错误信息:



    EABF26DA-89EA-44BA-B16E-117FE03D29C7
    cloudpush.aliyuncs.com
    Throttling.User
    Request was denied due to user flow control.

这个错误信息按照官方的解释是限流了,但是实际并不是,可以尝试分开调用,不要连续进行push message和push notice。

另外一个问题是: 这份代码在对于最新的安卓8.0以上系统的消息无法正常弹出,按照文档解释需要设置NotificationChannel(文档链接:https://help.aliyun.com/knowledge_detail/67398.html)。

Continue Reading