Use CRUD helper for position list

This commit is contained in:
Mark Veidemanis 2022-12-08 07:20:07 +00:00
parent aa8ee887d3
commit d396abca84
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
3 changed files with 85 additions and 70 deletions

View File

@ -17,7 +17,7 @@
<th>trades</th> <th>trades</th>
<th>actions</th> <th>actions</th>
</thead> </thead>
{% for item in items %} {% for item in object_list %}
<tr class=" <tr class="
{% if item.unrealized_pl > 0 %}has-background-success-light {% if item.unrealized_pl > 0 %}has-background-success-light
{% elif item.unrealized_pl < 0 %}has-background-danger-light {% elif item.unrealized_pl < 0 %}has-background-danger-light

View File

@ -33,7 +33,7 @@ class RestrictedViewMixin:
page_kwarg = "page" page_kwarg = "page"
ordering = None ordering = None
def get_queryset(self): def get_queryset(self, **kwargs):
""" """
This function is overriden to filter the objects by the requesting user. This function is overriden to filter the objects by the requesting user.
""" """
@ -70,14 +70,18 @@ class RestrictedViewMixin:
class ObjectNameMixin(object): class ObjectNameMixin(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
if self.model is None:
self.title = self.context_object_name.title()
self.title_singular = self.context_object_name_singular.title()
else:
self.title_singular = self.model._meta.verbose_name.title() # Hook self.title_singular = self.model._meta.verbose_name.title() # Hook
self.context_object_name_singular = self.title_singular.lower() # hook self.context_object_name_singular = self.title_singular.lower() # hook
self.title = self.model._meta.verbose_name_plural.title() # Hooks self.title = self.model._meta.verbose_name_plural.title() # Hooks
self.context_object_name = self.title.lower() # hooks self.context_object_name = self.title.lower() # hooks
self.context_object_name = self.context_object_name.replace(" ", "") self.context_object_name = self.context_object_name.replace(" ", "")
self.context_object_name_singular = self.context_object_name_singular.replace( self.context_object_name_singular = (
" ", "" self.context_object_name_singular.replace(" ", "")
) )
super().__init__(*args, **kwargs) super().__init__(*args, **kwargs)
@ -97,11 +101,13 @@ class ObjectList(RestrictedViewMixin, ObjectNameMixin, ListView):
submit_url_name = None submit_url_name = None
delete_all_url_name = None delete_all_url_name = None
widget_options = None
# copied from BaseListView # copied from BaseListView
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.request = request self.request = request
self.object_list = self.get_queryset() self.object_list = self.get_queryset(**kwargs)
print("OBJ , ", self.object_list)
allow_empty = self.get_allow_empty() allow_empty = self.get_allow_empty()
type = kwargs.get("type", None) type = kwargs.get("type", None)
@ -132,9 +138,7 @@ class ObjectList(RestrictedViewMixin, ObjectNameMixin, ListView):
is_empty = not self.object_list is_empty = not self.object_list
if is_empty: if is_empty:
raise Http404("Empty list") raise Http404("Empty list")
submit_url = reverse(self.submit_url_name, kwargs={"type": type})
list_url = reverse(self.list_url_name, kwargs=list_url_args)
context = self.get_context_data() context = self.get_context_data()
context["title"] = self.title + f" ({type})" context["title"] = self.title + f" ({type})"
context["title_singular"] = self.title_singular context["title_singular"] = self.title_singular
@ -144,12 +148,19 @@ class ObjectList(RestrictedViewMixin, ObjectNameMixin, ListView):
context["page_title"] = self.page_title context["page_title"] = self.page_title
context["page_subtitle"] = self.page_subtitle context["page_subtitle"] = self.page_subtitle
context["type"] = type context["type"] = type
context["submit_url"] = submit_url
context["list_url"] = list_url
context["context_object_name"] = self.context_object_name context["context_object_name"] = self.context_object_name
context["context_object_name_singular"] = self.context_object_name_singular context["context_object_name_singular"] = self.context_object_name_singular
if self.submit_url_name is not None:
context["submit_url"] = reverse(self.submit_url_name, kwargs={"type": type})
if self.list_url_name is not None:
context["list_url"] = reverse(self.list_url_name, kwargs=list_url_args)
if self.delete_all_url_name: if self.delete_all_url_name:
context["delete_all_url"] = reverse(self.delete_all_url_name) context["delete_all_url"] = reverse(self.delete_all_url_name)
if self.widget_options:
context["widget_options"] = self.widget_options
# Return partials for HTMX # Return partials for HTMX
if self.request.htmx: if self.request.htmx:

View File

@ -3,7 +3,6 @@ import uuid
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseBadRequest from django.http import HttpResponseBadRequest
from django.shortcuts import render from django.shortcuts import render
from django.urls import reverse
from django.views import View from django.views import View
from rest_framework.parsers import FormParser from rest_framework.parsers import FormParser
from two_factor.views.mixins import OTPRequiredMixin from two_factor.views.mixins import OTPRequiredMixin
@ -11,24 +10,11 @@ from two_factor.views.mixins import OTPRequiredMixin
from core.exchanges import GenericAPIError from core.exchanges import GenericAPIError
from core.models import Account, Trade from core.models import Account, Trade
from core.util import logs from core.util import logs
from core.views import ObjectList
log = logs.get_logger(__name__) log = logs.get_logger(__name__)
def get_positions(user, account_id=None):
items = []
accounts = Account.objects.filter(user=user)
for account in accounts:
try:
positions = account.client.get_all_positions()
except GenericAPIError:
continue
for item in positions:
items.append(item)
return items
def annotate_positions(positions, user, return_order_ids=False): def annotate_positions(positions, user, return_order_ids=False):
""" """
Annotate positions with trade information. Annotate positions with trade information.
@ -55,7 +41,7 @@ def annotate_positions(positions, user, return_order_ids=False):
pass pass
class Positions(LoginRequiredMixin, OTPRequiredMixin, View): class Positions(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
allowed_types = ["modal", "widget", "window", "page"] allowed_types = ["modal", "widget", "window", "page"]
window_content = "window-content/objects.html" window_content = "window-content/objects.html"
list_template = "partials/position-list.html" list_template = "partials/position-list.html"
@ -63,47 +49,65 @@ class Positions(LoginRequiredMixin, OTPRequiredMixin, View):
page_subtitle = "Manual trades are editable under 'Bot Trades' tab." page_subtitle = "Manual trades are editable under 'Bot Trades' tab."
context_object_name_singular = "position" context_object_name_singular = "position"
context_object_name = "positions" context_object_name = "positions"
widget_options = 'gs-w="12" gs-h="1" gs-y="0" gs-x="0"'
def get(self, request, type, account_id=None): def get_queryset(self, **kwargs):
if type not in self.allowed_types: account_id = kwargs.get("account_id", None)
return HttpResponseBadRequest
self.template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
items = get_positions(request.user, account_id)
annotate_positions(items, request.user, return_order_ids=False)
orig_type = type
if type == "page":
type = "modal"
cast = {
"type": orig_type,
}
if account_id: if account_id:
cast["account_id"] = account_id self.extra_context["account_id"] = account_id
list_url = reverse("positions", kwargs={**cast}) items = []
context = { accounts = Account.objects.filter(user=self.request.user)
"title": f"Positions ({type})", for account in accounts:
"unique": unique, try:
"window_content": self.window_content, positions = account.client.get_all_positions()
"list_template": self.list_template, except GenericAPIError:
"items": items, continue
"type": type,
"page_title": self.page_title, for item in positions:
"page_subtitle": self.page_subtitle, items.append(item)
"list_url": list_url, annotate_positions(items, self.request.user, return_order_ids=False)
"context_object_name_singular": self.context_object_name_singular, return items
"context_object_name": self.context_object_name,
"widget_options": 'gs-w="12" gs-h="1" gs-y="0" gs-x="0"', # def get(self, request, type, account_id=None):
} # if type not in self.allowed_types:
# Return partials for HTMX # return HttpResponseBadRequest
if self.request.htmx: # self.template_name = f"wm/{type}.html"
if request.headers["HX-Target"] == self.context_object_name + "-table": # unique = str(uuid.uuid4())[:8]
self.template_name = self.list_template # items = get_positions(request.user, account_id)
elif orig_type == "page": # annotate_positions(items, request.user, return_order_ids=False)
self.template_name = self.list_template
else: # orig_type = type
context["window_content"] = self.list_template # if type == "page":
return render(request, self.template_name, context) # type = "modal"
# cast = {
# "type": orig_type,
# }
# if account_id:
# cast["account_id"] = account_id
# list_url = reverse("positions", kwargs={**cast})
# context = {
# "title": f"Positions ({type})",
# "unique": unique,
# "window_content": self.window_content,
# "list_template": self.list_template,
# "items": items,
# "type": type,
# "page_title": self.page_title,
# "page_subtitle": self.page_subtitle,
# "list_url": list_url,
# "context_object_name_singular": self.context_object_name_singular,
# "context_object_name": self.context_object_name,
# "widget_options": 'gs-w="12" gs-h="1" gs-y="0" gs-x="0"',
# }
# # Return partials for HTMX
# if self.request.htmx:
# if request.headers["HX-Target"] == self.context_object_name + "-table":
# self.template_name = self.list_template
# elif orig_type == "page":
# self.template_name = self.list_template
# else:
# context["window_content"] = self.list_template
# return render(request, self.template_name, context)
class PositionAction(LoginRequiredMixin, OTPRequiredMixin, View): class PositionAction(LoginRequiredMixin, OTPRequiredMixin, View):