Is this possible? Using signals to set a global variable - python

I have made this function that runs every time a user logs in. I want to get the branch from 'user' but every time the session is set it's only available to the function even after setting it to BRANCH_ID in the settings file. any help? plus I don't want to do anything in view function with the request as it's not accessible from models
EDIT
I have added all the models
def perform_some_action_on_login(sender, request, user, **kwargs):
"""
A signal receiver which performs some actions for
the user logging in.
"""
request.session[settings.BRANCH_ID] = user.profile.branch_id
branch = request.session.get(settings.BRANCH_ID)
print(branch)
user_logged_in.connect(perform_some_action_on_login)
class WaybillTabularInlineAdmin(admin.TabularInline):
model = WaybillItem
extra = 0
# form = WaybillItemForm
fk_name = 'waybill'
autocomplete_fields = ('product',)
class WaybillAdmin(admin.ModelAdmin):
list_display = (
'from_branch',
'to_branch',
'updated_by',
)
list_filters = (
'from_branch',
'to_branch',
'product',
)
inlines = [WaybillTabularInlineAdmin]
readonly_fields = ("updated_by",)
what I was trying to do is products by the branch
class Waybill(models.Model):
from_branch = models.ForeignKey(
Branch,
default=1,
on_delete=models.CASCADE, related_name='from_branch')
to_branch = models.ForeignKey(
Branch, on_delete=models.CASCADE, related_name='to_branch')
comments = models.CharField(max_length=1024, blank=True)
created_date = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(
User, on_delete=models.CASCADE,
blank=True, null=True,
related_name='waybill_created')
updated = models.BooleanField(default=False)
updated_by = models.ForeignKey(
User, on_delete=models.CASCADE, related_name='waybill_user')
def __str__(self):
return 'from {} to {}'.format(
self.from_branch.branch_name,
self.to_branch.branch_name,
)
class WaybillItem(models.Model):
waybill = models.ForeignKey(Waybill, on_delete=models.CASCADE)
product = models.ForeignKey(ProductDetail, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField()
def __str__(self):
return 'from {} to {}'.format(
self.waybill.from_branch,
self.waybill.to_branch
)
class Product(models.Model):
item = models.ForeignKey(
Item, on_delete=models.CASCADE, related_name="product")
branch = models.ForeignKey(
Branch, default=1, on_delete=models.CASCADE)
in_stock = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
updated_date = models.DateTimeField(auto_now=True)
objects = ProductManager()
class Meta:
verbose_name = "Inventory"
verbose_name_plural = "Inventories"
ordering = ("-created_date",)
constraints = [
models.UniqueConstraint(
fields=['item', 'branch'], name='unique product'),
]
def __str__(self):
return self.item.item_description
class ProductDetail(models.Model):
ITEM_CONDITION_CHOICES = (
("NEW", "New"),
("BROKEN", "Broken"),
("FAIRLY USED", "Fairly Used"),
)
condition = models.CharField(max_length=12, choices=ITEM_CONDITION_CHOICES,
default=ITEM_CONDITION_CHOICES[0][0])
product = models.ForeignKey(Product, on_delete=models.CASCADE)
short_description = models.CharField(max_length=255, blank=True)
color = models.CharField(max_length=15, blank=True)
bought_price = models.PositiveIntegerField(default=0.00)
sales_price = models.PositiveIntegerField(default=0.00)
retail_price = models.PositiveIntegerField(default=0.00)
item_code = models.CharField(max_length=15, default=0)
item_model_number = models.CharField(max_length=20, default=0)
quantity = models.PositiveIntegerField(default=0)
manufacturer_website = models.CharField(max_length=255, blank=True)
generated_url = models.CharField(max_length=255, blank=True)
created_date = models.DateTimeField(default=timezone.now)
updated_date = models.DateTimeField(auto_now=True)
# objects = ProductDetailManager()

Related

How to filter Many to Many field in django admin page using a foreign key value?

I am trying to filter my many to many variation fields with respect to the product. means, I only want the variations related to the current product to show in the admin page. now its showing all the variations available for every product.
I added formfield_for_manytomany() function to my admin.py but how can I get the current product(id) in the cart or order to filter the variations?
most of the questions in stack overflow Is based on the current user, which is easy to get? but how should I get the specific product(id) that is opened in the admin panel.
admin.py
from django.contrib import admin
from .models import *
from products.models import Variation
class CartAdmin(admin.ModelAdmin):
list_display = ('cart_id', 'date_created')
class CartItemAdmin(admin.ModelAdmin):
list_display = ('user','cart', 'product', 'quantity','is_active')
def formfield_for_manytomany(self, db_field, request, **kwargs):
if db_field.name == "variation":
product = Products.objects.get(id='??') # how I get the current product in the cart or order
kwargs["queryset"] = Variation.objects.filter(product=product.id)
return super().formfield_for_manytomany(db_field, request, **kwargs)
admin.site.register(Cart, CartAdmin)
admin.site.register(CartItem, CartItemAdmin)
CartItem Model
class CartItem(models.Model):
user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, null=True)
cart = models.ForeignKey(Cart, on_delete=models.CASCADE, null=True)
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation = models.ManyToManyField(Variation, blank=True)
quantity = models.IntegerField()
is_active = models.BooleanField(default=True)
created_date = models.DateTimeField(auto_now_add=True)
def item_total(self):
return self.product.price * self.quantity
def __str__(self):
return self.product.name
Product and Variation Model
class Products(models.Model):
name = models.CharField(max_length=50, unique=True)
slug = AutoSlugField(populate_from='name', max_length=100, unique=True)
isbn = models.CharField(max_length=20, unique=True, blank=True, null=True)
sub_category = models.ForeignKey(SubCategory, on_delete=models.CASCADE)
language = models.ForeignKey(Language, on_delete=models.SET_NULL, null=True)
author = models.CharField(max_length=100)
Publisher = models.CharField(max_length=100, blank=True, default=None)
release_date = models.DateField(blank=True, null=True, default=None)
price = models.IntegerField(default=None)
stock = models.IntegerField(default=None)
is_available = models.BooleanField(default=True)
cover_image = models.ImageField(upload_to='images/products')
image1 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image2 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
image3 = models.ImageField(upload_to='images/products', blank=True, default=None, null=True)
description = models.TextField(max_length=2000, blank=True, default=None)
create_date = models.DateTimeField(auto_now_add=True)
modified_date = models.DateTimeField(auto_now=True)
number_of_pages = models.IntegerField(blank=True, null=True)
weight = models.IntegerField(blank=True, null=True)
width = models.IntegerField(blank=True, null=True)
height = models.IntegerField(blank=True, null=True)
spine_width = models.IntegerField(blank=True, null=True)
class Meta:
verbose_name = 'Product'
verbose_name_plural = 'Products'
def get_url(self):
return reverse('product-view', args=[self.slug])
def __str__(self):
return self.name
class Variation(models.Model):
product = models.ForeignKey(Products, on_delete=models.CASCADE)
variation_category = models.CharField(max_length=100, choices=variation_category_choice)
variation_value = models.CharField(max_length=100, choices=variation_value_choice)
is_available = models.BooleanField(default=True)
date_added = models.DateTimeField(auto_now_add=True)
objects = VariationManager()
def __str__(self):
return self.variation_value

