Use ObjectRead helper for all list and detail views

This commit is contained in:
Mark Veidemanis 2022-12-08 07:20:46 +00:00
parent 1e85e830b2
commit 8840b04059
Signed by: m
GPG Key ID: 5ACFCEED46C0904F
12 changed files with 321 additions and 354 deletions

View File

@ -0,0 +1,72 @@
{% load pretty %}
{% include 'partials/notify.html' %}
{% if live is not None %}
<h1 class="title">Live {{ context_object_name_singular }} info</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% block live_tbody %}
{% for key, item in live.items %}
{% if key in pretty %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
<pre>{{ item|pretty }}</pre>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
{% endblock %}
</tbody>
</table>
{% endif %}
{% if object is not None %}
<h1 class="title">{{ title_singular }} info</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% block tbody %}
{% for key, item in object.items %}
{% if key in pretty %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
<pre>{{ item|pretty }}</pre>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
{% endblock %}
</tbody>
</table>
{% endif %}

View File

@ -0,0 +1,33 @@
{% extends 'partials/generic-detail.html' %}
{% block tbody %}
{% for key, item in object.items %}
<tr>
{% if key == 'trade_ids' %}
<th>{{ key }}</th>
<td>
{% if item is not None %}
{% for trade_id in item %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{% url 'trade_action' type=type trade_id=trade_id %}"
hx-trigger="click"
hx-target="#modals-here"
hx-swap="innerHTML"
class="button is-small {% if trade_id in valid_trade_ids %}is-primary{% else %}is-warning{% endif %}">
{{ trade_id }}
</button>
{% endfor %}
{% endif %}
</td>
{% else %}
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
{% endblock %}

View File

@ -1,53 +0,0 @@
{% load pretty %}
{% include 'partials/notify.html' %}
<h1 class="title">Live information</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key, item in live_info.items %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="title">Stored information</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key, item in db_info.items %}
{% if key == 'instruments' %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
<pre>{{ item|pretty }}</pre>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>

View File

@ -0,0 +1,45 @@
{% include 'partials/notify.html' %}
{% if page_title is not None %}
<h1 class="title is-4">{{ page_title }}</h1>
{% endif %}
{% if page_subtitle is not None %}
<h1 class="subtitle">{{ page_subtitle }}</h1>
{% endif %}
<div class="buttons">
{% if submit_url is not None %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{{ submit_url }}"
hx-trigger="click"
hx-target="#modals-here"
class="button is-info">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-plus"></i>
</span>
<span>{{ title_singular }}</span>
</span>
</button>
{% endif %}
{% if delete_all_url is not None %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-delete="{{ delete_all_url }}"
hx-trigger="click"
hx-target="#modals-here"
hx-swap="innerHTML"
hx-confirm="Are you sure you wish to delete all {{ context_object_name }}?"
class="button is-info">
<span class="icon-text">
<span class="icon">
<i class="fa-solid fa-xmark"></i>
</span>
<span>Delete all {{ context_object_name }} </span>
</span>
</button>
{% endif %}
</div>
{% include detail_template %}

View File

@ -1,53 +0,0 @@
{% load pretty %}
{% include 'partials/notify.html' %}
<h1 class="title">Live information</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key, item in live_info.items %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endfor %}
</tbody>
</table>
<h1 class="title">Stored information</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key, item in db_info.items %}
{% if key == 'response' %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
<pre>{{ item|pretty }}</pre>
{% endif %}
</td>
</tr>
{% else %}
<tr>
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
</tr>
{% endif %}
{% endfor %}
</tbody>
</table>

View File

@ -1,39 +0,0 @@
{% include 'partials/notify.html' %}
<h1 class="title">Live information</h1>
<table class="table is-fullwidth is-hoverable">
<thead>
<th>attribute</th>
<th>value</th>
</thead>
<tbody>
{% for key, item in items.items %}
<tr>
{% if key == 'trade_ids' %}
<th>{{ key }}</th>
<td>
{% if item is not None %}
{% for trade_id in item %}
<button
hx-headers='{"X-CSRFToken": "{{ csrf_token }}"}'
hx-get="{% url 'trade_action' type=type trade_id=trade_id %}"
hx-trigger="click"
hx-target="#modals-here"
hx-swap="innerHTML"
class="button is-small {% if trade_id in valid_trade_ids %}is-primary{% else %}is-warning{% endif %}">
{{ trade_id }}
</button>
{% endfor %}
{% endif %}
</td>
{% else %}
<th>{{ key }}</th>
<td>
{% if item is not None %}
{{ item }}
{% endif %}
</td>
{% endif %}
</tr>
{% endfor %}
</tbody>
</table>

View File

@ -3,7 +3,7 @@ import uuid
from django.core.exceptions import ImproperlyConfigured from django.core.exceptions import ImproperlyConfigured
from django.core.paginator import Paginator from django.core.paginator import Paginator
from django.db.models import QuerySet from django.db.models import QuerySet
from django.http import Http404, HttpResponseBadRequest from django.http import Http404, HttpResponse, HttpResponseBadRequest
from django.urls import reverse from django.urls import reverse
from django.views.generic.detail import DetailView from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView from django.views.generic.edit import CreateView, DeleteView, UpdateView
@ -105,15 +105,20 @@ class ObjectList(RestrictedViewMixin, ObjectNameMixin, ListView):
# copied from BaseListView # copied from BaseListView
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.request = request
self.object_list = self.get_queryset(**kwargs)
allow_empty = self.get_allow_empty()
type = kwargs.get("type", None) type = kwargs.get("type", None)
if not type: if not type:
return HttpResponseBadRequest("No type specified") return HttpResponseBadRequest("No type specified")
if type not in self.allowed_types: if type not in self.allowed_types:
return HttpResponseBadRequest("Invalid type specified") return HttpResponseBadRequest("Invalid type specified")
self.request = request
self.object_list = self.get_queryset(**kwargs)
if isinstance(self.object_list, HttpResponse):
return self.object_list
if isinstance(self.object_list, HttpResponseBadRequest):
return self.object_list
allow_empty = self.get_allow_empty()
self.template_name = f"wm/{type}.html" self.template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8] unique = str(uuid.uuid4())[:8]
@ -208,8 +213,6 @@ class ObjectCreate(RestrictedViewMixin, ObjectNameMixin, CreateView):
return self.get(self.request, **self.kwargs, form=form) return self.get(self.request, **self.kwargs, form=form)
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
self.request = request
self.kwargs = kwargs
type = kwargs.get("type", None) type = kwargs.get("type", None)
if not type: if not type:
return HttpResponseBadRequest("No type specified") return HttpResponseBadRequest("No type specified")
@ -218,6 +221,9 @@ class ObjectCreate(RestrictedViewMixin, ObjectNameMixin, CreateView):
self.template_name = f"wm/{type}.html" self.template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8] unique = str(uuid.uuid4())[:8]
self.request = request
self.kwargs = kwargs
list_url_args = {} list_url_args = {}
for arg in self.list_url_args: for arg in self.list_url_args:
list_url_args[arg] = locals()[arg] list_url_args[arg] = locals()[arg]
@ -253,8 +259,75 @@ class ObjectCreate(RestrictedViewMixin, ObjectNameMixin, CreateView):
class ObjectRead(RestrictedViewMixin, ObjectNameMixin, DetailView): class ObjectRead(RestrictedViewMixin, ObjectNameMixin, DetailView):
allowed_types = ["modal", "widget", "window", "page"] allowed_types = ["modal", "widget", "window", "page"]
window_content = "window-content/object.html" window_content = "window-content/object.html"
detail_template = "partials/generic-detail.html"
page_title = None
page_subtitle = None
model = None model = None
# submit_url_name = None
detail_url_name = None
# WARNING: TAKEN FROM locals()
detail_url_args = ["type"]
request = None
def get(self, request, *args, **kwargs):
type = kwargs.get("type", None)
if not type:
return HttpResponseBadRequest("No type specified")
if type not in self.allowed_types:
return HttpResponseBadRequest()
self.template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
detail_url_args = {}
for arg in self.detail_url_args:
if arg in locals():
detail_url_args[arg] = locals()[arg]
elif arg in kwargs:
detail_url_args[arg] = kwargs[arg]
self.request = request
self.object = self.get_object(**kwargs)
if isinstance(self.object, HttpResponse):
return self.object
orig_type = type
if type == "page":
type = "modal"
context = self.get_context_data()
context["title"] = self.title + f" ({type})"
context["title_singular"] = self.title_singular
context["unique"] = unique
context["window_content"] = self.window_content
context["detail_template"] = self.detail_template
if self.page_title:
context["page_title"] = self.page_title
if self.page_subtitle:
context["page_subtitle"] = self.page_subtitle
context["type"] = type
context["context_object_name"] = self.context_object_name
context["context_object_name_singular"] = self.context_object_name_singular
if self.detail_url_name is not None:
context["detail_url"] = reverse(
self.detail_url_name, kwargs=detail_url_args
)
# Return partials for HTMX
if self.request.htmx:
if request.headers["HX-Target"] == self.context_object_name + "-info":
self.template_name = self.detail_template
elif orig_type == "page":
self.template_name = self.detail_template
else:
context["window_content"] = self.detail_template
return self.render_to_response(context)
class ObjectUpdate(RestrictedViewMixin, ObjectNameMixin, UpdateView): class ObjectUpdate(RestrictedViewMixin, ObjectNameMixin, UpdateView):

View File

@ -1,20 +1,21 @@
import uuid
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseBadRequest
from django.shortcuts import render
from django.views import View
from two_factor.views.mixins import OTPRequiredMixin from two_factor.views.mixins import OTPRequiredMixin
from core.forms import AccountForm from core.forms import AccountForm
from core.models import Account from core.models import Account
from core.util import logs from core.util import logs
from core.views import ObjectCreate, ObjectDelete, ObjectList, ObjectUpdate from core.views import ObjectCreate, ObjectDelete, ObjectList, ObjectRead, ObjectUpdate
log = logs.get_logger(__name__) log = logs.get_logger(__name__)
class AccountInfo(LoginRequiredMixin, OTPRequiredMixin, View): class AccountInfo(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
context_object_name_singular = "account"
context_object_name = "accounts"
detail_url_name = "account_info"
detail_url_args = ["type", "pk"]
VIEWABLE_FIELDS_MODEL = [ VIEWABLE_FIELDS_MODEL = [
"name", "name",
"exchange", "exchange",
@ -24,20 +25,11 @@ class AccountInfo(LoginRequiredMixin, OTPRequiredMixin, View):
"supported_symbols", "supported_symbols",
# "instruments", # "instruments",
] ]
allowed_types = ["modal", "widget", "window", "page"]
window_content = "window-content/account-info.html"
def get(self, request, type, pk): def get_object(self, **kwargs):
""" pk = kwargs.get("pk")
Get the account details.
:param account_id: The id of the account.
"""
if type not in self.allowed_types:
return HttpResponseBadRequest
template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
try: try:
account = Account.get_by_id(pk, request.user) account = Account.get_by_id(pk, self.request.user)
except Account.DoesNotExist: except Account.DoesNotExist:
message = "Account does not exist" message = "Account does not exist"
message_class = "danger" message_class = "danger"
@ -46,8 +38,7 @@ class AccountInfo(LoginRequiredMixin, OTPRequiredMixin, View):
"message_class": message_class, "message_class": message_class,
"window_content": self.window_content, "window_content": self.window_content,
} }
return render(request, template_name, context) return self.render_to_response(context)
live_info = account.client.get_account() live_info = account.client.get_account()
live_info = live_info live_info = live_info
account_info = account.__dict__ account_info = account.__dict__
@ -56,18 +47,8 @@ class AccountInfo(LoginRequiredMixin, OTPRequiredMixin, View):
} }
account_info["supported_symbols"] = ", ".join(account_info["supported_symbols"]) account_info["supported_symbols"] = ", ".join(account_info["supported_symbols"])
if type == "page": self.extra_context = {"live": live_info}
type = "modal" return account_info
context = {
"db_info": account_info,
"live_info": live_info,
"pk": pk,
"type": type,
"unique": unique,
"window_content": self.window_content,
}
return render(request, template_name, context)
class AccountList(LoginRequiredMixin, OTPRequiredMixin, ObjectList): class AccountList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
@ -91,19 +72,6 @@ class AccountCreate(LoginRequiredMixin, OTPRequiredMixin, ObjectCreate):
submit_url_name = "account_create" submit_url_name = "account_create"
# class AccountRead(LoginRequiredMixin, ObjectRead):
# model = Account
# context_object_name = "accounts"
# submit_url_name = "account_read"
# fields = (
# "name",
# "exchange",
# "api_key",
# "api_secret",
# "sandbox",
# )
class AccountUpdate(LoginRequiredMixin, OTPRequiredMixin, ObjectUpdate): class AccountUpdate(LoginRequiredMixin, OTPRequiredMixin, ObjectUpdate):
model = Account model = Account
form_class = AccountForm form_class = AccountForm

