From c1aff2509977452e667e0877c8fd829dd0f75755 Mon Sep 17 00:00:00 2001 From: hukai Date: Tue, 29 Oct 2024 11:50:07 +0800 Subject: [PATCH 1/5] =?UTF-8?q?feat;=20Python=20=E5=90=8E=E7=AB=AF=20?= =?UTF-8?q?=E7=94=A8=E6=88=B7=E7=BB=91=E5=AE=9A=E8=A7=92=E8=89=B2=E7=AD=89?= =?UTF-8?q?=E3=80=82=20=20=E7=BB=91=E5=AE=9A=E9=9C=80=E6=B1=82=E9=81=BF?= =?UTF-8?q?=E5=85=8D=E6=9A=B4=E5=8A=9B=E6=95=B0=E6=8D=AE=E5=BA=93=E8=A1=A8?= =?UTF-8?q?=E7=9A=84=E6=96=B0=E5=A2=9E=E5=92=8C=E5=88=9B=E5=BB=BA=E3=80=82?= =?UTF-8?q?=20=20=E4=BC=98=E5=8C=96=E6=95=B0=E6=8D=AE=E5=BA=93=E6=9F=A5?= =?UTF-8?q?=E8=AF=A2=E5=92=8C=E4=BF=AE=E6=94=B9=E3=80=82=20=20=E9=A1=B9?= =?UTF-8?q?=E7=9B=AE=E5=85=AC=E5=85=B1=E6=96=B9=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo.py" | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 "\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" diff --git "a/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" "b/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" new file mode 100644 index 0000000..9906b5c --- /dev/null +++ "b/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" @@ -0,0 +1,48 @@ +from django.db import models +from django.db.transaction import atomic + +class User(models.Model): + name = models.CharField(max_length=10) + + +class Role(models.Model): + name = models.CharField(max_length=10) + + +class RoleUser(models.Model): + user = models.ForeignKey(User, on_delete=models.SET_NULL) + role = models.ForeignKey(Role, on_delete=models.SET_NULL) + + + +def update_create(instance, data,): + """ + a 绑定 b。 + 常见方法 a和b中间表 删除旧绑定数据,新增新绑定数据。 + 升级方法 通过 集合特性比对,优化 旧数据时新数据的子集或新数据是旧数据子集时,重复删除和创建问题。 + 放弃 暴力 删除所有。比对 + :param instance 对象 + :param data 前端传递数据 + """ + set1 = set(data) + set2 = set(RoleUser.objects.filter(user=instance).values_list('role_id', flat=True)) + delete_ids, create_ids = None, None + if set1.issubset(set2): + delete_ids = set2 - set1 + + elif set2.issubset(set1): + create_ids = set1 - set2 + else: + union = set1 & set2 + delete_ids = union - set2 + create_ids = union - set1 + + if delete_ids or create_ids: + # 开启事务 + with atomic(): + if delete_ids: + RoleUser.objects.filter(user_id__in=delete_ids).delete() + if create_ids: + RoleUser.objects.bulk_create( + [models.OrgUnitMeterModel(user=instance, role_id=ite) for ite in create_ids] + ) \ No newline at end of file -- Gitee From d22e9251d5dae7dcefa3bc080cb19990260478f1 Mon Sep 17 00:00:00 2001 From: hukai Date: Tue, 29 Oct 2024 13:19:20 +0800 Subject: [PATCH 2/5] =?UTF-8?q?to;=20=E9=80=BB=E8=BE=91=E9=97=AE=E9=A2=98?= =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../demo.py" | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git "a/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" "b/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" index 9906b5c..2afcba5 100644 --- "a/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" +++ "b/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" @@ -33,7 +33,7 @@ def update_create(instance, data,): elif set2.issubset(set1): create_ids = set1 - set2 else: - union = set1 & set2 + union = set1 | set2 delete_ids = union - set2 create_ids = union - set1 @@ -44,5 +44,5 @@ def update_create(instance, data,): RoleUser.objects.filter(user_id__in=delete_ids).delete() if create_ids: RoleUser.objects.bulk_create( - [models.OrgUnitMeterModel(user=instance, role_id=ite) for ite in create_ids] + [RoleUser(user=instance, role_id=ite) for ite in create_ids] ) \ No newline at end of file -- Gitee From 3321c4dab8f1b7c9043a46e9050973a03945ff87 Mon Sep 17 00:00:00 2001 From: hukai Date: Wed, 30 Oct 2024 13:39:31 +0800 Subject: [PATCH 3/5] =?UTF-8?q?update=20;=20=E6=B6=88=E6=81=AF=E5=B9=BF?= =?UTF-8?q?=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dj-channels" | 1 + 1 file changed, 1 insertion(+) create mode 160000 "\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" diff --git "a/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" "b/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" new file mode 160000 index 0000000..5f4f2f9 --- /dev/null +++ "b/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" @@ -0,0 +1 @@ +Subproject commit 5f4f2f9600801c069490653edbb5bf4f723d6c60 -- Gitee From 4125c333d9b5076cabaf35cb8ae1d6f5dc724552 Mon Sep 17 00:00:00 2001 From: hukai Date: Wed, 30 Oct 2024 13:45:57 +0800 Subject: [PATCH 4/5] =?UTF-8?q?update=20;=20=E6=B6=88=E6=81=AF=E5=B9=BF?= =?UTF-8?q?=E6=92=AD=20=E4=BF=AE=E6=94=B9readme?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dj-channels" | 2 +- .../demo.py" | 48 ------------------- 2 files changed, 1 insertion(+), 49 deletions(-) delete mode 100644 "\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" diff --git "a/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" "b/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" index 5f4f2f9..acb65b2 160000 --- "a/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" +++ "b/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" @@ -1 +1 @@ -Subproject commit 5f4f2f9600801c069490653edbb5bf4f723d6c60 +Subproject commit acb65b214e4eb00a1de2ad40d456c31b2e5c2d8c diff --git "a/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" "b/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" deleted file mode 100644 index 2afcba5..0000000 --- "a/\350\265\204\346\272\220\347\273\221\345\256\232\344\274\230\345\214\226/demo.py" +++ /dev/null @@ -1,48 +0,0 @@ -from django.db import models -from django.db.transaction import atomic - -class User(models.Model): - name = models.CharField(max_length=10) - - -class Role(models.Model): - name = models.CharField(max_length=10) - - -class RoleUser(models.Model): - user = models.ForeignKey(User, on_delete=models.SET_NULL) - role = models.ForeignKey(Role, on_delete=models.SET_NULL) - - - -def update_create(instance, data,): - """ - a 绑定 b。 - 常见方法 a和b中间表 删除旧绑定数据,新增新绑定数据。 - 升级方法 通过 集合特性比对,优化 旧数据时新数据的子集或新数据是旧数据子集时,重复删除和创建问题。 - 放弃 暴力 删除所有。比对 - :param instance 对象 - :param data 前端传递数据 - """ - set1 = set(data) - set2 = set(RoleUser.objects.filter(user=instance).values_list('role_id', flat=True)) - delete_ids, create_ids = None, None - if set1.issubset(set2): - delete_ids = set2 - set1 - - elif set2.issubset(set1): - create_ids = set1 - set2 - else: - union = set1 | set2 - delete_ids = union - set2 - create_ids = union - set1 - - if delete_ids or create_ids: - # 开启事务 - with atomic(): - if delete_ids: - RoleUser.objects.filter(user_id__in=delete_ids).delete() - if create_ids: - RoleUser.objects.bulk_create( - [RoleUser(user=instance, role_id=ite) for ite in create_ids] - ) \ No newline at end of file -- Gitee From 589e00354575a111aa4821d66aa94cfdf9eef589 Mon Sep 17 00:00:00 2001 From: hukai Date: Wed, 30 Oct 2024 13:51:19 +0800 Subject: [PATCH 5/5] =?UTF-8?q?update=20;=20=E6=B6=88=E6=81=AF=E5=B9=BF?= =?UTF-8?q?=E6=92=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dj-channels" | 1 - .../dj-channels/README.en.md" | 36 +++++ .../dj-channels/README.md" | 18 +++ .../dj-channels/img.png" | Bin 0 -> 37869 bytes .../dj-channels/instant/instant/__init__.py" | 0 .../dj-channels/instant/instant/asgi.py" | 28 ++++ .../dj-channels/instant/instant/settings.py" | 125 ++++++++++++++++++ .../dj-channels/instant/instant/urls.py" | 23 ++++ .../dj-channels/instant/instant/wsgi.py" | 16 +++ .../dj-channels/instant/manage.py" | 22 +++ .../dj-channels/instant/req.txt" | 24 ++++ .../dj-channels/instant/ws/__init__.py" | 0 .../dj-channels/instant/ws/admin.py" | 3 + .../dj-channels/instant/ws/apps.py" | 6 + .../dj-channels/instant/ws/consumers.py" | 37 ++++++ .../instant/ws/migrations/__init__.py" | 0 .../dj-channels/instant/ws/models.py" | 3 + .../dj-channels/instant/ws/routing.py" | 9 ++ .../instant/ws/templates/index.html" | 27 ++++ .../instant/ws/templates/room.html" | 50 +++++++ .../dj-channels/instant/ws/tests.py" | 1 + .../dj-channels/instant/ws/urls.py" | 11 ++ .../dj-channels/instant/ws/views.py" | 37 ++++++ 23 files changed, 476 insertions(+), 1 deletion(-) delete mode 160000 "\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.en.md" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.md" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/img.png" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/instant/__init__.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/instant/asgi.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/instant/settings.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/instant/urls.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/instant/wsgi.py" create mode 100755 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/manage.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/req.txt" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/__init__.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/admin.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/apps.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/consumers.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/migrations/__init__.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/models.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/routing.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/index.html" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/room.html" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/tests.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/urls.py" create mode 100644 "\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/views.py" diff --git "a/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" "b/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" deleted file mode 160000 index acb65b2..0000000 --- "a/\345\214\272\345\237\237\347\275\221\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels" +++ /dev/null @@ -1 +0,0 @@ -Subproject commit acb65b214e4eb00a1de2ad40d456c31b2e5c2d8c diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.en.md" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.en.md" new file mode 100644 index 0000000..cc6f923 --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.en.md" @@ -0,0 +1,36 @@ +# 消息广播 + +#### Description +广播消息文字,下个版本迭代文件广播传输 + +#### Software Architecture +Software architecture description + +#### Installation + +1. xxxx +2. xxxx +3. xxxx + +#### Instructions + +1. xxxx +2. xxxx +3. xxxx + +#### Contribution + +1. Fork the repository +2. Create Feat_xxx branch +3. Commit your code +4. Create Pull Request + + +#### Gitee Feature + +1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md +2. Gitee blog [blog.gitee.com](https://blog.gitee.com) +3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore) +4. The most valuable open source project [GVP](https://gitee.com/gvp) +5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help) +6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/) diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.md" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.md" new file mode 100644 index 0000000..f804dac --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/README.md" @@ -0,0 +1,18 @@ +# 消息广播 + +![你可以得到](./img.png) + +#### 介绍 + +广播消息文字,下个版本迭代文件广播传输。区域网内传递消息。最终版本类似`QQ`聊天或`群`聊天。你可以在上班的时候找你的小伙伴快乐聊天。 + +#### 软件架构 +软件架构说明 +- python +- django + +#### 使用说明 + +- `pip install -r req` +- `python manage.py runserver 0.0.0.0:80` +- 访问`http://localhost/chat/index/`开始你们的聊天或传递消息 diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/img.png" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/img.png" new file mode 100644 index 0000000000000000000000000000000000000000..0fa495196729d7168f3f829c48df1b3c6f756455 GIT binary patch literal 37869 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\w+)/$", consumers.ChatConsumer.as_asgi()), +] diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/index.html" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/index.html" new file mode 100644 index 0000000..e826230 --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/index.html" @@ -0,0 +1,27 @@ + + + + + + Chat Rooms + + + What chat room would you like to enter?
+
+ + + + + \ No newline at end of file diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/room.html" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/room.html" new file mode 100644 index 0000000..3014a7b --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/templates/room.html" @@ -0,0 +1,50 @@ + + + + + + Chat Room + + +
+
+ +{{ room_name|json_script:"room-name" }} + + + \ No newline at end of file diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/tests.py" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/tests.py" new file mode 100644 index 0000000..e4defab --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/tests.py" @@ -0,0 +1 @@ +# from django.test import TestCase diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/urls.py" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/urls.py" new file mode 100644 index 0000000..55eeba5 --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/urls.py" @@ -0,0 +1,11 @@ +# @Author : hk +# @DateTime : 2023-09-18 11:44 +from django.urls import path + +from . import views + +urlpatterns = [ + path("", views.index, name="index"), + path("/", views.room, name="room"), + path('upload/', views.upload, name='upload') +] diff --git "a/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/views.py" "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/views.py" new file mode 100644 index 0000000..90ee410 --- /dev/null +++ "b/\346\266\210\346\201\257\345\271\277\346\222\255/dj-channels/instant/ws/views.py" @@ -0,0 +1,37 @@ +from django.shortcuts import render +from django.http import JsonResponse +from django.conf import settings +from pathlib import Path + +from datetime import datetime + + +# Create your views here. +def fm_datetime(): + now = datetime.now() + return now.strftime('%Y%m%d%H%M%S') + + +def index(request): + return render(request, "index.html") + + +def room(request, room_name): + return render(request, "room.html", {"room_name": room_name}) + + +def upload(request): + file = request.FILES.get('file') + folder = fm_datetime() + Path(folder).mkdir(exist_ok=True) + file_name = file.name + path = Path(settings.BASE_DIR).joinpath('file', folder, file_name) + if path.exists(): + file_name = '%s1%s' % (Path(file_name).name, Path(file_name).suffix) + file_path = ['file', folder, file_name] + with open(Path(settings.BASE_DIR).joinpath(*file_path)) as f: + f.write(file.read()) + return JsonResponse({'data': '/'.join(file_path)}) + + + -- Gitee