Using Application Engine to Import Data from Files

本文将指导您如何使用 Application Engine 从平面文件导入数据至 PeopleSoft 数据库,包括创建文件布局定义、加载数据及使用 SQL 和 PeopleCode 的步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You can use application engine to import files into tables in your PeopleSoft Database. Prior to version 8, the only way to programmatically do this was by using SQR. However, you now have the ability to create a File Layout Definition object and using Peoplecode, you can load a file directly into your database.

Application Engine is extremely powerful when utilized correctly. For example, you can utilize functionality such as peoplecode, SQL, Do While, Do Until, and Do Select. Therefore, you have the ability to manipulate the data just as you were capable of doing using SQR.

I'm going to walk through loading data from a flat file into a table using Application Engine. This example is a very simple one and is easy to follow. So lets get started!

First and foremost, you will need to create a File Layout Definition.

For this example we are using a table that we have defined in Application Designer named "N_SDN_TBL". This table is constructed as follows:

---------------------- --------------
N_SDN_ID decimal 9,10
N_SDN_NAME char 50
N_SDN_TYPE char 12
N_SDN_SNCTION_PGM char 20
N_SDN_TITLE char 180
N_SDN_VSSL_CALLSGN char 8
N_SDN_VESSEL_TYPE char 25
N_SDN_VSSLTONNAGE char 14
N_SDN_GRT_REG_TON char 8
N_SDN_VESSEL_FLAG char 40
N_SDN_VSSL_OWNER char 150
N_SDN_REMARKS char 254

When you define a File Layout, you can define it with a format of FIXED, CSV, or XML. In this Example we are using Fixed. From Application Designer, simply create a new File Layout object. Right click on the File Layout and Insert a Record. For this example we choose N_SDN_TBL. Once you choose the record App Designer will add the record and its fields to the layout.

The Next step is to adjust the start and ending positions for each field. Simply double click on a field and enter the start and ending position for this field the way it is in your flat file. Once you go through and complete this process for each field you can save your file layout and start building your application engine program.

All we need for this program are two simple steps.

The first step will be a simple SQL step to truncate the table N_SDN_TBL.Second, we add another step for PeopleCode. The PeopleCode for loading this data into the table is written below.


/**********************************************************
FUNCTION TO IMPORT DATA
**********************************************************/
Function ImportSegment(&RS2 As Rowset, &RSParent As Rowset)
Local Rowset &RS1, &RSP;
Local string &RecordName;
Local Record &REC2, &RECP;
Local SQL &SQL1;
Local integer &I, &L;
&SQL1 = CreateSQL("%Insert(:1)");
&RecordName = "RECORD." | &RS2.DBRecordName;
&REC2 = CreateRecord(@(&RecordName));
&RECP = &RSParent(1).GetRecord(@(&RecordName));
For &I = 1 To &RS2.ActiveRowCount
&RS2(&I).GetRecord(1).CopyFieldsTo(&REC2);
If (EditRecord(&REC2)) Then
&SQL1.Execute(&REC2);
&RS2(&I).GetRecord(1).CopyFieldsTo(&RECP);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&RSP = &RSParent.GetRow(1).GetRowset(&L);
ImportSegment(&RS1, &RSP);
End-If;
End-For;
If &RSParent.ActiveRowCount > 0 Then
&RSParent.DeleteRow(1);
End-If;
Else
&LOGFILE.WriteRowset(&RS);
&LOGFILE.WriteLine("****Correct error in this record and delete all error messages");
&LOGFILE.WriteRecord(&REC2);
For &L = 1 To &RS2.GetRow(&I).ChildCount
&RS1 = &RS2.GetRow(&I).GetRowset(&L);
If (&RS1 <> Null) Then
&LOGFILE.WriteRowset(&RS1);
End-If;
End-For;
End-If;
End-For;
End-Function;



Rem *****************************************************************;
rem * Define our Objects *;
rem *****************************************************************;
Local File &FILE1
Local Record &REC1
Local SQL &SQL1
Local Rowset &RS1
Local integer &M


/******************************************************************/
/* LOAD A FILE CALLED SDN.FF */
/******************************************************************/

/* CREATE A HANDLE TO THE FILE AND THE LOGFILE SETTING THE ATTRIBUTES */

&FILE1 = GetFile("D:\FS800\N_INTERFACES\SDN\SDN.FF", "r", "a", %FilePath_Absolute);
&LOGFILE = GetFile("D:\FS800\N_INTERFACES\SDN\SDN.FF.err", "W", %FilePath_Absolute);

/* LOAD OUR FILELAYOUT TO THE FILE HANDLE */

&FILE1.SetFileLayout(FileLayout.N_SDN_TBL);
&LOGFILE.SetFileLayout(FileLayout.N_SDN_TBL);

/*************************************************************
CREATE A ROWSET FOR THE FILE AND ONE FOR THE RECORD THAT WE
WILL BE LOADING THEN READ EACH ROW OF THE FILE AND INSERT
IT INTO OUR TABLE
**************************************************************/

&RS1 = &FILE1.CreateRowset();
&RS = CreateRowset(Record.N_SDN_TBL);
&SQL1 = CreateSQL("%Insert(:1)");
&RS1 = &FILE1.ReadRowset();

While &RS1 <> Null;
ImportSegment(&RS1, &RS);
&RS1 = &FILE1.ReadRowset();
End-While;