View File

@ -1,11 +1,8 @@
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.views import View
from core.models import Callback, Hook, Signal from core.models import Callback, Hook, Signal
from core.views import ObjectList
def get_callbacks(user, hook=None, signal=None): def get_callbacks(user, hook=None, signal=None):
@ -17,21 +14,30 @@ def get_callbacks(user, hook=None, signal=None):
return callbacks return callbacks
class Callbacks(LoginRequiredMixin, View): class Callbacks(LoginRequiredMixin, ObjectList):
allowed_types = ["modal", "widget", "window", "page"]
window_content = "window-content/objects.html"
list_template = "partials/callback-list.html" list_template = "partials/callback-list.html"
page_title = "List of received callbacks" page_title = "List of received callbacks"
async def get(self, request, type, object_type, object_id): context_object_name_singular = "callback"
if type not in self.allowed_types: context_object_name = "callbacks"
return HttpResponseBadRequest
template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
list_url_name = "callbacks"
list_url_args = ["type", "object_type", "object_id"]
def get_callbacks(self, user, hook=None, signal=None):
if hook:
cast = {"hook": hook, "hook__user": user}
elif signal:
cast = {"signal": signal, "signal__user": user}
callbacks = Callback.objects.filter(**cast)
return callbacks
def get_queryset(self, **kwargs):
object_type = kwargs.get("object_type")
object_id = kwargs.get("object_id")
if object_type == "hook": if object_type == "hook":
try: try:
hook = Hook.objects.get(id=object_id, user=request.user) hook = Hook.objects.get(id=object_id, user=self.request.user)
except Hook.DoesNotExist: except Hook.DoesNotExist:
message = "Hook does not exist." message = "Hook does not exist."
message_class = "danger" message_class = "danger"
@ -40,11 +46,11 @@ class Callbacks(LoginRequiredMixin, View):
"class": message_class, "class": message_class,
"type": type, "type": type,
} }
return render(request, template_name, context) return self.render_to_response(context)
callbacks = get_callbacks(request.user, hook) callbacks = self.get_callbacks(self.request.user, hook)
elif object_type == "signal": elif object_type == "signal":
try: try:
signal = Signal.objects.get(id=object_id, user=request.user) signal = Signal.objects.get(id=object_id, user=self.request.user)
except Signal.DoesNotExist: except Signal.DoesNotExist:
message = "Signal does not exist." message = "Signal does not exist."
message_class = "danger" message_class = "danger"
@ -53,20 +59,9 @@ class Callbacks(LoginRequiredMixin, View):
"class": message_class, "class": message_class,
"type": type, "type": type,
} }
return render(request, template_name, context) return self.render_to_response(context)
callbacks = get_callbacks(request.user, signal=signal) callbacks = self.get_callbacks(self.request.user, signal=signal)
else: else:
callbacks = get_callbacks(request.user) return HttpResponseBadRequest("Invalid object type")
if type == "page":
type = "modal"
context = { return callbacks
"title": f"Callbacks ({type})",
"unique": unique,
"window_content": self.window_content,
"list_template": self.list_template,
"object_list": callbacks,
"type": type,
"page_title": self.page_title,
}
return render(request, template_name, context)

