Testing Views in django/Python - django-views

class UserProfile(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request):
user = self.request.user
user_id = user.id
client_info = ClientInformation.objects.filter(user_id=user_id).values('full_name', 'address1', 'address2', 'city', 'state', 'zipcode')
return JsonResponse(client_info[0])
def put(self, request):
try:
user = self.request.user
user_id = user.id
data = self.request.data
full_name = data['full_name']
address1 = data['address1']
address2 = data['address2']
city = data['city']
state = data['state']
zipcode = data['zipcode']
ClientInformation.objects.filter(user_id=user_id).update(full_name=full_name, address1=address1, address2=address2, city=city, state=state, zipcode=zipcode)
return Response({ 'success': 'Profile has been updated.' })
except:
return Response({ 'error': 'Something went wrong when updating profile.' })
class QuotesHistory(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request):
user = self.request.user
user_id = user.id
quotes = list(FuelQuotes.objects.filter(user_id=user_id).values('id', 'gallons', 'delivery_address', 'delivery_date', 'price', 'amount_due'))
return JsonResponse(quotes, safe=False)
def post(self, request):
try:
user = self.request.user
user_id = user.id
data = self.request.data
FuelQuotes.objects.create(user_id=user_id, gallons=data['gallons'], delivery_address=data['delivery_address'], delivery_date=data['delivery_date'], price=data['price'], amount_due=data['amount_due'])
print(FuelQuotes.objects.all())
return Response({ 'success': 'Fuel quote has been submitted.' })
except:
return Response({ 'error': 'Something went wrong when submitting fuel quote.' })
class GetPrice(APIView):
permission_classes = (IsAuthenticated,)
def get(self, request):
user = self.request.user
user_id = user.id
gallons = int(self.request.data['gallons'])
location_factor = 0.02 if ClientInformation.objects.get(user_id=user_id).state == 'TX' else 0.04
history_factor = 0.01 if len(FuelQuotes.objects.filter(user_id=user_id)) != 0 else 0
gallons_factor = 0.02 if gallons > 1000 else 0.03
company_factor = 0.1
price = (1.5 * (1 + (location_factor - history_factor + gallons_factor + company_factor)))
return JsonResponse({"price": round(price,3), "amount_due": round(gallons * price, 2)})
I'm trying to build a testing page in django for this views page, but I'm encountering lots of challenges

Related

request.user in createdview