How can I split orders by attributes in my API

I have a method that creates orders from the user's cart. For the courier to take an order from different restaurants, the order is divided into several. But at the moment I'm splitting the order just by the dish in the cart. How to make an order split by restaurants? that is, if a user orders 5 dishes from two different restaurants, then 2 orders were formed.
views.py
#action(methods=['PUT'], detail=False, url_path='current_customer_cart/add_to_order')
def add_cart_to_order(self, *args, **kwargs):
cart = Cart.objects.get(owner=self.request.user.customer)
cart_meals = CartMeal.objects.filter(cart=cart)
data = self.request.data
for cart_meal in cart_meals:
order = Order.objects.create(customer=self.request.user.customer,
cart_meal=cart_meal,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.save()
return response.Response({"detail": "Order is created", "added": True})
models.py
class Order(models.Model):
"""User's order"""
customer = models.ForeignKey(Customer, on_delete=models.CASCADE, related_name='related_orders')
first_name = models.CharField(max_length=255)
last_name = models.CharField(max_length=255)
phone = models.CharField(max_length=20)
cart_meal = models.ForeignKey(CartMeal, on_delete=models.CASCADE, null=True, blank=True)
restaurant_address = models.CharField(max_length=1024, null=True)
address = models.CharField(max_length=1024)
status = models.CharField(max_length=100, choices=STATUS_CHOICES, default=STATUS_NEW)
created_at = models.DateTimeField(auto_now=True)
delivered_at = models.DateTimeField(null=True, blank=True)
courier = models.OneToOneField('Courier', on_delete=models.SET_NULL, null=True, blank=True)
class CartMeal(models.Model):
"""Cart Meal"""
user = models.ForeignKey('Customer', on_delete=models.CASCADE)
cart = models.ForeignKey('Cart', verbose_name='Cart', on_delete=models.CASCADE, related_name='related_meals')
meal = models.ForeignKey(Meal, verbose_name='Meal', on_delete=models.CASCADE)
qty = models.IntegerField(default=1)
final_price = models.DecimalField(max_digits=9, decimal_places=2)
class Meal(models.Model):
"""Meal"""
title = models.CharField(max_length=255)
description = models.TextField(default='The description will be later')
price = models.DecimalField(max_digits=9, decimal_places=2)
discount = models.IntegerField(default=0)
restaurant = models.ForeignKey(Restaurant, on_delete=models.CASCADE, null=True)
slug = models.SlugField(unique=True)
class Restaurant(models.Model):
"""Restaurant"""
name = models.CharField(max_length=255)
slug = models.SlugField(unique=True)
address = models.CharField(max_length=1024)
owner = models.ForeignKey('Restaurateur', on_delete=models.CASCADE, null=True)
meals = models.ManyToManyField('Meal', related_name='related_restaurant', blank=True)
How can I do this, please help me
You can group your meals with respect to resturants.
import itertools
from core.models import CartMeal, Order
for restaurant, cart_meals in itertools.groupby(CartMeal.objects.order_by('meal__restaurant'), lambda s: s.meal.restaurant):
order = Order.objects.create(
customer=self.request.user.customer,
first_name=data['first_name'],
last_name=data['last_name'],
phone=data['phone'],
address=data.get('address', self.request.user.customer.home_address),
restaurant_address=cart_meal.meal.restaurant.address,
)
order.cart_meal.set([cart_meal for cart_meal in cart_meals])
Ref: The answer is formulated by taking help from following answer.
https://stackoverflow.com/a/57897654/14005534

How can i update a specific field using foreign key relationship

I want to update a field which is called level. My relation is like this. i am using django User model. Which is extended to Extended user like this below:-
class ExtendedUser(models.Model):
levels_fields = (
("NEW SELLER", "NEW SELLER"),
("LEVEL1", "LEVEL1"),
("LEVEL 2", "LEVEL 2"),
("LEVEL 3", "LEVEL 3")
)
user = models.OneToOneField(User, on_delete=models.CASCADE)
email = models.EmailField(null=True, unique=True)
contact_no = models.CharField(max_length=15, null=True)
profile_picture = models.ImageField(upload_to="images/", null=True)
country = models.ForeignKey(Country, on_delete=models.CASCADE, null=True)
city = models.ForeignKey(City, on_delete=models.CASCADE, null=True)
level = models.CharField(max_length = 120, null=True, blank=True, choices=levels_fields, default="NEW SELLER")
I have a field call "Level" which is full of choices. Now i have a model named Checkout
This is the checkout model :-
class Checkout(models.Model):
ORDER_CHOICES = (
("ACTIVE", "ACTIVE"),
("LATE", "LATE"),
("DELIVERED", "DELIVERED"),
("CANCELLED", "CANCELLED"),
)
user = models.ForeignKey(User, on_delete=models.CASCADE)
seller = models.ForeignKey(
User, on_delete=models.CASCADE, null=True, related_name='seller')
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now_add=True)
first_name = models.CharField(max_length=120)
last_name = models.CharField(max_length=120)
package = models.ForeignKey(OfferManager, on_delete=models.CASCADE)
quantity = models.PositiveIntegerField(default=0)
price = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
total = models.DecimalField(decimal_places=2, max_digits=10, default=0.00)
grand_total = models.DecimalField(
decimal_places=2, max_digits=10, default=0.00, null=True)
paid = models.BooleanField(default=False)
due_date = models.DateField(null=True)
order_status = models.CharField(max_length=200, choices=ORDER_CHOICES, default="ACTIVE")
is_complete = models.BooleanField(default=False, null=True)
I have another model which is called SellerSubmit and the checkout is the foreign key here. Here is the model :-
class SellerSubmit(models.Model):
checkout = models.ForeignKey(Checkout, on_delete=models.CASCADE, related_name="checkout")
file_field = models.FileField(upload_to="files/", null=True)
submit_date = models.DateField(auto_now_add=True, null=True)
def __str__(self):
return str(self.id)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
Now when a seller post in the SUbmitModel it will update the level to LEVEL1. How can do it,
This is what i tried :-
def sellerSubmitView(request, pk):
form = SellerSubmitForm()
if request.method == "POST":
file_field = request.FILES.get("file_field")
try:
checkout = Checkout.objects.get(id=pk)
# print(file_field)
except:
return redirect("manage-order")
else:
SellerSubmit.objects.create(checkout=checkout, file_field=file_field)
checkout.order_status ="DELIVERED"
chk = checkout.is_complete = True
l = Checkout.objects.filter(is_complete = True).filter(seller=request.user).count()
print("Count:" + str(l))
if l > 5:
out = checkout.seller.extendeduser.level = "LEVEL1"
print(out)
checkout.save()
print(chk)
checkout.save()
return redirect("manage-order")
args = {
"form": form,
"checkout_id": pk,
}
return render(request, "wasekPart/sellerSubmit.html", args)
checkout.seller.extendeduser.level = "LEVEL1"
checkout.seller.extendeduser.save()
This should solve your problem
out = checkout.seller.extendeduser.level = "LEVEL1"
print(out)
checkout.seller.extendeduser.save()
checkout.save()
It's my bad that didn't notice ExtendedUser is not extended from User.
Please let me know if it's worked or not