View File

@ -1,16 +1,11 @@
import uuid
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseBadRequest
from django.shortcuts import render from django.shortcuts import render
from django.views import View
from rest_framework.parsers import FormParser
from two_factor.views.mixins import OTPRequiredMixin 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 from core.views import ObjectList, ObjectRead
log = logs.get_logger(__name__) log = logs.get_logger(__name__)
@ -71,42 +66,27 @@ class Positions(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
return items return items
class PositionAction(LoginRequiredMixin, OTPRequiredMixin, View): class PositionAction(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
allowed_types = ["modal", "widget", "window", "page"] detail_template = "partials/position-detail.html"
window_content = "window-content/view-position.html"
parser_classes = [FormParser]
def get(self, request, type, account_id, symbol): context_object_name_singular = "position"
""" context_object_name = "positions"
Get live information for a trade.
"""
if type not in self.allowed_types:
return HttpResponseBadRequest()
template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
account = Account.get_by_id(account_id, request.user) detail_url_name = "position_action"
detail_url_args = ["type", "account_id", "symbol"]
def get_object(self, **kwargs):
account_id = kwargs.get("account_id")
symbol = kwargs.get("symbol")
account = Account.get_by_id(account_id, self.request.user)
info = account.client.get_position_info(symbol) info = account.client.get_position_info(symbol)
valid_trade_ids = list(
annotate_positions([info], request.user, return_order_ids=True)
)
# Remove some fields from the info dict
del info["long"] del info["long"]
del info["short"] del info["short"]
valid_trade_ids = list(
if type == "page": annotate_positions([info], self.request.user, return_order_ids=True)
type = "modal" )
context = { self.extra_context = {"valid_trade_ids": valid_trade_ids}
"title": f"Position info ({type})", return info
"unique": unique,
"window_content": self.window_content,
"type": type,
"items": info,
"valid_trade_ids": valid_trade_ids,
}
return render(request, template_name, context)
def delete(self, request, account_id, side, symbol): def delete(self, request, account_id, side, symbol):
""" """

View File

@ -1,80 +1,39 @@
import uuid
from django.contrib.auth.mixins import LoginRequiredMixin from django.contrib.auth.mixins import LoginRequiredMixin
from django.http import HttpResponseBadRequest
from django.shortcuts import render
from django.urls import reverse
from django.views import View
from two_factor.views.mixins import OTPRequiredMixin from two_factor.views.mixins import OTPRequiredMixin
from core.exchanges import GenericAPIError from core.exchanges import GenericAPIError
from core.models import Account from core.models import Account
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_profit(user): class Profit(LoginRequiredMixin, OTPRequiredMixin, ObjectList):
items = []
accounts = Account.objects.filter(user=user)
for account in accounts:
try:
details = account.client.get_account()
pl = details["pl"]
item = {
"account": account,
"pl": float(pl),
"balance": details["balance"],
"currency": details["currency"],
}
items.append(item)
except GenericAPIError:
continue
return items
class Profit(LoginRequiredMixin, OTPRequiredMixin, View):
allowed_types = ["modal", "widget", "window", "page"]
window_content = "window-content/objects.html"
list_template = "partials/profit-list.html" list_template = "partials/profit-list.html"
page_title = "Profit by account" page_title = "Profit by account"
page_subtitle = None page_subtitle = None
context_object_name_singular = "profit" context_object_name_singular = "profit"
context_object_name = "profit" context_object_name = "profit"
def get(self, request, type): list_url_name = "profit"
if type not in self.allowed_types: list_url_args = ["type"]
return HttpResponseBadRequest
self.template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
items = get_profit(request.user)
orig_type = type def get_queryset(self, **kwargs):
if type == "page": items = []
type = "modal" accounts = Account.objects.filter(user=self.request.user)
cast = { for account in accounts:
"type": orig_type, try:
} details = account.client.get_account()
list_url = reverse("profit", kwargs={**cast}) pl = details["pl"]
context = { item = {
"title": f"Profit ({type})", "account": account,
"unique": unique, "pl": float(pl),
"window_content": self.window_content, "balance": details["balance"],
"list_template": self.list_template, "currency": details["currency"],
"object_list": items, }
"type": type, items.append(item)
"page_title": self.page_title, except GenericAPIError:
"page_subtitle": self.page_subtitle, continue
"list_url": list_url, return items
"context_object_name_singular": self.context_object_name_singular,
"context_object_name": self.context_object_name,
}
# 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)

View File

@ -1,5 +1,3 @@
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
@ -15,25 +13,23 @@ from core.views import (
ObjectDelete, ObjectDelete,
ObjectList, ObjectList,
ObjectNameMixin, ObjectNameMixin,
ObjectRead,
ObjectUpdate, ObjectUpdate,
) )
log = logs.get_logger(__name__) log = logs.get_logger(__name__)
class TradeAction(LoginRequiredMixin, OTPRequiredMixin, View): class TradeAction(LoginRequiredMixin, OTPRequiredMixin, ObjectRead):
allowed_types = ["modal", "widget", "window", "page"] context_object_name_singular = "position"
window_content = "window-content/trade.html" context_object_name = "positions"
def get(self, request, type, trade_id): detail_url_name = "trade_action"
""" detail_url_args = ["type", "trade_id"]
Get live information for a trade.
""" def get_object(self, **kwargs):
if type not in self.allowed_types: trade_id = kwargs.get("trade_id")
return HttpResponseBadRequest() db_info = Trade.get_by_id_or_order(trade_id, self.request.user)
template_name = f"wm/{type}.html"
unique = str(uuid.uuid4())[:8]
db_info = Trade.get_by_id_or_order(trade_id, request.user)
if db_info is None: if db_info is None:
return HttpResponseBadRequest("Trade not found.") return HttpResponseBadRequest("Trade not found.")
if db_info.order_id is not None: if db_info.order_id is not None:
@ -50,21 +46,12 @@ class TradeAction(LoginRequiredMixin, OTPRequiredMixin, View):
else: else:
live_info = {} live_info = {}
if type == "page":
type = "modal"
db_info = db_info.__dict__ db_info = db_info.__dict__
del db_info["_state"] del db_info["_state"]
del db_info["_original"] del db_info["_original"]
context = {
"title": f"Trade info ({type})",
"unique": unique,
"window_content": self.window_content,
"type": type,
"db_info": db_info,
"live_info": live_info,
}
return render(request, template_name, context) self.extra_context = {"live": live_info, "pretty": ["response"]}
return db_info
class TradeList(LoginRequiredMixin, OTPRequiredMixin, ObjectList): class TradeList(LoginRequiredMixin, OTPRequiredMixin, ObjectList):