&FILE1.Close();
&LOGFILE.Close();

That's all there really is to it. I hope that this example was helpful in providing you a simple, quick, and easy way
to load data from a fixed field length flat file into a table. There really is no need to continue to do these types of
applications using SQR. You should start programming using Application engine for any type of process that does not require a fancy report. Remember, Application Engine programs are objects that you can upgrade. SQR's are not.
MultiValueDictKeyError at /auth/users/ 'password' Request Method: POST Request URL: http://127.0.0.1:8000/auth/users/ Django Version: 4.2.21 Exception Type: MultiValueDictKeyError Exception Value: 'password' Exception Location: C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\utils\datastructures.py, line 86, in __getitem__ Raised during: account.views.UserView Python Executable: C:\Users\高琨\AppData\Local\Programs\Python\Python39\python.exe Python Version: 3.9.11 Python Path: ['C:\\Users\\高琨\\Desktop\\backend', 'C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\python39.zip', 'C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\DLLs', 'C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\lib', 'C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39', 'C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\lib\\site-packages'] Server time: Tue, 24 Jun 2025 10:29:49 +0800 Traceback Switch to copy-and-paste view C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\utils\datastructures.py, line 84, in __getitem__ list_ = super().__getitem__(key) … Local vars During handling of the above exception ('password'), another exception occurred: C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\exception.py, line 55, in inner response = get_response(request) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\core\handlers\base.py, line 197, in _get_response response = wrapped_callback(request, *callback_args, **callback_kwargs) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\views\decorators\csrf.py, line 56, in wrapper_view return view_func(*args, **kwargs) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\rest_framework\viewsets.py, line 124, in view return self.dispatch(request, *args, **kwargs) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\rest_framework\views.py, line 509, in dispatch response = self.handle_exception(exc) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\rest_framework\views.py, line 469, in handle_exception self.raise_uncaught_exception(exc) … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\rest_framework\views.py, line 480, in raise_uncaught_exception raise exc … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\rest_framework\views.py, line 506, in dispatch response = handler(request, *args, **kwargs) … Local vars C:\Users\高琨\Desktop\backend\account\views.py, line 31, in login password = request.data['password'] … Local vars C:\Users\高琨\AppData\Local\Programs\Python\Python39\lib\site-packages\django\utils\datastructures.py, line 86, in __getitem__ raise MultiValueDictKeyError(key) … Local vars Request information USER AnonymousUser GET No GET data POST Variable Value csrfmiddlewaretoken 'DWg42eYqodHAyGvU8iq7SW01Agw6SWsrGqn2RNRtENkZgyesArpAfiWcxFAkniwR' last_login '' first_name '琨' last_name '高' date_joined '' email '3537676579@qq.com' desc '啊大苏打' mobile '13698551543' gender '' FILES Variable Value avatar <InMemoryUploadedFile: 屏幕截图 2025-05-16 181140.png (image/png)> COOKIES Variable Value csrftoken '********************' META Variable Value ALLUSERSPROFILE 'C:\\ProgramData' APPDATA 'C:\\Users\\高琨\\AppData\\Roaming' CHROME_CRASHPAD_PIPE_NAME '\\\\.\\pipe\\crashpad_2004_IXNEYUSYGSDNGSXV' COLORTERM 'truecolor' COMMONPROGRAMFILES 'C:\\Program Files\\Common Files' COMMONPROGRAMFILES(X86) 'C:\\Program Files (x86)\\Common Files' COMMONPROGRAMW6432 'C:\\Program Files\\Common Files' COMPUTERNAME 'LAPTOP-SUN5G18K' COMSPEC 'C:\\WINDOWS\\system32\\cmd.exe' CONTENT_LENGTH '75110' CONTENT_TYPE 'multipart/form-data; boundary=----WebKitFormBoundaryJGK9BG3i7H6CHnvK' CSRF_COOKIE 'dEh8ZJ3dqKNzS2TICj9Dxw6l7zeoFweA' DJANGO_SETTINGS_MODULE 'core.settings' DRIVERDATA 'C:\\Windows\\System32\\Drivers\\DriverData' EFC_9700_1262719628 '1' EFC_9700_1592913036 '1' EFC_9700_2283032206 '1' EFC_9700_2775293581 '1' EFC_9700_3789132940 '1' FPS_BROWSER_APP_PROFILE_STRING 'Internet Explorer' FPS_BROWSER_USER_PROFILE_STRING 'Default' GATEWAY_INTERFACE 'CGI/1.1' HOMEDRIVE 'C:' HOMEPATH '\\Users\\高琨' HTTP_ACCEPT 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7' HTTP_ACCEPT_ENCODING 'gzip, deflate, br, zstd' HTTP_ACCEPT_LANGUAGE 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6' HTTP_CACHE_CONTROL 'max-age=0' HTTP_CONNECTION 'keep-alive' HTTP_COOKIE '********************' HTTP_HOST '127.0.0.1:8000' HTTP_ORIGIN 'http://127.0.0.1:8000' HTTP_REFERER 'http://127.0.0.1:8000/auth/users/' HTTP_SEC_CH_UA '"Microsoft Edge";v="137", "Chromium";v="137", "Not/A)Brand";v="24"' HTTP_SEC_CH_UA_MOBILE '?0' HTTP_SEC_CH_UA_PLATFORM '"Windows"' HTTP_SEC_FETCH_DEST 'document' HTTP_SEC_FETCH_MODE 'navigate' HTTP_SEC_FETCH_SITE 'same-origin' HTTP_SEC_FETCH_USER '?1' HTTP_UPGRADE_INSECURE_REQUESTS '1' HTTP_USER_AGENT ('Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like ' 'Gecko) Chrome/137.0.0.0 Safari/537.36 Edg/137.0.0.0') LANG 'zh_CN.UTF-8' LOCALAPPDATA 'C:\\Users\\高琨\\AppData\\Local' LOGONSERVER '\\\\LAPTOP-SUN5G18K' NPM_HOME 'C:\\Program Files\\nodejs\\node_global' NUMBER_OF_PROCESSORS '16' NVM_HOME 'E:\\nvm' NVM_SYMLINK 'C:\\nvm4w\\nodejs' ONEDRIVE 'C:\\Users\\高琨\\OneDrive' ORIGINAL_XDG_CURRENT_DESKTOP 'undefined' OS 'Windows_NT' PATH ('E:\\bin\\;C:\\Windows\\system32;C:\\Windows;C:\\Windows\\System32\\Wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Windows\\System32\\OpenSSH\\;C:\\Windows\\system32\\config\\systemprofile\\AppData\\Local\\Microsoft\\WindowsApps;C:\\windows\\system32\\HWAudioDriver\\;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;E:\\nvm;C:\\nvm4w\\nodejs;C:\\Program ' 'Files\\dotnet\\;C:\\Program Files\\nodejs\\;C:\\Program ' 'Files\\nodejs\\node_global;C:\\Windows\\System32\\node_modules\\yarn\\bin;D:\\yarn_global\\bin;F:\\;C:\\Program ' 'Files ' '(x86)\\Tencent\\微信web开发者工具\\dll;C:\\Users\\高琨\\AppData\\Local\\Microsoft\\WindowsApps\\python3.exe;D:\\phpstudy_pro\\Extensions\\php\\php7.3.4nts;D:\\phpstudy_pro\\Extensions\\composer2.5.8;C:\\Program ' 'Files (x86)\\NetSarang\\Xftp ' '8\\;C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\Scripts\\;C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Python39\\;C:\\Users\\高琨\\AppData\\Local\\Programs\\Python\\Launcher\\;C:\\Users\\高琨\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Users\\高琨\\AppData\\Local\\Programs\\Microsoft ' 'VS Code\\bin;E:\\nvm;C:\\nvm4w\\nodejs;C:\\Users\\高琨\\AppData\\Roaming\\npm') PATHEXT '.COM;.EXE;.BAT;.CMD;.VBS;.VBE;.JS;.JSE;.WSF;.WSH;.MSC;.CPL' PATH_INFO '/auth/users/' PROCESSOR_ARCHITECTURE 'AMD64' PROCESSOR_IDENTIFIER 'Intel64 Family 6 Model 154 Stepping 3, GenuineIntel' PROCESSOR_LEVEL '6' PROCESSOR_REVISION '9a03' PROGRAMDATA 'C:\\ProgramData' PROGRAMFILES 'C:\\Program Files' PROGRAMFILES(X86) 'C:\\Program Files (x86)' PROGRAMW6432 'C:\\Program Files' PSMODULEPATH ('C:\\Users\\高琨\\Documents\\WindowsPowerShell\\Modules;C:\\Program ' 'Files\\WindowsPowerShell\\Modules;C:\\WINDOWS\\system32\\WindowsPowerShell\\v1.0\\Modules') PUBLIC 'C:\\Users\\Public' QUERY_STRING '' REMOTE_ADDR '127.0.0.1' REMOTE_HOST '' REQUEST_METHOD 'POST' RUN_MAIN 'true' SCRIPT_NAME '' SERVER_NAME '127.0.0.1' SERVER_PORT '8000' SERVER_PROTOCOL 'HTTP/1.1' SERVER_SOFTWARE 'WSGIServer/0.2' SESSIONNAME 'Console' SYSTEMDRIVE 'C:' SYSTEMROOT 'C:\\WINDOWS' TEMP 'C:\\Users\\高琨\\AppData\\Local\\Temp' TERM_PROGRAM 'vscode' TERM_PROGRAM_VERSION '1.101.1' TMP 'C:\\Users\\高琨\\AppData\\Local\\Temp' USERDOMAIN 'LAPTOP-SUN5G18K' USERDOMAIN_ROAMINGPROFILE 'LAPTOP-SUN5G18K' USERNAME '高琨' USERPROFILE 'C:\\Users\\高琨' VSCODE_INJECTION '1' VSCODE_NONCE '71bb0211-da42-4580-bb3d-e761a3af6e04' VSCODE_STABLE '1' WINDIR 'C:\\WINDOWS' ZES_ENABLE_SYSMAN '1' wsgi.errors <_io.TextIOWrapper name='<stderr>' mode='w' encoding='utf-8'> wsgi.file_wrapper <class 'wsgiref.util.FileWrapper'> wsgi.input <django.core.handlers.wsgi.LimitedStream object at 0x000001EBE9AE46D0> wsgi.multiprocess False wsgi.multithread True wsgi.run_once False wsgi.url_scheme 'http' wsgi.version (1, 0) Settings Using settings module core.settings Setting Value ABSOLUTE_URL_OVERRIDES {} ADMINS [] ALLOWED_HOSTS ['*'] APPEND_SLASH True AUTHENTICATION_BACKENDS ['django.contrib.auth.backends.ModelBackend'] AUTH_PASSWORD_VALIDATORS '********************' AUTH_USER_MODEL 'account.User' BASE_DIR WindowsPath('C:/Users/高琨/Desktop/backend') CACHES {'default': {'BACKEND': 'django.core.cache.backends.locmem.LocMemCache'}} CACHE_MIDDLEWARE_ALIAS 'default' CACHE_MIDDLEWARE_KEY_PREFIX '********************' CACHE_MIDDLEWARE_SECONDS 600 CORS_ALLOW_ALL_ORIGINS True CSRF_COOKIE_AGE 31449600 CSRF_COOKIE_DOMAIN None CSRF_COOKIE_HTTPONLY False CSRF_COOKIE_MASKED False CSRF_COOKIE_NAME 'csrftoken' CSRF_COOKIE_PATH '/' CSRF_COOKIE_SAMESITE 'Lax' CSRF_COOKIE_SECURE False CSRF_FAILURE_VIEW 'django.views.csrf.csrf_failure' CSRF_HEADER_NAME 'HTTP_X_CSRFTOKEN' CSRF_TRUSTED_ORIGINS [] CSRF_USE_SESSIONS False DATABASES {'default': {'ATOMIC_REQUESTS': False, 'AUTOCOMMIT': True, 'CONN_HEALTH_CHECKS': False, 'CONN_MAX_AGE': 0, 'ENGINE': 'django.db.backends.sqlite3', 'HOST': '', 'NAME': WindowsPath('C:/Users/高琨/Desktop/backend/db.sqlite3'), 'OPTIONS': {}, 'PASSWORD': '********************', 'PORT': '', 'TEST': {'CHARSET': None, 'COLLATION': None, 'MIGRATE': True, 'MIRROR': None, 'NAME': None}, 'TIME_ZONE': None, 'USER': ''}} DATABASE_ROUTERS [] DATA_UPLOAD_MAX_MEMORY_SIZE 2621440 DATA_UPLOAD_MAX_NUMBER_FIELDS 1000 DATA_UPLOAD_MAX_NUMBER_FILES 100 DATETIME_FORMAT 'N j, Y, P' DATETIME_INPUT_FORMATS ['%Y-%m-%d %H:%M:%S', '%Y-%m-%d %H:%M:%S.%f', '%Y-%m-%d %H:%M', '%m/%d/%Y %H:%M:%S', '%m/%d/%Y %H:%M:%S.%f', '%m/%d/%Y %H:%M', '%m/%d/%y %H:%M:%S', '%m/%d/%y %H:%M:%S.%f', '%m/%d/%y %H:%M'] DATE_FORMAT 'N j, Y' DATE_INPUT_FORMATS ['%Y-%m-%d', '%m/%d/%Y', '%m/%d/%y', '%b %d %Y', '%b %d, %Y', '%d %b %Y', '%d %b, %Y', '%B %d %Y', '%B %d, %Y', '%d %B %Y', '%d %B, %Y'] DEBUG True DEBUG_PROPAGATE_EXCEPTIONS False DECIMAL_SEPARATOR '.' DEFAULT_AUTO_FIELD 'django.db.models.BigAutoField' DEFAULT_CHARSET 'utf-8' DEFAULT_EXCEPTION_REPORTER 'django.views.debug.ExceptionReporter' DEFAULT_EXCEPTION_REPORTER_FILTER 'django.views.debug.SafeExceptionReporterFilter' DEFAULT_FILE_STORAGE 'django.core.files.storage.FileSystemStorage' DEFAULT_FROM_EMAIL 'webmaster@localhost' DEFAULT_INDEX_TABLESPACE '' DEFAULT_TABLESPACE '' DISALLOWED_USER_AGENTS [] EMAIL_BACKEND 'django.core.mail.backends.smtp.EmailBackend' EMAIL_HOST 'localhost' EMAIL_HOST_PASSWORD '********************' EMAIL_HOST_USER '' EMAIL_PORT 25 EMAIL_SSL_CERTFILE None EMAIL_SSL_KEYFILE '********************' EMAIL_SUBJECT_PREFIX '[Django] ' EMAIL_TIMEOUT None EMAIL_USE_LOCALTIME False EMAIL_USE_SSL False EMAIL_USE_TLS False FILE_UPLOAD_DIRECTORY_PERMISSIONS None FILE_UPLOAD_HANDLERS ['django.core.files.uploadhandler.MemoryFileUploadHandler', 'django.core.files.uploadhandler.TemporaryFileUploadHandler'] FILE_UPLOAD_MAX_MEMORY_SIZE 2621440 FILE_UPLOAD_PERMISSIONS 420 FILE_UPLOAD_TEMP_DIR None FIRST_DAY_OF_WEEK 0 FIXTURE_DIRS [] FORCE_SCRIPT_NAME None FORMAT_MODULE_PATH None FORM_RENDERER 'django.forms.renderers.DjangoTemplates' IGNORABLE_404_URLS [] INSTALLED_APPS ['django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'rest_framework', 'corsheaders', 'account'] INTERNAL_IPS [] LANGUAGES [('af', 'Afrikaans'), ('ar', 'Arabic'), ('ar-dz', 'Algerian Arabic'), ('ast', 'Asturian'), ('az', 'Azerbaijani'), ('bg', 'Bulgarian'), ('be', 'Belarusian'), ('bn', 'Bengali'), ('br', 'Breton'), ('bs', 'Bosnian'), ('ca', 'Catalan'), ('ckb', 'Central Kurdish (Sorani)'), ('cs', 'Czech'), ('cy', 'Welsh'), ('da', 'Danish'), ('de', 'German'), ('dsb', 'Lower Sorbian'), ('el', 'Greek'), ('en', 'English'), ('en-au', 'Australian English'), ('en-gb', 'British English'), ('eo', 'Esperanto'), ('es', 'Spanish'), ('es-ar', 'Argentinian Spanish'), ('es-co', 'Colombian Spanish'), ('es-mx', 'Mexican Spanish'), ('es-ni', 'Nicaraguan Spanish'), ('es-ve', 'Venezuelan Spanish'), ('et', 'Estonian'), ('eu', 'Basque'), ('fa', 'Persian'), ('fi', 'Finnish'), ('fr', 'French'), ('fy', 'Frisian'), ('ga', 'Irish'), ('gd', 'Scottish Gaelic'), ('gl', 'Galician'), ('he', 'Hebrew'), ('hi', 'Hindi'), ('hr', 'Croatian'), ('hsb', 'Upper Sorbian'), ('hu', 'Hungarian'), ('hy', 'Armenian'), ('ia', 'Interlingua'), ('id', 'Indonesian'), ('ig', 'Igbo'), ('io', 'Ido'), ('is', 'Icelandic'), ('it', 'Italian'), ('ja', 'Japanese'), ('ka', 'Georgian'), ('kab', 'Kabyle'), ('kk', 'Kazakh'), ('km', 'Khmer'), ('kn', 'Kannada'), ('ko', 'Korean'), ('ky', 'Kyrgyz'), ('lb', 'Luxembourgish'), ('lt', 'Lithuanian'), ('lv', 'Latvian'), ('mk', 'Macedonian'), ('ml', 'Malayalam'), ('mn', 'Mongolian'), ('mr', 'Marathi'), ('ms', 'Malay'), ('my', 'Burmese'), ('nb', 'Norwegian Bokmål'), ('ne', 'Nepali'), ('nl', 'Dutch'), ('nn', 'Norwegian Nynorsk'), ('os', 'Ossetic'), ('pa', 'Punjabi'), ('pl', 'Polish'), ('pt', 'Portuguese'), ('pt-br', 'Brazilian Portuguese'), ('ro', 'Romanian'), ('ru', 'Russian'), ('sk', 'Slovak'), ('sl', 'Slovenian'), ('sq', 'Albanian'), ('sr', 'Serbian'), ('sr-latn', 'Serbian Latin'), ('sv', 'Swedish'), ('sw', 'Swahili'), ('ta', 'Tamil'), ('te', 'Telugu'), ('tg', 'Tajik'), ('th', 'Thai'), ('tk', 'Turkmen'), ('tr', 'Turkish'), ('tt', 'Tatar'), ('udm', 'Udmurt'), ('uk', 'Ukrainian'), ('ur', 'Urdu'), ('uz', 'Uzbek'), ('vi', 'Vietnamese'), ('zh-hans', 'Simplified Chinese'), ('zh-hant', 'Traditional Chinese')] LANGUAGES_BIDI ['he', 'ar', 'ar-dz', 'ckb', 'fa', 'ur'] LANGUAGE_CODE 'zh-hans' LANGUAGE_COOKIE_AGE None LANGUAGE_COOKIE_DOMAIN None LANGUAGE_COOKIE_HTTPONLY False LANGUAGE_COOKIE_NAME 'django_language' LANGUAGE_COOKIE_PATH '/' LANGUAGE_COOKIE_SAMESITE None LANGUAGE_COOKIE_SECURE False LOCALE_PATHS [] LOGGING {} LOGGING_CONFIG 'logging.config.dictConfig' LOGIN_REDIRECT_URL '/accounts/profile/' LOGIN_URL '/accounts/login/' LOGOUT_REDIRECT_URL None MANAGERS [] MEDIA_ROOT 'C:/Users/高琨/Desktop/backend/media' MEDIA_URL '/media/' MESSAGE_STORAGE 'django.contrib.messages.storage.fallback.FallbackStorage' MIDDLEWARE ['corsheaders.middleware.CorsMiddleware', 'django.middleware.security.SecurityMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware'] MIGRATION_MODULES {} MONTH_DAY_FORMAT 'F j' NUMBER_GROUPING 0 PASSWORD_HASHERS '********************' PASSWORD_RESET_TIMEOUT '********************' PREPEND_WWW False REST_FRAMEWORK {'DEFAULT_AUTHENTICATION_CLASSES': ('rest_framework_simplejwt.authentication.JWTAuthentication',), 'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination', 'DEFAULT_PERMISSION_CLASSES': 'rest_framework.permissions.IsAuthenticated', 'NON_FIELD_ERRORS_KEY': '********************', 'PAGE_SIZE': 3} ROOT_URLCONF 'core.urls' SECRET_KEY '********************' SECRET_KEY_FALLBACKS '********************' SECURE_CONTENT_TYPE_NOSNIFF True SECURE_CROSS_ORIGIN_OPENER_POLICY 'same-origin' SECURE_HSTS_INCLUDE_SUBDOMAINS False SECURE_HSTS_PRELOAD False SECURE_HSTS_SECONDS 0 SECURE_PROXY_SSL_HEADER None SECURE_REDIRECT_EXEMPT [] SECURE_REFERRER_POLICY 'same-origin' SECURE_SSL_HOST None SECURE_SSL_REDIRECT False SERVER_EMAIL 'root@localhost' SESSION_CACHE_ALIAS 'default' SESSION_COOKIE_AGE 1209600 SESSION_COOKIE_DOMAIN None SESSION_COOKIE_HTTPONLY True SESSION_COOKIE_NAME 'sessionid' SESSION_COOKIE_PATH '/' SESSION_COOKIE_SAMESITE 'Lax' SESSION_COOKIE_SECURE False SESSION_ENGINE 'django.contrib.sessions.backends.db' SESSION_EXPIRE_AT_BROWSER_CLOSE False SESSION_FILE_PATH None SESSION_SAVE_EVERY_REQUEST False SESSION_SERIALIZER 'django.contrib.sessions.serializers.JSONSerializer' SETTINGS_MODULE 'core.settings' SHORT_DATETIME_FORMAT 'm/d/Y P' SHORT_DATE_FORMAT 'm/d/Y' SIGNING_BACKEND 'django.core.signing.TimestampSigner' SILENCED_SYSTEM_CHECKS [] SIMPLE_JWT {'ACCESS_TOKEN_LIFETIME': '********************', 'AUTH_HEADER_TYPES': ('Bearer',), 'REFRESH_TOKEN_LIFETIME': '********************', 'SIGNING_KEY': '********************'} STATICFILES_DIRS [] STATICFILES_FINDERS ['django.contrib.staticfiles.finders.FileSystemFinder', 'django.contrib.staticfiles.finders.AppDirectoriesFinder'] STATICFILES_STORAGE 'django.contrib.staticfiles.storage.StaticFilesStorage' STATIC_ROOT 'C:\\Users\\高琨\\Desktop\\backend\\static' STATIC_URL '/static/' STORAGES {'default': {'BACKEND': 'django.core.files.storage.FileSystemStorage'}, 'staticfiles': {'BACKEND': 'django.contrib.staticfiles.storage.StaticFilesStorage'}} TEMPLATES [{'APP_DIRS': True, 'BACKEND': 'django.template.backends.django.DjangoTemplates', 'DIRS': [], 'OPTIONS': {'context_processors': ['django.template.context_processors.debug', 'django.template.context_processors.request', 'django.contrib.auth.context_processors.auth', 'django.contrib.messages.context_processors.messages']}}] TEST_NON_SERIALIZED_APPS [] TEST_RUNNER 'django.test.runner.DiscoverRunner' THOUSAND_SEPARATOR ',' TIME_FORMAT 'P' TIME_INPUT_FORMATS ['%H:%M:%S', '%H:%M:%S.%f', '%H:%M'] TIME_ZONE 'Asia/Shanghai' USE_DEPRECATED_PYTZ False USE_I18N True USE_L10N True USE_THOUSAND_SEPARATOR False USE_TZ False USE_X_FORWARDED_HOST False USE_X_FORWARDED_PORT False WSGI_APPLICATION 'core.wsgi.application' X_FRAME_OPTIONS 'DENY' YEAR_MONTH_FORMAT 'F Y'
06-25
<think>我们遇到了一个Django的MultiValueDictKeyError异常,具体是在请求中缺少了'password'键。根据错误信息,异常发生在视图`account.views.UserView`中,具体位置是`account.views.py`的第31行,尝试从`request.data`中获取'password'键时发生。从请求信息中我们可以看到,POST数据中确实没有提供'password'字段,而是提供了其他字段(如last_name,first_name,email,avatar等)和一个文件(avatar)。这个请求的URL是`/auth/users/`,看起来是一个创建用户的端点。根据DjangoRESTframework(DRF)的常见做法,这可能是使用了DRF的UserViewSet,通常用于用户注册。错误的原因:在视图代码中,我们尝试访问`request.data['password']`,但是在请求的POST数据中并没有包含这个字段,因此引发了MultiValueDictKeyError。解决方案:1.首先,我们需要确保前端发送的请求中包含'password'字段。如果不包含,那么需要修改前端代码,确保在创建用户时发送密码。2.如果这个视图是用于用户注册,那么密码是必填项。因此,在视图代码中,我们应该检查请求数据中是否包含密码,如果不包含,应该返回一个错误响应,而不是让程序抛出异常。修改视图代码的建议:使用`request.data.get('password')`来获取密码,然后判断其是否存在。如果不存在,则返回一个400BadRequest响应,提示缺少密码。另外,从堆栈信息中我们看到,这个视图函数中有一个`login`函数(或者是一个处理登录的视图?),但错误发生在用户注册的请求上(URL为`/auth/users/`,通常对应注册)。所以我们需要检查视图函数的结构。根据错误信息,视图位于`account.views.py`的31行,代码为:password=request.data['password']我们将其改为更安全的方式,例如:原代码可能类似于:```pythondefcreate(self,request,*args,**kwargs):#...其他代码password=request.data['password']#...使用密码创建用户```修改后:```pythonpassword=request.data.get('password')ifpasswordisNone:returnResponse({'error':'Passwordisrequired'},status=status.HTTP_400_BAD_REQUEST)```但是,请注意,根据堆栈信息,这个视图可能是`UserView`,并且使用了DRF的视图集(ViewSet)。因此,我们需要检查视图集中的创建方法(create)或登录方法(如果有自定义的登录动作)。另外,从请求的POST数据中,我们看到有csrfmiddlewaretoken和其他用户信息,还有文件上传(avatar)。这看起来是一个创建用户的请求,但缺少了密码。所以,除了修改代码确保健壮性外,还需要确认前端是否确实需要发送密码。考虑到这些,以下是修改代码的示例:假设在`account/views.py`中,我们有如下的视图类:```pythonfromrest_frameworkimportviewsets,statusfromrest_framework.responseimportResponseclassUserView(viewsets.ModelViewSet):#...其他代码defcreate(self,request,*args,**kwargs):#获取密码password=request.data.get('password')ifnotpassword:returnResponse({"password":["Thisfieldisrequired."]},status=status.HTTP_400_BAD_REQUEST)#然后继续处理其他字段,创建用户#...其他代码```但是,如果这个视图不是用于创建用户,而是用于登录,那么URL可能应该是`/auth/login/`,而不是`/auth/users/`。根据URL,我们推断它可能是DRF的默认用户注册端点(如果使用了dj-rest-auth或类似库,可能会有这样的端点)。但这里我们看到是自定义的视图(account.views.UserView)。因此,请检查视图的具体逻辑,确保在尝试获取密码之前,请求中确实应该包含密码。另外,我们注意到请求中包含了头像文件(avatar),所以这个视图可能是处理用户注册的,并且允许上传头像。在这种情况下,密码是必填项。总结步骤:1.修改视图代码,使用`get`方法获取密码,并检查是否存在。2.如果不存在,返回400错误。下面是一个修改的代码示例:原始代码(出错行):```pythonpassword=request.data['password']```修改为:```pythonpassword=request.data.get('password')ifpasswordisNone:#返回错误响应,密码为必填项returnResponse({"detail":"Passwordisrequired."},status=status.HTTP_400_BAD_REQUEST)```注意:需要导入Response和status:```pythonfromrest_framework.responseimportResponsefromrest_frameworkimportstatus```但是,如果视图是基于APIView的,那么可以直接返回Response。如果是ViewSet,同样适用。另外,考虑到请求数据可能是multipart(因为有文件上传),所以`request.data`是一个MultiValueDict,但通常对于密码,我们期望只有一个值,所以使用`get`是安全的。最后,请确保在视图的其他地方也进行了必要的验证,例如使用序列化器(Serializer)来验证所有字段。如果使用了序列化器,那么可以在序列化器中设置密码字段为必填,这样即使视图中没有检查,序列化器验证也会捕获这个错误。但是,根据错误堆栈,错误发生在视图代码中,而不是序列化器验证中,所以当前代码可能没有使用序列化器,或者是在序列化器验证之前就访问了密码字段。因此,我们建议将必填字段的检查放在序列化器中进行,这样更符合DRF的设计模式。如果当前视图使用了序列化器,那么我们应该在序列化器中定义密码字段,并设置为required=True(默认就是True),然后让序列化器去验证。这样,在视图的create方法中,我们就不需要单独检查密码字段了,而是通过序列化器来统一验证。所以,更优的解决方案是使用序列化器,并在序列化器中包含密码字段,然后视图中的代码可能是这样的:```pythondefcreate(self,request,*args,**kwargs):serializer=self.get_serializer(data=request.data)serializer.is_valid(raise_exception=True)#这里会自动验证必填字段,如果密码不存在,会抛出ValidationError#...其他操作```这样,如果密码不存在,序列化器验证会失败,并返回400响应,其中包含字段错误信息。因此,如果当前视图没有使用序列化器,建议重构使用序列化器。如果已经使用了序列化器,那么错误应该在序列化器验证时被捕获,而不是在视图中直接访问`request.data`。所以,我们需要检查为什么在序列化器验证之前就访问了`request.data['password']`。考虑到时间,我们给出一个直接修改当前代码的解决方案(即添加检查)和一个推荐的重构方案(使用序列化器验证)。但根据错误堆栈,错误发生在视图的31行,所以我们先直接修复该行。根据以上分析,我们修改视图代码,避免直接通过键访问,而是使用get,并检查存在性。修改后的代码示例:```python#account/views.pyfromrest_frameworkimportstatusfromrest_framework.responseimportResponse#在原来的视图函数中修改classUserView(viewsets.ViewSet):#...其他方法defcreate(self,request):#获取密码password=request.data.get('password')ifnotpassword:returnResponse({"password":["Thisfieldisrequired."]},status=status.HTTP_400_BAD_REQUEST)#然后继续处理#...原来的代码```但是,请注意,如果视图已经使用了序列化器,我们应该去掉这个单独的检查,而让序列化器去处理。所以,我们需要根据上下文来决定。由于错误信息中显示是在`login`函数中,而视图是`UserView`,并且请求URL是`/auth/users/`,我猜测可能有一个自定义的登录动作被错误地放在了这个视图中。我们需要检查视图的结构。如果这个视图是一个ViewSet,那么`create`方法通常对应POST`/auth/users/`,而`login`可能是自定义的一个action。在错误信息中,我们看到:Raisedduring:account.views.UserView并且堆栈中最后一行是:C:\Users\高琨\Desktop\backend\account\views.py,line31,inlogin所以,实际上错误发生在`login`方法中,而不是`create`方法。因此,我们需要修改`login`方法。在`login`方法中,我们同样需要检查请求数据中是否包含密码。修改方式类似:```pythondeflogin(self,request):#获取用户名和密码username=request.data.get('username')password=request.data.get('password')ifnotusernameornotpassword:returnResponse({"detail":"Usernameandpasswordarerequired."},status=status.HTTP_400_BAD_REQUEST)#...其他登录逻辑```因此,根据错误发生在`login`方法,我们修改该方法。总结:在视图的`login`方法中,使用`get`方法获取密码,并检查是否存在,如果不存在则返回400错误。修改后的代码:```python#在account/views.py中的UserView类的login方法deflogin(self,request):try:#修改前:password=request.data['password']password=request.data.get('password')ifpasswordisNone:returnResponse({"error":"Passwordisrequired."},status=status.HTTP_400_BAD_REQUEST)#同样,检查用户名(或其他认证字段)username=request.data.get('username')#或者可能是email,根据你的登录方式ifusernameisNone:returnResponse({"error":"Usernameisrequired."},status=status.HTTP_400_BAD_REQUEST)#然后继续验证用户#...其他代码exceptExceptionase:#其他异常处理pass```这样修改后,如果请求中没有密码,就会返回一个明确的错误信息,而不是抛出异常。请根据实际的视图代码进行调整。由于我们无法看到完整的视图代码,以上代码仅供参考。最后,确保前端在登录请求中发送了密码字段。如果前端没有发送,需要修改前端代码。相关问题:1.如何正确使用DjangoRESTframework处理用户认证?2.在DRF中,如何设计用户注册和登录的API?3.如何全局处理DRF中的异常,避免出现500错误?4.在DRF中,如何使用序列化器验证必填字段?根据以上分析,我们给出修改代码的示例。</think>### 问题分析 您遇到的 `MultiValueDictKeyError: 'password'` 错误表明在 Django 视图处理 POST 请求时,尝试访问 `request.data['password']` 但请求体中缺少 `password` 字段。根据错误堆栈和请求信息: 1. **错误位置**:`account/views.py` 第 31 行尝试访问 `request.data['password']` 2. **请求内容**: - POST 数据包含:`first_name`, `last_name`, `email`, `mobile`, `avatar` 等字段 - **缺少**:`password` 字段 3. **上下文**:请求发送到 `/auth/users/` 端点,很可能是用户注册/创建功能 ### 解决方案 #### 1. 修复视图代码(推荐) 修改视图代码,使用更安全的 `.get()` 方法访问请求数据,并提供默认值或错误处理: ```python # account/views.py from rest_framework import status from rest_framework.response import Response def login(self, request): # 使用 get() 方法替代直接索引访问 password = request.data.get('password') if not password: # 返回明确的错误响应 return Response( {"error": "Password field is required"}, status=status.HTTP_400_BAD_REQUEST ) # 继续处理密码验证逻辑... # user = authenticate(username=email, password=password) ``` #### 2. 前端修复 确保前端表单/请求包含必要的 `password` 字段: ```html <!-- 前端表单示例 --> <form method="POST" enctype="multipart/form-data"> <input type="password" name="password" required> <!-- 其他字段... --> </form> ``` #### 3. 使用 Django REST Framework 序列化器(最佳实践) 创建序列化器自动处理字段验证: ```python # account/serializers.py from rest_framework import serializers class UserCreateSerializer(serializers.ModelSerializer): password = serializers.CharField(write_only=True, required=True) class Meta: model = User fields = ['email', 'password', 'first_name', 'last_name', 'avatar'] extra_kwargs = {'password': {'write_only': True}} def create(self, validated_data): user = User.objects.create_user( email=validated_data['email'], password=validated_data['password'], first_name=validated_data.get('first_name', ''), last_name=validated_data.get('last_name', '') ) return user ``` 在视图中使用序列化器: ```python # account/views.py from rest_framework import generics, status class UserCreateView(generics.CreateAPIView): serializer_class = UserCreateSerializer def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) # 自动返回400错误 self.perform_create(serializer) return Response(serializer.data, status=status.HTTP_201_CREATED) ``` ### 错误原因详解 - **`MultiValueDictKeyError`**:当访问 `request.POST['key']` 或 `request.data['key']` 时,如果键不存在就会抛出此异常 - **根本原因**:当前端请求缺少 `password` 字段时,直接索引访问会引发异常 - **解决方案核心**: 1. 使用安全的 `.get()` 方法访问字典 2. 添加显式的字段验证 3. 使用 DRF 序列化器自动处理验证 ### 预防措施 1. **始终验证必填字段**: ```python required_fields = ['password', 'email'] for field in required_fields: if field not in request.data: return Response({"error": f"{field} is required"}, status=400) ``` 2. **启用 DRF 验证**: ```python # settings.py REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': [...], 'EXCEPTION_HANDLER': 'rest_framework.views.exception_handler' } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值