本篇文章我會持續更新,把開發中遇到的一切orm相關的問題都放在這裏前端
使用django 的orm,數據庫用的mysql,在使用makemigrations和migrate生成數據庫表時,報以下錯誤:mysql
Traceback (most recent call last): File "manage.py", line 15, in <module> execute_from_command_line(sys.argv) File "C:\Program Files\Python37\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from _command_line utility.execute() File "C:\Program Files\Python37\lib\site-packages\django\core\management\__init__.py", line 375, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "C:\Program Files\Python37\lib\site-packages\django\core\management\base.py", line 316, in run_from_argv self.execute(*args, **cmd_options) File "C:\Program Files\Python37\lib\site-packages\django\core\management\base.py", line 353, in execute output = self.handle(*args, **options) File "C:\Program Files\Python37\lib\site-packages\django\core\management\base.py", line 83, in wrapped res = handle_func(*args, **kwargs) File "C:\Program Files\Python37\lib\site-packages\django\core\management\commands\migrate.py", line 203, in hand le fake_initial=fake_initial, File "C:\Program Files\Python37\lib\site-packages\django\db\migrations\executor.py", line 117, in migrate state = self._migrate_all_forwards(state, plan, full_plan, fake=fake, fake_initial=fake_initial) File "C:\Program Files\Python37\lib\site-packages\django\db\migrations\executor.py", line 147, in _migrate_all_f orwards state = self.apply_migration(state, migration, fake=fake, fake_initial=fake_initial) File "C:\Program Files\Python37\lib\site-packages\django\db\migrations\executor.py", line 244, in apply_migratio n state = migration.apply(state, schema_editor) File "C:\Program Files\Python37\lib\site-packages\django\db\migrations\migration.py", line 124, in apply operation.database_forwards(self.app_label, schema_editor, old_state, project_state) File "C:\Program Files\Python37\lib\site-packages\django\db\migrations\operations\models.py", line 514, in datab ase_forwards getattr(new_model._meta, self.option_name, set()), File "C:\Program Files\Python37\lib\site-packages\django\db\backends\base\schema.py", line 360, in alter_unique_ together self.execute(self._create_unique_sql(model, columns)) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\base\schema.py", line 133, in execute cursor.execute(sql, params) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\utils.py", line 100, in execute return super().execute(sql, params) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\utils.py", line 68, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\utils.py", line 77, in _execute_with_wrappe rs return executor(sql, params, many, context) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\utils.py", line 85, in _execute return self.cursor.execute(sql, params) File "C:\Program Files\Python37\lib\site-packages\django\db\utils.py", line 89, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "C:\Program Files\Python37\lib\site-packages\django\db\backends\utils.py", line 85, in _execute return self.cursor.execute(sql, params) File "C:\Program Files\Python37\lib\site-packages\django\db\backends\mysql\base.py", line 71, in execute return self.cursor.execute(query, args) File "C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py", line 170, in execute result = self._query(query) File "C:\Program Files\Python37\lib\site-packages\pymysql\cursors.py", line 328, in _query conn.query(q) File "C:\Program Files\Python37\lib\site-packages\pymysql\connections.py", line 516, in query self._affected_rows = self._read_query_result(unbuffered=unbuffered) File "C:\Program Files\Python37\lib\site-packages\pymysql\connections.py", line 727, in _read_query_result result.read() File "C:\Program Files\Python37\lib\site-packages\pymysql\connections.py", line 1066, in read first_packet = self.connection._read_packet() File "C:\Program Files\Python37\lib\site-packages\pymysql\connections.py", line 683, in _read_packet packet.check_error() File "C:\Program Files\Python37\lib\site-packages\pymysql\protocol.py", line 220, in check_error err.raise_mysql_exception(self._data) File "C:\Program Files\Python37\lib\site-packages\pymysql\err.py", line 109, in raise_mysql_exception raise errorclass(errno, errval) django.db.utils.InternalError: (1071, 'Specified key was too long; max key length is 767 bytes')
使用 如下命令能夠查看默認編碼sql
到mysql的配置文件裏把編碼改成utf8便可,修改步驟具體百度解決數據庫
配置文件裏修改django
default-storage-engine=INNODB
innodb_large_prefix=on
我遇到的問題和以上的方法都沒有關係,就把定義的字段,從新審查了一遍,把choices字段,能用SmallIntergerField或者PositiveIntegerField都由以前的IntegerField改爲前者兩個,把CharField的max_length超過1024的字段都換成TextField,把DateTimeField能換成DateField都改爲DateField。就這樣,問題奇蹟般的解決後端
在orm操做裏,作外鍵查詢時,反向查詢按表名時報錯,好比一個課程對象 course,須要去拿與course作一對一關聯的coursedetail數據,發現報錯course no attribute "coursedetail"restful
反覆檢查查詢字段,沒有問題,就是報錯,最後發現是由於一對一的兩個表數據量不統一,有的爲空,因此在一對一查詢時有NoneType對象,因此會報錯沒有coursedetail屬性。添加上匹配的字段後,正常返回數據app
首先,場景是這樣的,有個課程系統,課程表由於不一樣使用時間有不一樣的價格, 因此使用django的ccontent_type表把價格策略放進去,而後在作數據提取時,前端有個價格排行,以下:框架
後端接口,提取數據部分ssh
前端請求的結果:
數據庫用的mysql。遵循了restful規範,因此用了djangorestframwork框架
其餘可有可無的就不展現了
其實我整個數據庫的課程表就只有十五個,可是產生了重複的部分,由於數據庫表有價格策略數據,以下:
課程表:
價格策略表:
由於相同課程有不一樣的價格,因此致使出現了一個課程有多個數據
可是,我明明使用了distinct仍是沒法去重啊
而後網上查閱了不少資料,看django的官方文檔,有以下說法:
我加了:distinct('id')
報錯:DISTINCT ON fields is not supported by this database backend
意思是當前的數據庫不支持在distinct里加參數
這個方法是網上找到的最多的方法,我想說,老弟啊,我就是要取數據庫的對象啊,你這用values是把字段的值取出來啊,這個方法我想都沒想,直接放棄這個方法
固然是能夠用values的,方法是可行的,主要是什麼,我須要的是把數據庫的對象取出來,交給restframework去序列化,而後傳給前端的:
因此此法不行
如下是我想的方法,最後一個方法才能完美解決去重問題
用django的annotate()方法,原理就是先分組,就能夠把有重複數據的分組出來,而後再處理篩選便可,這方法已試,沒用
就在以下位置寫差費去重代碼
可是,由於取出來的數據是QuerySet對象,這個是django自帶的對象,咱們熟悉的Python的操做都不太好完成,怎麼去重嘛,想了不少,碼了不少種方法都不行,有點難度
由於什麼,你去重,是否是要先所有遍歷一遍,另外放進一個對象裏,而後當第二次遍歷相同數據時就再也不存進去就好了,提及來簡單,你另外建立的變量最終也得是QuerySet對象,而後QuerySet對象沒有 in 的判斷,像列表,字典,就有 if XXX in dict/list/tuple...,QuerySet就不支持這個if XXX in QuerySet的寫法
並且就算支持也沒有把數據存進去的方法,不存在append方法
在QuerySet源碼中找了兩個update,update_or_create()方法,不行,會報錯,因此這個方法也放棄
首先,看res.data裏的數據的對象是什麼類型:
這裏你要是用OrderedDict來進行後續操做你就大錯特錯了,我都是慢慢摸索出的,最後serializer序列化獲得的res.data是ReturnList對象,而並非OrederedDict對象
因此這裏建立一個ReturnList跟res.data進行拆分去重:
發現仍是報錯,看了源碼,貌似要傳入一個serializer對象才行,這裏又沒辦法了,最後仍是看源碼,在ReturnList源碼裏,找到幾個方法:
['__add__', '__class__', '__contains__', '__delattr__', '__delitem__', '__dict__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__iadd__', '__imul__', '__init__', '__init_subclass__', '__iter__', '__le__', '__len__', '__lt__', '__module__', '__mul__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__rmul__', '__setattr__', '__setitem__', '__sizeof__', '__str__', '__subclasshook__', '__weakref__', 'append', 'clear', 'copy', 'count', 'extend', 'index', 'insert', 'pop', 'remove', 'reverse', 'serializer', 'sort']
魔法方法就忽略了,看那幾個比較熟悉的方法名,看着是否是就是list的一些方法啊?因此,最後的代碼:
# 針對mysql數據庫數據去重 if query: temp = res.data temp.clear() for item in res.data: if item not in temp: temp.append(item) else: continue return Response(temp)
前端展現,正確返回,完成去重
這個問題耗了我幾個小時,終於找到了解決方法。
可是,此法並非通用的,由於結合了djagnorestframework才完成的,若是你沒用這個框架,那就不用考慮取到的數據必定得是數據庫對象了,使用values('xxxx')以後,再用用distinct('XX')傳參去重就好了。
報以下錯誤:
RuntimeError: You called this URL via POST, but the URL doesn't end in a slash and you have APPEND_SLASH set. Django can't redirect to the slash URL while maintaining POST data. Change your form to point to 127.0.0.1:8000/XXXX (note the trailing slash), or set APPEND_SLASH=False in your Django settings.
發現是由於在url定義的時候給結束符 【/】,而在請求測試的時候沒有給【/】:
因此二者統一就行。