我是Django的新手(我正在使用Django 1.4& python 2.7)并且无法理解如何完成以下问题。
我在SO& S上进行了很多搜索。谷歌,到目前为止对如何解决这个问题变得非常困惑。
我在表单上有两个html选择列表 - Industry&部门。当用户从Industry html选择列表中选择Engineering时,Sector html选择列表应仅使用Engineering选项动态填充。与行业html选择列表中的其他选择相同。扇区html选择列表应该在没有页面刷新的情况下动态填充 - 所以我假设必须使用JQuery / AJAX。
我不确定我是否正确设置了下面的UserProfile模型。工业与工业扇区html选择列表出现在表单和工作中,但不相互依赖 - 它们是单独的models.PositiveIntegerField字段。也许是工业与工业扇区值应该是下面的UserProfile模型上的外键。 我需要一些建议。
这是我的用户models.py文件:
class UserProfile(models.Model):
SELECT_INDUSTRY = 0
ACCOUNTING = 1
ADMINISTRATION_OFFICE_SUPPORT = 2
BANKING_FINANCIAL_SERVICES = 3
CALL_CENTRE_CUSTOMER_SERVICE = 4
COMMUNITY_SERVICES_DEVELOPMENT = 5
CONSTRUCTION = 6
CONSULTING_STRATEGY = 7
DESIGN_ARCHITECTURE = 8
EDUCATION_TRAINING = 9
ENGINEERING = 10
EXECUTIVE_GENERAL_MANAGEMENT = 11
FARMING_ANIMALS_CONSERVATION = 12
GOVERNMENT_DEFENCE = 13
GRADUATE_ENTRY_LEVEL = 14
HEALTHCARE_MEDICAL = 15
HOSPITALITY_TRAVEL_TOURISM = 16
HUMAN_RESOURCES_RECRUITMENT = 17
INSURANCE_SUPERANNUATION = 18
INFORMATION_TECHNOLOGY_TELECOMMUNICATIONS = 19
LEGAL = 20
MANUFACTURING = 21
MARKETING_COMMUNICATIONS = 22
MEDIA_ADVERTISING_ARTS_ENTERTAINMENT = 23
MINING_RESOURCES_ENERGY = 24
REAL_ESTATE_PROPERTY = 25
RETAIL_CONSUMER_PRODUCTS = 26
SALES = 27
SCIENCE_TECHNOLOGY = 28
SELF_EMPLOYMENT = 29
SPORT_RECREATION = 30
TRADES_SERVICES = 31
TRANSPORT_LOGISTICS = 32
USER_PROFILE_CURRENT_INDUSTRY_TYPES = (
(SELECT_INDUSTRY, _('Select Current Industry')),
(ACCOUNTING, _('Accounting')),
(ADMINISTRATION_OFFICE_SUPPORT, _('Administration & Office Support')),
(BANKING_FINANCIAL_SERVICES, _('Banking & Financial Services')),
(CALL_CENTRE_CUSTOMER_SERVICE, _('Call Centre & Customer Service')),
(COMMUNITY_SERVICES_DEVELOPMENT, _('Community Services & Development')),
(CONSTRUCTION, _('Construction')),
(CONSULTING_STRATEGY, _('Consulting & Strategy')),
(DESIGN_ARCHITECTURE, _('Design & Architecture')),
(EDUCATION_TRAINING, _('Education & Training')),
(ENGINEERING, _('Engineering')),
(EXECUTIVE_GENERAL_MANAGEMENT, _('Executive & General Management')),
(FARMING_ANIMALS_CONSERVATION, _('Farming, Animals & Conservation')),
(GOVERNMENT_DEFENCE, _('Government & Defence')),
(GRADUATE_ENTRY_LEVEL, _('Graduate / Entry Level')),
(HEALTHCARE_MEDICAL, _('Healthcare & Medical')),
(HOSPITALITY_TRAVEL_TOURISM, _('Hospitality, Travel & Tourism')),
(HUMAN_RESOURCES_RECRUITMENT, _('Human Resources & Recruitment')),
(INSURANCE_SUPERANNUATION, _('Insurance & Superannuation')),
(INFORMATION_TECHNOLOGY_TELECOMMUNICATIONS, _('Information Technology & Telecommunications')),
(LEGAL, _('Legal')),
(MANUFACTURING, _('Manufacturing')),
(MARKETING_COMMUNICATIONS, _('Marketing & Communications')),
(MEDIA_ADVERTISING_ARTS_ENTERTAINMENT, _('Media, Advertising, Arts & Entertainment')),
(MINING_RESOURCES_ENERGY, _('Mining, Resources & Energy')),
(REAL_ESTATE_PROPERTY, _('Real Estate & Property')),
(RETAIL_CONSUMER_PRODUCTS, _('Retail & Consumer Products')),
(SALES, _('Sales')),
(SCIENCE_TECHNOLOGY, _('Science & Technology')),
(SELF_EMPLOYMENT, _('Self Employment')),
(SPORT_RECREATION, _('Sport & Recreation')),
(TRADES_SERVICES, _('Trades & Services')),
(TRANSPORT_LOGISTICS, _('Transport & Logistics'))
)
SELECT_SECTOR_TYPE = 0
_ALL_ACCOUNTING_JOBS = 1
....(culled for brevity)
_ALL_ENGINEERING_JOBS = 124
AEROSPACE_ENGINEERING = 125
AUTOMOTIVE_ENGINEERING = 126
BUILDING_SERVICES_ENGINEERING = 127
CHEMICAL_ENGINEERING = 128
CIVIL_STRUCTURAL_ENGINEERING = 129
ELECTRICAL_ELECTRONIC_ENGINEERING = 130
ENGINEERING_DRAFTING = 131
ENVIRONMENTAL_ENGINEERING = 132
FIELD_ENGINEERING = 133
INDUSTRIAL_ENGINEERING = 134
MAINTENANCE = 135
MANAGEMENT = 136
MATERIALS_HANDLING_ENGINEERING = 137
MECHANICAL_ENGINEERING = 138
PROCESS_ENGINEERING = 139
PROJECT_ENGINEERING = 140
PROJECT_MANAGEMENT = 141
SUPERVISORS = 142
SYSTEMS_ENGINEERING = 143
WATER_WASTE_ENGINEERING = 144
OTHER_ENGINEERING_JOBS = 145
_ALL_EXECUTIVE_GENERAL_MANAGEMENT_JOBS = 146
....(culled for brevity)
OTHER_TRANSPORT_LOGISTICS_JOBS = 462
USER_PROFILE_CURRENT_SECTOR_TYPES = (
(SELECT_SECTOR_TYPE, _('Select Current Sector')),
.......(culled for brevity)
(OTHER_TRANSPORT_LOGISTICS_JOBS, _('Other Transport & Logistics Jobs'))
)
user = models.OneToOneField(User)
....(culled for brevity)
current_industry_type = models.PositiveIntegerField(choices=USER_PROFILE_CURRENT_INDUSTRY_TYPES, default=SELECT_INDUSTRY, validators=[MinValueValidator(1)])
current_sector_type = models.PositiveIntegerField(choices=USER_PROFILE_CURRENT_SECTOR_TYPES, default=SELECT_SECTOR_TYPE, validators=[MinValueValidator(1)])
....(culled for brevity)
.
我见过django-smart-selects,但我不确定这是一个动态的解决方案,我不确定是否必须为Industry& S添加单独的模型。部门与然后为Industry& amp;添加外键扇区到上面的UserProfile模型。
我希望我能以某种方式轻松获得Industry&扇区html选择使用AJAX或JQuery相互依赖的列表。
任何建议和帮助都将不胜感激。
答案 0 :(得分:4)
当我遇到这个问题时,我使用 AJAX 来选择2个依赖项。首先,我使用 Django Form ,如:
# I avoid the importation of the choices to make answer shorter
class YourForm(forms.Form):
industry = forms.ChoiceField(choices=USER_PROFILE_CURRENT_INDUSTRY_TYPES)
sector = forms.ChoiceField(choices=USER_PROFILE_CURRENT_SECTOR_TYPES)
# ... other fields
我将避免视图的基础知识(如何管理GET / POST方法)和基本的HTML django表单,我将直接转到 AJAX函数:
我们假设选择器ID为: #id_sector
和 #id_industry
function get_industry(){
jQuery.ajax({
async: false,
type: "POST",
url: "/a/get/industry/",
data: "sector_id=" + $('#id_sector').val(),
success: function(response) {
result = JSON.parse(response);
if (result) {
// I usually receive a list of items here
// I use this list to replace the dependant select
$('#id_industry').empty() // Use to empty the select
// Now we append the industry options we've received
for(var i=0;i < result.item_list.length;i++){
$('#id_industry').append($('<option>', {
value: result.item_list[i]['id'],
text: result.item_list[i]['name']
}));
}
} else {
console.log('error');
}
}
});
}
function get_sector(){
jQuery.ajax({
async: false,
type: "POST",
url: "/a/get/sector/",
data: "industry_id=" + $('#id_industry').val(),
success: function(response) {
result = JSON.parse(response);
if (result) {
$('#id_sector').empty() // Use to empty the select
// Now we append the sector options we've received
for(var i=0;i < result.item_list.length;i++){
$('#id_sector').append($('<option>', {
value: result.item_list[i]['id'],
text: result.item_list[i]['name']
}));
}
} else {
console.log('error');
}
}
});
}
现在我要展示 AJAX视图。您可以在名为ajax.py的文件中设置 AJAX视图:
from yourapp.models import USER_PROFILE_CURRENT_SECTOR_TYPES
INDUSTRY_DICT = {
4: range(14,36),
5: range(36,58),
6: range(58,80),
7: range(80,102),
8: range(102,124),
10: range(124,146) # This is the only true equivalence that you passed to me
}
@csrf_exempt
def get_sectors(request):
response = []
industry_id = int(request.POST['industry_id'])
# With the sector_id you know wich sector the user has selected
# You should generate the list based in your needs
data = []
if industry_id:
sectors = INDUSTRY_DICT[industry_id] # This return a list of ID's of sectors
# Then make loop over all sectors
for sector_id in sectors:
# To get the sector name you should use another dict
# I think you already have it in USER_PROFILE_CURRENT_SECTOR_TYPES
# Remember to import it (check above)
sector_name = USER_PROFILE_CURRENT_SECTOR_TYPES[sector_id]
# We append the id and the name to replace options in the HTML
data.append({'id':sector_id, 'name':sector_name})
response = { 'item_list':data } # We send back the list
return HttpResponse(simplejson.dumps(response))
# If we get any error, or cannot get the sector, we send an empty response
response = {}
return HttpResponse(simplejson.dumps(response))
我会避免添加第二个 AJAX 函数'get_sectors
',因为我习惯你理解逻辑,它应该和这个函数一样,但你会收到{{1而不是industry_id
,我认为你可以面对第二个功能。
设置url之前的最后一步是定义管理选择更改并调用AJAX函数的函数:
sector_id
您需要在 urls.py 中添加两个网址:
$("#id_sector").change(function(){
get_industry(); // AJAX function call when sector is selected
});
$("#id_industry").change(function(){
get_sector(); // AJAX function call when industry is selected
});
当您看到# ... YOUR OTHER URLS
url(r'^a/get/industry/?$', 'yourproject.ajax.get_industries', name='get_industries'),
url(r'^a/get/sector/?$', 'yourproject.ajax.get_sectors', name='get_sectors'),
时,这是指行业选择器ID,与$('#id_industry')
相同是指行业选择器ID
我称之为 AJAX功能在HTML模板中
$('#id_sector')
文件中,我通常会将AJAX视图添加到.py
文件ajax.py
,如果您想知道如何在 AJAX 中管理 CSRF令牌 >功能,你可以去:CSRF & AJAX: Official Docs @csrf_exempt
已更改为get_industries(request)
首先你应该有等价,你可以有不同的方式,你可以有2个模型工业和扇区,并使用外键关联它们但我认为你没有模型所以你可以有2个字典,一个针对行业,一个针对行业。
我将使用等价词,你应该改变你需要的词的值:
get_sectors(request)
这将生成一个dict,如果你执行INDUSTRY_DICT = {
4: range(14,36),
5: range(36,58),
6: range(58,80),
7: range(80,102),
8: range(102,124),
10: range(124,146) # This is the only equivalence that you passed to me
}
,它将返回应该出现在select中的扇区的ID列表。使用新更改检查上述功能。