I am trying to create a column on django admin whose values changes based on the input from an action form
我正在尝试在django admin上创建一个列,其值根据操作表单的输入而更改
So for example
所以举个例子
#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)
My question is how can i dynamically display the new distance
generated by the queryset?
我的问题是如何动态显示查询集生成的新距离?
2 个解决方案
#1
1
As I said in other answer, there is no simple way to get request
in column method. But even if it will be possible, it will be different from one in your action method.
正如我在其他答案中所说,没有简单的方法来获取列方法中的请求。但即使它有可能,它也会与你的行动方法不同。
If we want to have our distance calculated every time, we can save our latitude and longitude in some more permanent storage. It can be database, cache or user session. Example with saving into session:
如果我们希望每次计算距离,我们可以将经度和经度保存在更永久的存储空间中。它可以是数据库,缓存或用户会话。保存到会话的示例:
@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
#2
0
Unfortunately, there is no easy solution to get your request in distance
method. Also, that request will be different that your post request because django admin will do automatic redirection after action is done processing, but we can prevent that by returning response inside your action.
不幸的是,没有简单的解决方案来获取您的远程方法请求。此外,该请求将与您的发布请求不同,因为django admin将在操作完成处理后执行自动重定向,但我们可以通过在您的操作中返回响应来阻止该请求。
When we are returning response in action, we can save latitude and longitude into ModelAdmin
instance and retrieve it later in distance
method.
当我们返回响应时,我们可以将经度和经度保存到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
#1
1
As I said in other answer, there is no simple way to get request
in column method. But even if it will be possible, it will be different from one in your action method.
正如我在其他答案中所说,没有简单的方法来获取列方法中的请求。但即使它有可能,它也会与你的行动方法不同。
If we want to have our distance calculated every time, we can save our latitude and longitude in some more permanent storage. It can be database, cache or user session. Example with saving into session:
如果我们希望每次计算距离,我们可以将经度和经度保存在更永久的存储空间中。它可以是数据库,缓存或用户会话。保存到会话的示例:
@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
#2
0
Unfortunately, there is no easy solution to get your request in distance
method. Also, that request will be different that your post request because django admin will do automatic redirection after action is done processing, but we can prevent that by returning response inside your action.
不幸的是,没有简单的解决方案来获取您的远程方法请求。此外,该请求将与您的发布请求不同,因为django admin将在操作完成处理后执行自动重定向,但我们可以通过在您的操作中返回响应来阻止该请求。
When we are returning response in action, we can save latitude and longitude into ModelAdmin
instance and retrieve it later in distance
method.
当我们返回响应时,我们可以将经度和经度保存到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