我正在尝试在django admin上创建一个列,其值根据操作表单的输入而改变
所以例如
#Action form
class CalculateDistanceForm(ActionForm):
latitude = forms.DecimalField()
longitude = forms.DecimalField(initial=0)
#Admin
@register(Distance)
class DistanceAdmin(admin.ModelAdmin):
list_display = ['latitude','longitude','distance']
action_form = CalculateDistanceForm
actions = ['update distance']
def distance(self,obj):
# how do i get the request instance to determine the post parameters on the form
return distance_calculator(obj.latitude,obj.longitude)
def update_distance(self,request,queryset):
lat = request.POST.get('latitude',None)
lon = request.POST.get('longitude',None)
queryset.calculate_price(lat,lon)
我的问题是如何动态显示查询集生成的新distance
?
答案 0 :(得分:1)
正如我在其他答案中所说,在列方法中没有简单的方法来获取request
。但即使它有可能,它也会与你的行动方法不同。
如果我们希望每次计算距离,我们可以将经度和经度保存在更永久的存储空间中。它可以是数据库,缓存或用户会话。保存到会话的示例:
@register(Distance)
class DistanceAdmin(admin.ModelAdmin):
list_display = ['latitude','longitude'] # not displaying distance by default
list_display_alt = ['latitude', 'longitude', 'distance'] # we will use that one if this was proper action call
action_form = CalculateDistanceForm
actions = ['update_distance']
def changelist_view(self, request, *args, **kwargs):
# We can't get user session in our column method, so we will copy our values from that session into `ModelAdmin` instance here:
if request.session.get('admin_latitude') and request.session.get('admin_longitude'):
self.latitude = request.session['admin_latitude']
self.longitude = request.session['admin_longitude']
return super(DistanceAdmin, self).changelist_view(self, request, *args, **kwargs)
def distance(self,obj):
return distance_calculator(obj.latitude,obj.longitude, self.latitude, self.longitude)
def get_list_display(self, request):
if hasattr(self, 'latitude') and hasattr(self, 'longitude'): # that means it was our action call, so we will modify default columns
return list_display_alt
return super(DistanceAdmin, self).get_list_display(request)
def update_distance(self,request,queryset):
#self.latitude = request.POST.get('latitude',None)
#self.longitude = request.POST.get('longitude',None)
# it will better to use form here instead of raw POST processing
form = CalculateDistanceForm(request.POST, request.FILES)
form.fields['action'].choices = (('update_distance', "Update distance"), ) # this is necessary because default ActionForm has no idea about valid actions
if form.is_valid():
latitude = form.cleaned_data['latitude']
longitude = form.cleaned_data['longitude']
request.session['admin_latitude'] = latitude
request.session['admin_longitude'] = longitude
else:
# if form wasn't valid, we can inform about that using messages framework here
答案 1 :(得分:0)
不幸的是,没有简单的解决方案可以通过distance
方法获取您的请求。此外,该请求将与您的发布请求不同,因为django admin将在操作完成处理后执行自动重定向,但我们可以通过在您的操作中返回响应来阻止该请求。
当我们返回响应时,我们可以将纬度和经度保存到ModelAdmin
实例中,稍后在distance
方法中检索它。
@register(Distance)
class DistanceAdmin(admin.ModelAdmin):
list_display = ['latitude','longitude'] # not displaying distance by default
list_display_alt = ['latitude', 'longitude', 'distance'] # we will use that one if this was proper action call
action_form = CalculateDistanceForm
actions = ['update_distance']
def distance(self,obj):
return distance_calculator(obj.latitude,obj.longitude, self.latitude, self.longitude)
def get_list_display(self, request):
if hasattr(self, 'latitude') and hasattr(self, 'longitude'): # that means it was our action call, so we will modify default columns
return list_display_alt
return super(DistanceAdmin, self).get_list_display(request)
def update_distance(self,request,queryset):
#self.latitude = request.POST.get('latitude',None)
#self.longitude = request.POST.get('longitude',None)
# it will better to use form here instead of raw POST processing
form = CalculateDistanceForm(request.POST, request.FILES)
form.fields['action'].choices = (('update_distance', "Update distance"), ) # this is necessary because default ActionForm has no idea about valid actions
if form.is_valid():
self.latitude = form.cleaned_data['latitude']
self.longitude = form.cleaned_data['longitude']
request.method = GET # tricking default changelist_view to think that there is no action called, without that we will end up in infinite loop.
return self.changelist_view(request)
else:
# if form wasn't valid, we can inform about that using messages framework here