How implement that the user in the Model Entities add automatically the user that is authenticated in django?
now, returning the following error:
error
I have tried differents methods that i have founding in the internet but not function. all cases return error in the momento to record a row.
only, i need that, in the moment that create a row, the user field was the user that is authenticated.
My Model:
class Entities(models.Model):
#class Category(models.Model):
id = models.BigAutoField(primary_key=True)
code = models.CharField(verbose_name='Código', max_length=10, blank=False, unique=True,
help_text='Codigo de entidad.')
name = models.CharField(max_length=150, verbose_name='Nombre', unique=True,
help_text='Nombre de la entidad.')
desc = models.CharField(max_length=500, null=True, blank=True, verbose_name='Descripción',
help_text='Descripción de la entidad.')
name_report = models.CharField(verbose_name='Nombre Reporte', max_length=100, blank=False, unique=True,
help_text='Rellenar para ACTIVAR el reporte')
long_desc = models.CharField(verbose_name='Descripción Larga', max_length=800, blank=True,
help_text='Descripción larga. Máximo 800 caracteres.')
language = models.CharField(verbose_name='Idioma', max_length=2, choices=languages, default='ES',
help_text='Idioma del reporte')
user = models.ForeignKey(User, default=0, verbose_name='Usuario', on_delete=models.DO_NOTHING)
date_created = models.DateTimeField(default=timezone.now, verbose_name='Creado', blank=False, unique=False)
date_updated = models.DateTimeField(default=timezone.now, verbose_name='Actualizado', blank=False, unique=False)
historical = HistoricalRecords()
def __str__(self):
return self.name
def toJSON(self):
item = model_to_dict(self)
return item
class Meta:
verbose_name = 'Entidad'
verbose_name_plural = 'Entidades'
ordering = ['id']
My CreateView:
class entitiesCreateView(LoginRequiredMixin, ValidatePermissionRequiredMixin, CreateView):
model = Entities
form_class = EntitiesForm
template_name = 'Entities/create.html'
success_url = reverse_lazy('erp:entities_list')
permission_required = 'add_Entities'
url_redirect = success_url
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'add':
form = self.get_form()
data = form.save()
else:
data['error'] = 'No ha ingresado a ninguna opción'
except Exception as e:
data['error'] = str(e)
return JsonResponse(data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Creación de una Entidad'
context['entity'] = 'Entidades'
context['list_url'] = self.success_url
context['action'] = 'add'
return context
My Form:
class EntitiesForm(ModelForm):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# for form in self.visible_fields():
# form.field.widget.attrs['class'] = 'form-control'
# form.field.widget.attrs['autocomplete'] = 'off'
self.fields['code'].widget.attrs['autofocus'] = True
class Meta:
model = Entities
fields = '__all__'
exclude = ['user','date_created','date_updated']
widgets = {
'name': forms.TextInput(
attrs={
'placeholder': 'Ingrese un nombre',
}
),
'desc': forms.Textarea(
attrs={
'placeholder': 'Ingrese un nombre',
'rows': 3,
'cols': 3
}
),
}
def save(self, commit=True):
data = {}
form = super()
try:
if form.is_valid():
**self.instante.user = self.request.user**
form.save()
else:
data['error'] = form.errors
except Exception as e:
data['error'] = str(e)
return data
SOLVED.
Adding, in the view, the line :
form.instance.user = self.request.user
full Createview would be :
class entitiesCreateView(LoginRequiredMixin, ValidatePermissionRequiredMixin, CreateView):
model = Entities
form_class = EntitiesForm
template_name = 'Entities/create.html'
success_url = reverse_lazy('erp:entities_list')
permission_required = 'add_Entities'
url_redirect = success_url
def dispatch(self, request, *args, **kwargs):
return super().dispatch(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'add':
form = self.get_form()
form.instance.user = self.request.user <============================
data = form.save()
else:
data['error'] = 'No ha ingresado a ninguna opción'
except Exception as e:
data['error'] = str(e)
return JsonResponse(data)
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['title'] = 'Creación de una Entidad'
context['entity'] = 'Entidades'
context['list_url'] = self.success_url
context['action'] = 'add'
return context
If you want to save additional data into form you can commit=False for this...
def post(self, request, *args, **kwargs):
data = {}
try:
action = request.POST['action']
if action == 'add':
form = self.get_form()
form = form.save(commit=False)
form.user = request.user
data = form.save()
else:
data['error'] = 'No ha ingresado a ninguna opción'
except Exception as e:
data['error'] = str(e)
return JsonResponse(data)

Is there a way I can get a list of all the items with balance variable in django

I have created an API that is being called by my react frontend. So the problem is this I have a viewset that shows a list of all customers in the database which works perfectly. I have also created a retrieve method that shows individual customer details and all the orders purchased. In this retrieve method, I have a variable that shows the balance for the customer. My question is, is there a way I can get a List of all customers with a balance that is greater than 0 and lower than 0
Here is my viewset
class CustomerViewSet(viewsets.ViewSet):
authentication_classes = [JWTAuthentication]
permission_classes = [IsAuthenticated]
def list(self, request):
customer = Customer.objects.all()
serializer = CustomerSerializer(customer, many=True, context={"request": request})
response_dict = {"error": False, "message": "All Customers List Data", "data": serializer.data}
return Response(response_dict)
def create(self, request):
try:
serializer = CustomerSerializer(data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
serializer.save()
dict_response = {"error": False, "message": "Customer Data Stored Successfully"}
except:
dict_response = {"error": True, "message": "Phone Number Exists In Database, Fill All Fields"}
return Response(dict_response)
def retrieve(self, request, pk=None):
queryset = Customer.objects.all()
customer = get_object_or_404(queryset, pk=pk)
serializer = CustomerSerializer(customer, context={"request": request})
serializer_data = serializer.data
# Accessing All the Orders Details of Current Customer
orders_details = Orders.objects.filter(customer_id=serializer_data["id"]).order_by('-id')
orders_details_serializers = OrdersSerializer(orders_details, many=True)
serializer_data["orders"] = orders_details_serializers.data
# Accessing All Orders of Current Customer
orders_count = Orders.objects.filter(customer_id=serializer_data["id"])
orders_count_serializer = OrdersSerializer(orders_count, many=True, context={"request": request})
# Total orders amount of current customer
orders_total = Orders.objects.filter(customer_id=serializer_data["id"])
amount = 0
discount = 0
kgs = 0
for total in orders_total:
amount = amount + float(total.amount)
discount = discount + float(total.discount)
kgs = kgs + float(total.kgs)
serializer_data1 = serializer.data
# Accessing All the Payment Details of Current Customer
payments_details = Payments.objects.filter(customer_id=serializer_data1["id"]).order_by('-id')
payments_details_serializers = PaymentsSerializer(payments_details, many=True)
serializer_data["payments"] = payments_details_serializers.data
serializer_data2 = serializer_data
payment_count = Payments.objects.filter(customer_id=serializer_data2["id"])
payment_count_serializer = PaymentsSerializer(payment_count, many=True, context={"request": request})
# Total Payment of current customer
payment_total = Payments.objects.filter(customer_id=serializer_data2["id"])
t_amount = 0
for balance in payment_total:
t_amount = t_amount + float(balance.payment)
balance = amount - t_amount
dict_response = {"error": False, "message": "Single Data Fetch",
"data": serializer_data,
"payment": len(payment_count_serializer.data),
"buy_total": amount,
"payed_total": t_amount,
"balance": balance,
"kgs": kgs,
"discount": discount,
"orders_count": len(orders_count_serializer.data)}
return Response(dict_response)
def update(self, request, pk=None):
try:
queryset = Customer.objects.all()
customer = get_object_or_404(queryset, pk=pk)
serializer = CustomerSerializer(customer, data=request.data, context={"request": request})
serializer.is_valid(raise_exception=True)
serializer.save()
dict_response = {"error": False, "message": "Customer Data Updated Successfully"}
except:
dict_response = {"error": True, "message": "An Error Occurred"}
return Response(dict_response)
def destroy(self, request, pk=None):
queryset = Customer.objects.all()
customer = get_object_or_404(queryset, pk=pk)
# serializer = PaymentsSerializer(customer, context={"request": request})
customer.delete()
return Response({"error": False, "message": "Customer Deleted"})
Any idea or solution on how I can achieve that
Here is the solution you may like
from django.db.models import Sum
order = Orders.objects.filter(customer_id=serializer_data['id']).aggregate(Sum('amount'))
total_order_sum = order.get('amount__sum')
payment = Payments.objects.filter(customer_id=serializer_data2["id"])..aggregate(Sum('payment'))
total_payment_sum = payment.get('payment__sum')
balance = float(total_order_sum - total_payment_sum)

Django Rest Framework can't identify serializer field name

This is the problem: I have a serializer field pointing to another serializer. I sending an allright request to server and I get this response:
{
"purchase_header": [
"This field is required."
]
}
But the field was sended by POST request (in debugger I can see it).
I finded this code in html.py (from DRF):
def parse_html_dict(dictionary, prefix=''):
"""
Used to support dictionary values in HTML forms.
{
'profile.username': 'example',
'profile.email': 'example#example.com',
}
-->
{
'profile': {
'username': 'example',
'email': 'example#example.com'
}
}
"""
ret = MultiValueDict()
regex = re.compile(r'^%s\.(.+)$' % re.escape(prefix))
for field in dictionary:
match = regex.match(field)
if not match:
continue
key = match.groups()[0]
value = dictionary.getlist(field)
ret.setlist(key, value)
return ret
Well, when debuging I can see that prefix variable contain "purchase_header" and field variable contain the same "purchase_header" string but de match fail returning None. Very rare... dictionary parameter contain all keys and values.
But If you can helpme I appreciate much.
This is the rest of significant code:
urls.py
router = DefaultRouter()
router.register(r'cancel-requests', PurchaseCancellationsRequestViewSet,
basename='purchase-cancel-requests')
router.register(r'invoices', PurchaseViewSet, basename='purchase')
urlpatterns = router.urls
urlpatterns += [path('payment-headers/', PaymentHeadersListAPIView.as_view(
), name='PaymentHeadersListAPIView')]
api.py
class PurchaseViewSet(viewsets.ModelViewSet):
"""
A viewset for viewing and editing purchases instances.
"""
serializer_class = PurchaseSerializer
queryset = Purchase.objects.all().order_by('-created_at')
permission_classes = (IsAuthenticated,)
serializer_action_classes = {
'list': PurchaseSerializer,
'create': PurchaseSerializer,
'retrieve': PurchaseSerializer,
'update': PurchaseSerializer,
'partial_update': PurchaseSerializer,
'destroy': PurchaseSerializer
}
def get_serializer_class(self):
try:
return self.serializer_action_classes[self.action]
except (KeyError, AttributeError):
return super().get_serializer_class()
def get_serializer(self, *args, **kwargs):
serializer_class = self.get_serializer_class()
kwargs["context"] = self.get_serializer_context()
return serializer_class(*args, **kwargs)
def get_list_queryset(self):
try:
store = Store.objects.get(my_owner=self.request.user)
except EmptyResultSet as e:
print("Data Error: {0}".format(e))
urlquery = self.request.GET.get('cancelled', '')
cancelled = False
if urlquery == 'true':
cancelled = True
elif urlquery == '':
# return all
return Purchase.objects.filter(created_for=store)
return Purchase.objects.filter(cancelled=cancelled, created_for=store)
def put(self, request, *args, **kwargs):
if request.user.is_seller:
raise PermissionDenied(
detail='Only owners can cancellate Purchases')
# seller create invoice cancellation request
return self.update(request, *args, **kwargs)
def post(self, request, *args, **kwargs):
request.data['created_by'] = request.user.pk
print(request.data)
if request.user.is_owner is True:
try:
request.data['created_for'] = Store.objects.get(
my_owner=request.user).pk
except Exception as e:
print(e)
return Response(data='User has no Store associated',
status=status.HTTP_400_BAD_REQUEST)
else:
try:
request.data['created_for'] = request.user.seller_profile \
.my_store.pk
except Exception as e:
print(e)
return Response(data='User has no Store associated',
status=status.HTTP_400_BAD_REQUEST)
return self.create(request, *args, **kwargs)
def list(self, request, *args, **kwargs):
# TODO: date ranges
if self.request.user.is_seller:
# TODO: Change -> Indeed the seller can get his own created
# purchases and refactor this to method
raise PermissionDenied(
detail='Only owners can get purchase list.')
queryset = self.get_list_queryset()
page = self.paginate_queryset(queryset)
if page is not None:
serializer = self.get_serializer(page, many=True)
return self.get_paginated_response(serializer.data)
serializer = self.get_serializer(queryset, many=True)
return Response(serializer.data)
serializers.py
from rest_framework import serializers
from .models import Purchase, PurchaseCancellationRequest, PurchaseHeader
class PurchaseHeaderSerializer(serializers.ModelSerializer):
class Meta:
model = PurchaseHeader
fields = ['id', 'name']
extra = {
'id': {'read_only': True},
'name': {'read_only': True}
}
class PurchaseSerializer(serializers.ModelSerializer):
purchase_header = PurchaseHeaderSerializer()
class Meta:
model = Purchase
fields = ['id', 'cancelled', 'created_at', 'created_by',
'created_for', 'pic', 'total_amount', 'purchase_header']
extra = {
'cancelled': {'read_only': True},
'created_at': {'read_only': True},
'id': {'read_only': True}
}
def validate_total_amount(self, value):
"""
Sanitize the amount value.
:return: total_amount as float
"""
total_amount = None
try:
total_amount = float(value)
except Exception as e:
print(e)
if total_amount:
return value
else:
raise serializers.ValidationError('Exists an error with '
'total_amount value, probably '
'an empty param or bad float '
'format')
def validate_cancelled(self, value):
"""
Sanitize the cancelled value.
:return: cancelled as python boolean
"""
cancelled = None
try:
cancelled = False if value == 'false' else True
except Exception as e:
print(e)
if cancelled:
return value
else:
raise serializers.ValidationError('Exists an error with '
'cancelled value, probably an '
'empty param or bad boolean '
'value')
def create(self, validated_data):
payment_header_pk = validated_data.pop('purchase_header')
payment_header_obj = PaymentHeader.objects.get(pk=payment_header_pk)
purchase_obj = Purchase.objects.create(
payment_header=payment_header_obj, **validated_data)
return purchase_obj
class PurchaseCancellationRequestSerializer(serializers.ModelSerializer):
class Meta:
model = PurchaseCancellationRequest
fields = ['purchase']
models.py
class PurchaseHeader(SoftDeleteModel):
name = models.CharField(max_length=50)
city = models.ManyToManyField(City, through='purchases.ProviderCity')
created_at = models.DateTimeField(default=timezone.now(), editable=False)
modified_at = models.DateTimeField(default=timezone.now())
class ProviderCity(SoftDeleteModel):
city = models.ForeignKey(City, on_delete=models.PROTECT)
purchase_header = models.ForeignKey(PurchaseHeader,
on_delete=models.PROTECT)
class Meta:
unique_together = ('city', 'purchase_header')
Thank for all friends!!

Drf throttling restart when POST

I created some app and want to set up different throttling for GET/POST,PUT,PATCH. When I make a GET request, it works fine. But when I perfom POST/PUT/PATCH it looks like cache is restarted. I want to create also extra headers so that's why I think this is actually the problem.
Throttling.py
class SetHeaders:
def throttle_success(self):
self.history.insert(0, self.now)
self.cache.set(self.key, self.history, self.duration)
print(self.key, self.history, self.duration)
print(f"REMAIN TIME {self.duration - (self.now - self.history[-1])}")
print(f'LIMIT {self.get_rate()}')
print(f'REMAIN RATE {self.num_requests - len(self.history) + 1}')
return True
class UserPostRateThrottle(SetHeaders, throttling.UserRateThrottle):
scope = "user_post"
def allow_request(self, request, view):
if request.method == "GET":
return True
return super().allow_request(request, view)
class UserGetRateThrottle(SetHeaders, throttling.UserRateThrottle):
scope = "user_get"
def allow_request(self, request, view):
if request.method in ("POST", "PUT", "PATCH"):
return True
return super().allow_request(request, view)
views.py
class TruckViewSet(viewsets.ModelViewSet):
queryset = Truck.confirmed.all()
serializer_class = TruckSerializer
filterset_class = TruckFilter
permission_classes = (
permissions.DjangoModelPermissions,
IsOwnerOrReadOnly,
)
throttle_classes = (UserGetRateThrottle, UserPostRateThrottle)
def _get_images(self, request):
for img in request.data.getlist("image"):
image_serializer = TruckImageSerializer(data={"image": img})
image_serializer.is_valid(raise_exception=True)
def create(self, request, *args, **kwargs):
if request.data.get("image"):
self._get_images(request)
return super(TruckViewSet, self).create(request, *args, **kwargs)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
def update(self, request, *args, **kwargs):
if request.data.get("image"):
self._get_images(request)
return super(TruckViewSet, self).update(request, *args, **kwargs)
serializers.py
class TruckSerializer(serializers.ModelSerializer):
location = LocationSerializer(
read_only=True,
)
owner = serializers.PrimaryKeyRelatedField(
read_only=True,
)
name = serializers.CharField(
max_length=50,
validators=[
validators.UniqueValidator(queryset=Truck.confirmed.all())
],
)
images = serializers.SerializerMethodField()
payment_methods = serializers.SerializerMethodField()
class Meta:
model = Truck
fields = (
"id",
"owner",
"name",
"phone",
"email",
"facebook",
"instagram",
"page_url",
"description",
"city",
"payment_methods",
"images",
"updated",
"location",
)
def _get_payments(self, data):
new_payments = []
payments = data.get("payment_methods")
for payment in payments.split(", "):
try:
filtered_payment = PaymentMethod.objects.get(
payment_name__iexact=payment
).id
except PaymentMethod.DoesNotExist:
raise serializers.ValidationError(
"Given payment method does not match"
)
new_payments.append(filtered_payment)
return new_payments
def create(self, validated_data):
data = self.context.get("view").request.data
new_payments = data.get("payment_methods", {})
if new_payments:
new_payments = self._get_payments(data)
truck = Truck.objects.create(**validated_data)
if data.get("image"):
for image_data in data.getlist("image"):
TruckImage.objects.create(truck=truck, image=image_data)
truck.payment_methods.add(*new_payments)
return truck
def update(self, instance, validated_data):
data = self.context.get("view").request.data
method = self.context.get("view").request.method
new_payments = data.get("payment_methods", {})
if new_payments:
new_payments = self._get_payments(data)
if data.get("image"):
images = instance.images.all()
if images.exists():
instance.images.all().delete()
for image_data in data.getlist("image"):
TruckImage.objects.create(truck=instance, image=image_data)
if method == "PUT" or method == "PATCH" and new_payments:
instance.payment_methods.clear()
instance.payment_methods.add(*new_payments)
return super(TruckSerializer, self).update(instance, validated_data)
def get_images(self, obj):
images = obj.images.all()
return [img.image.url for img in images]
def get_payment_methods(self, obj):
return obj.payment_methods.values_list("payment_name", flat=True)
settings.py
REST_FRAMEWORK = {
"DEFAULT_THROTTLE_CLASSES": [
'rest_framework.throttling.ScopedRateThrottle',
# 'rest_framework.throttling.UserRateThrottle'
],
"DEFAULT_THROTTLE_RATES": {
"user_get": "6/day",
"user_post": "4/day",
# 'user': '5/day'
},
"DEFAULT_PAGINATION_CLASS": "rest_framework.pagination.LimitOffsetPagination",
"PAGE_SIZE": 10,
"DEFAULT_FILTER_BACKENDS": [
"django_filters.rest_framework.DjangoFilterBackend"
],
"DEFAULT_VERSIONING_CLASS": "rest_framework.versioning.NamespaceVersioning",
}
So when GET requested is performed I get:
>>>REMAIN TIME 86399.02145123482
>>>LIMIT 6/day
>>>REMAIN RATE 3
and so on...
But in case of other request i get the same info all the time
>>>REMAIN TIME 86400.0
>>>LIMIT 4/day
>>>REMAIN RATE 4
What i've tried?
I've tried to change to simple UserRateThrottle, but nothing changed. So I think custom throttle is made correctly. Also I was changing between default Django cache/Redis server/Dummy cache and still not working as desired.
Thanks in advance!

Django request.user returns 'NoneType'

I am setting up a djangos channel and I am receiving the following error when I visit Threadview at the url below. It seems that it can't query the user? The user is "dominic" and I am signed in, but the view doesn't seem to be able to request.user.. See error message referencing line 99 below.
http://127.0.0.1:8000/portal/messages/dominic/
Error:
Exception Type: TypeError
Exception Value:
'NoneType' object is not iterable
Exception Location: /home/dominic/Desktop/Projects/robobud/web/robobud/portal/views.py in get_object, line 99
Python Executable: /home/dominic/Desktop/Projects/robobud/web/env/bin/python3
Line 99 from views.py:
def get_object(self):
...
obj, created = Thread.objects.get_or_new(self.request.user, other_username) #Line99
Urls.py:
#channels
path("messages/", InboxView.as_view()),
#url(r"^messages/(?P<username>[\w.#+-]+)", ThreadView.as_view(), name='thread'),
path('messages/<username>/', ThreadView.as_view(), name='thread'),
Views.py:
class InboxView(LoginRequiredMixin, ListView):
template_name = 'portal/inbox.html'
def get_queryset(self):
return Thread.objects.by_user(self.request.user)
class ThreadView(LoginRequiredMixin, FormMixin, DetailView):
template_name = 'portal/thread.html'
form_class = ComposeForm
success_url = './'
def get_queryset(self):
return Thread.objects.by_user(self.request.user)
def get_object(self):
other_username = self.kwargs.get("username")
obj, created = Thread.objects.get_or_new(self.request.user, other_username)
if obj == None:
raise Http404
return obj
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['form'] = self.get_form()
return context
def post(self, request, *args, **kwargs):
if not request.user.is_authenticated:
return HttpResponseForbidden()
self.object = self.get_object()
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
def form_valid(self, form):
thread = self.get_object()
user = self.request.user
message = form.cleaned_data.get("message")
ChatMessage.objects.create(user=user, thread=thread, message=message)
return super().form_valid(form)
models.py
class ThreadManager(models.Manager):
def by_user(self, user):
qlookup = Q(first=user) | Q(second=user)
qlookup2 = Q(first=user) & Q(second=user)
qs = self.get_queryset().filter(qlookup).exclude(qlookup2).distinct()
return qs
def get_or_new(self, user, other_username): # get_or_create
username = user.username
if username == other_username:
return None
qlookup1 = Q(first__username=username) & Q(second__username=other_username)
qlookup2 = Q(first__username=other_username) & Q(second__username=username)
qs = self.get_queryset().filter(qlookup1 | qlookup2).distinct()
if qs.count() == 1:
return qs.first(), False
elif qs.count() > 1:
return qs.order_by('timestamp').first(), False
else:
Klass = user.__class__
user2 = Klass.objects.get(username=other_username)
if user != user2:
obj = self.model(
first=user,
second=user2
)
obj.save()
return obj, True
return None, False
class Thread(models.Model):
first = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_first')
second = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='chat_thread_second')
updated = models.DateTimeField(auto_now=True)
timestamp = models.DateTimeField(auto_now_add=True)
objects = ThreadManager()
#property
def room_group_name(self):
return 'chat_{self.id}' #Removed f
def broadcast(self, msg=None):
if msg is not None:
broadcast_msg_to_chat(msg, group_name=self.room_group_name, user='admin')
return True
return False
class ChatMessage(models.Model):
thread = models.ForeignKey(Thread, null=True, blank=True, on_delete=models.SET_NULL)
user = models.ForeignKey(settings.AUTH_USER_MODEL, verbose_name='sender', on_delete=models.CASCADE)
message = models.TextField()
timestamp = models.DateTimeField(auto_now_add=True)