While defining method for autosaving in CreateView for ManyToMany field Error shows

I have three Models, in third models Foreign Key and ManyToMany fields are linked, which are:
Personal_info Models.py
class Personal_info(models.Model):
gen_choices = (
("पुरुष", "पुरूष"),
("महिला", "महिला"),
("तेस्रो", "तेस्रो"),
)
pinfo_id = models.AutoField(primary_key=True)
userid = models.OneToOneField(User, on_delete=models.CASCADE)
nfullname = models.CharField(validators=[max_len_check], max_length=128)
efullname = models.CharField(validators=[max_len_check], max_length=128)
dob_ad = models.DateField()
dob_bs = models.DateField()
gender = models.CharField(max_length=6, choices=gen_choices)
citizen_no = models.CharField(max_length=56)
cissue_dist = models.ForeignKey(District, on_delete=models.CASCADE)
cissue_date = models.DateField()
language = models.CharField(max_length=56)
p_district = models.CharField(max_length=56)
p_vdc = models.CharField(max_length=56)
p_ward = models.CharField(max_length=2)
p_city = models.CharField(max_length=56)
t_district = models.CharField(max_length=56)
t_vdc = models.CharField(max_length=59)
t_ward = models.CharField(max_length=2)
t_city = models.CharField(max_length=56)
telephone = models.BigIntegerField(null=True, blank=True)
mobile = models.BigIntegerField()
mother_name = models.CharField(validators=[max_len_check], max_length=128)
mother_cit = models.CharField(max_length=10, null=True)
father_name = models.CharField(validators=[max_len_check], max_length=128)
father_cit = models.CharField(max_length=10, null=True)
gfather_name = models.CharField(validators=[max_len_check], max_length=128)
gfather_cit = models.CharField(max_length=10, null=True)
spose_name = models.CharField(validators=[max_len_check], max_length=128, null=True)
spose_cit = models.CharField(max_length=10, null=True, blank=True)
image = models.FileField(upload_to="photos/", null=True, blank=True)
cit_image = models.FileField(upload_to="citizens/")
inclu_image = models.FileField(upload_to="inclusions/", null=True)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager
def __str__(self):
return str(self.efullname)
Educational Models.py
class Education(models.Model):
edu_id = models.AutoField(primary_key=True)
userid = models.ForeignKey(User, on_delete=models.CASCADE)
institute = models.CharField(max_length=255, validators=[max_len_check])
board = models.CharField(max_length=128, validators=[max_len_check1])
pexam = models.CharField(max_length=16, choices=exam_choices)
faculty = models.CharField(max_length=16, choices=fac_choices)
division = models.CharField(max_length=16, validators=[max_len_check2])
tmarks = models.IntegerField()
percent = models.FloatField(null=True, blank=True)
mainsub = models.CharField(max_length=16, validators=[max_len_check2])
image = models.FileField(upload_to="educations/", null=True, blank=True)
active = models.BooleanField(default=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager
def __str__(self):
return str(self.userid)
V_applied models.py
class V_applied(models.Model):
appNo = models.IntegerField(null=True, blank=True, default=add_one)
p_srlno = models.IntegerField(blank=True, null=0, default=0)
userid = models.ForeignKey(User, on_delete=models.CASCADE)
post = models.ForeignKey(Vacancy,on_delete=models.CASCADE)
inclusive = models.ManyToManyField(Inclusive)
bank = models.CharField(max_length=128)
v_no = models.CharField(max_length=32, validators=[max_len_check1])
dep_date = models.DateField()
ser_fee = models.IntegerField()
image = models.FileField(upload_to="vouchers/")
personal_info = models.ForeignKey(Personal_info, on_delete=models.CASCADE, blank=True)
education = models.ManyToManyField(Education, blank=True, default=0)
active = models.BooleanField(default=True)
status = models.CharField(max_length=10, validators=[max_len_check], default="Pending")
remarks = models.CharField(max_length=56, validators=[max_len_check1], default="Pending")
comment = models.CharField(max_length=128, validators=[max_len_check2], blank=True, null=True)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
objects = models.Manager
#property
def per_info(self):
return (self.personal_info.efullname, self.personal_info.gender, )
'''
def __str__(self):
return str(self.userid) + ':' + str(self.post)
Here I want to make auto save method in CreateView for ForeignKey & ManyToMany fields of V_applied models, for this I tried views.py as below:
#method_decorator(login_required(login_url='login'), name='dispatch')
class v_appliedadd(CreateView):
form_class = V_appliedForm
template_name = 'v_applied/v_applied_form.html'
success_url = '/v_applied/vapp_details/'
def form_valid(self, form):
form.instance.userid = self.request.user
form.instance.personal_info = Personal_info.objects.get(userid=self.request.user)
educationall = Education.objects.filter(userid=self.request.user)
for edu in educationall:
form.instance.education.add(edu)
return super().form_valid(form)
While saving data Error display like this:
ValueError at /v_applied/v_appliedadd/
"<V_applied: testuser>" needs to have a value for field "id" before this many-to-many relationship can be used.
Request Method: POST
Request URL: http://localhost:8000/v_applied/v_appliedadd/
Django Version: 3.0.8
Exception Type: ValueError
Exception Value:
"<V_applied: testuser>" needs to have a value for field "id" before this many-to-many relationship can be used.
Exception Location: C:\Users\User\AppData\Local\Programs\Python\Python38\lib\site-packages\django\db\models\fields\related_descriptors.py in __init__, line 846
Python Executable: C:\Users\User\AppData\Local\Programs\Python\Python38\python.exe
Python Version: 3.8.1
Python Path:
['D:\\DjangoProject\\app_epf',
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\python38.zip',
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\DLLs',
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\lib',
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38',
'C:\\Users\\User\\AppData\\Roaming\\Python\\Python38\\site-packages',
'C:\\Users\\User\\AppData\\Local\\Programs\\Python\\Python38\\lib\\site-packages']
Server time: Mon, 14 Sep 2020 23:09:21 +0545
I am new in python-django, please help me how to solve it.
form.instance.userid = self.request.user
form.instance.personal_info = Personal_info.objects.get(userid=self.request.user)
instance_from = form.save()
educationall = Education.objects.filter(userid=self.request.user)
for edu in educationall:
instance_edu = Education.objects.get(pk=edu.pk)
instance_from.education.add(instance_edu)
instance_from.save()
return super().form_valid(form)

How can I create a model property based on specific model fields?

Let's say I have the following model:
class DriverReview(models.Model):
driver = models.ForeignKey(Driver, on_delete=models.CASCADE,)
driving_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
communication_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
professionalism_score = models.PositiveIntegerField(default=1, validators=[MinValueValidator(1), MaxValueValidator(5)])
review_text = models.TextField()
created = models.DateTimeField(auto_now_add=True)
created_by = models.ForeignKey(User, related_name="driver_review_created_by", on_delete=models.CASCADE, null=True, blank=True)
last_updated = models.DateTimeField(auto_now=True)
last_updated_by = models.ForeignKey(User, related_name="driver_review_last_updated_by", on_delete=models.CASCADE, null=True, blank=True)
is_deleted = models.BooleanField(default=False)
deleted = models.DateTimeField(null=True, blank=True)
deleted_by = models.ForeignKey(User, related_name="driver_review_deleted_by", on_delete=models.CASCADE, null=True, blank=True)
#property
def review_average_score(self):
review_average_score = round(np.mean([self.driving_score, self.communication_score, self.professionalism_score]), 2)
return review_average_score
I have created a property to get the review average score. The issue is that I don't want to hardcode the _score fields. Is there a way to filter the fields that contain _score and use them in the average ?
Yes, you can inspect the fields through the _meta, so:
#property
def review_average_score(self):
data = [
getattr(self, f.attname)
for f in self._meta.get_fields()
if '_score' in f.name
]
review_average_score = np.mean(data), 2)
return review_average_score

Categories

Resources