Request.user on Django Model forms - django

I have a ledger account table that consist of ledger accounts of all the companies. The user in logged into a specific company and hen he selects an account to use on a form only the accounts that company must be available for the user. for this purpose I use the request.user to determine the user. I however get an error "request does not exist". I understand why it is not available on the forms.py as there is no request executed. Is there a way that I can make request.user available of the form.
Models.py
class tledger_account(models.Model):
id = models.AutoField(primary_key=True)
description = models.CharField(max_length=30, unique=True)
gl_category = models.CharField(max_length=30, choices=category_choices, verbose_name='category', db_index=True)
note = models.CharField(max_length=25, blank=True, default=None)
active = models.BooleanField(default=True)
company = models.ForeignKey(tcompany, on_delete=models.PROTECT, db_index=True)
forms.py
class SelectAccountForm(forms.ModelForm):
date_from = forms.DateField(widget=forms.SelectDateWidget(years=year_range))
date_to = forms.DateField(widget=forms.SelectDateWidget(years=year_range))
select_account = forms.ModelChoiceField(queryset=tledger_account.objects.filter(
company = request.user.current_company))
class Meta:
model = ttemp_selection
fields = ['select_account', 'date_from', 'date_to']

When you use request.user you are using the fields of the user model so it is not necessary to have them in the form, for that you need to have a forensic relationship with the user model:
class tledger_account(models.Model):
id = models.AutoField(primary_key=True)
user = models.ForeignKey(User, on_delete=models.CASCADE)
description = models.CharField(max_length=30, unique=True)
gl_category = models.CharField(max_length=30, choices=category_choices, verbose_name='category', db_index=True)
note = models.CharField(max_length=25, blank=True, default=None)
active = models.BooleanField(default=True)
company = models.ForeignKey(tcompany, on_delete=models.PROTECT, db_index=True)
and the view:
def tledger_account_view(request):
template_name = 'your template'
user = request.user
tledger_account = tledger_account.objects.get(user=user)
return render(request, template_name, {
'tledger_account': tledger_account,
})
more info https://docs.djangoproject.com/en/3.1/topics/auth/default/

Related

Django: Assign Route to Order Based on User Input of Location

In my create order view, I am trying to automatically assign the respective route based on the location the user inputs. Basically, every location in the system has a FK to a route. There are many locations within a route. If you select a location to send products to, the route should automatically be tied to.
Currently I am able to see the route for an order in my order_list.html page, but when I view the order in the Django admin, the route is not assigned to the order but the location is.
I want it to work similarly to how you would assign the current logged in user to an order:
form.instance.user = request.user
I tried using:
form.instance.company = request.user.company
But I am getting an attribute error:
'WSGIRequest' object has no attribute 'location'
Here is my full order_create function:
orders/views.py:
#login_required(login_url='account_login')
def order_create(request):
"""
A function that takes the users cart with products, then converts the cart into an
OrderForm. Then saves the form/order to the database.
"""
cart = Cart(request)
if request.method == 'POST':
form = OrderCreateForm(request.POST)
if form.is_valid():
form.instance.user = request.user
form.instance.company = request.user.company
form.instance.route = request.location.route
order = form.save()
for item in cart:
OrderItem.objects.create(order=order,
product=item['product'],
price=item['price'],
quantity=item['quantity'])
# clear the cart
cart.clear()
return render(request,
'orders/order/created.html',
{'order': order,
})
else:
form = OrderCreateForm()
return render(request,
'orders/order/create.html',
{'cart': cart, 'form': form})
Here are the Location, Route and Order models:
orders/models.py:
class Route(models.Model):
name = models.CharField(max_length=50)
def __str__(self):
return self.name
class Locations(models.Model):
"""
A model to represent a location or locations a company has.
"""
name = models.CharField(max_length=100)
company = models.ForeignKey(Company, on_delete=models.CASCADE)
route = models.ForeignKey(Route, on_delete=models.DO_NOTHING)
store_number = models.CharField(max_length=15, blank=True, null=True)
address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, blank=True, null=True)
class Order(models.Model):
user = models.ForeignKey(User, on_delete=models.DO_NOTHING)
route = models.ForeignKey(Route, on_delete=models.DO_NOTHING, blank=True, null=True)
location = models.ForeignKey(Locations, on_delete=models.DO_NOTHING, blank=True, null=True)
company = models.ForeignKey(Company, on_delete=models.DO_NOTHING, blank=True, null=True)
delivery_date = models.DateField()
address = models.ForeignKey(Address, on_delete=models.DO_NOTHING, blank=True, null=True)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
paid = models.BooleanField(default=False)
delivered = models.BooleanField(default=False)
and then finally the company and user model in my accounts app that are used as foreign keys in the orders app.
accounts/models.py:
class Company(models.Model):
"""
A model to represent companies that can operate within the system, which multiple users are apart of.
"""
name = models.CharField(max_length=100)
address = models.CharField(max_length=100)
city = models.CharField(max_length=25)
state = USStateField()
zip = models.CharField(max_length=5)
admin = models.ForeignKey("accounts.User", on_delete=models.DO_NOTHING, related_name="company_admin", blank=True, null=True)
class User(AbstractBaseUser, PermissionsMixin):
"""
A model to represent a User of the system.
"""
ROLE_CHOICES = (
('ADMIN', "Admin"),
('MANAGER', "Manager"),
('DRIVER', "Driver"),
('PRODUCTION', "Production")
)
email = models.EmailField(max_length=254, unique=True)
phone = models.CharField(max_length=15, help_text="(123)-123-1234", blank=True, null=True)
first_name = models.CharField(max_length=254, null=True, blank=True)
last_name = models.CharField(max_length=254, null=True, blank=True)
company = models.ForeignKey(Company, on_delete=models.CASCADE, blank=True, null=True)
role = models.CharField(max_length=10, choices=ROLE_CHOICES, default=None, blank=True, null=True)
is_employee = models.BooleanField(default=False, blank=True, null=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)

Django api filter search on other models without a direct foreign field

I have two models named user, skill, and profile.
I am trying to implement a search filter on the user's skills. which means when someone searches for something that is contained in the skills of a user, that user would appear in the search result.
Note: when the user signs up, a signal is used to auto-create a profile for that user. The user simply updates their profile to add skills and other things.
user model
class User(AbstractBaseUser, PermissionsMixin):
email = models.EmailField(max_length=254, unique=True)
name = models.CharField(max_length=250)
picture = models.TextField(null=True, blank=True)
is_staff = models.BooleanField(default=False)
is_superuser = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
last_login = models.DateTimeField(null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True)
slug = models.SlugField(max_length=255, unique=True, blank=True)
profile model
class Profile(models.Model):
user = models.OneToOneField(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='profiles')
date_of_birth = models.DateField(blank=True, verbose_name="DOB", null=True)
bio = models.TextField(max_length=500, blank=True, null=True)
skills = models.ManyToManyField(Skill, related_name='skills')
sex = models.CharField(max_length=6, choices=SEX, blank=True, null=True)
type_of_body = models.CharField(max_length=8, choices=BODYTYPE, blank=True, null=True)
feet = models.PositiveIntegerField(blank=True, null=True)
inches = models.PositiveIntegerField(blank=True, null=True)
lives_in = models.CharField(max_length=50, blank=True, null=True)
updated_on = models.DateTimeField(auto_now=True)
skill model
class Skill(models.Model):
name = models.CharField(max_length=60)
subcategory = models.CharField(max_length=60, blank=True, null=True)
description = models.TextField(null=True, blank=True)
created_on = models.DateTimeField(auto_now=True)
updated_on = models.DateTimeField(auto_now_add=True)
updated_by = models.ForeignKey(settings.AUTH_USER_MODEL, null=True, on_delete=models.DO_NOTHING)
the user view, where the search is done from
class ListUsersView(generics.ListAPIView):
'''
Gets all the users in the database
'''
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
filter_backends = [filtr.SearchFilter]
search_fields = ['email', 'name']
currently, the solution above works, but when I add to the search_fields other fields like profiles__skills in order to include results where there is a skill like that created by ay user, the code doesn't work.
Please, how can I get the skills in the profile of a user to show in the search?
The SearchFilter class supports simple single query parameter based searching. The search_fields attribute should be a list of names of text type fields on the model.
profiles__skills is not a field. You should use a text field eg. profiles__skills__name
class ListUsersView(generics.ListAPIView):
'''
Gets all the users in the database
'''
queryset = User.objects.all()
serializer_class = UserSerializer
permission_classes = [AllowAny]
filter_backends = [filtr.SearchFilter]
search_fields = ['email', 'name', 'profiles__skills__name']

How to save multiple object in a single POST request

I am new to DRF
I am saving a user details and his pets details .
Here is the model
class Users(models.Model):
id = models.AutoField(primary_key=True)
first_name = models.CharField(max_length=255, blank=True)
last_name = models.CharField(max_length=255, blank=True)
job = models.CharField(max_length=255, blank=True)
age = models.CharField(max_length=255, blank=True)
class PetDetails(models.Model):
user = models.ForeignKey(
Users, on_delete=models.CASCADE, blank=True, null=True)
pet_name = models.CharField(max_length=255, blank=True)
pet_color = models.CharField(max_length=255, blank=True)
pet_category = models.CharField(max_length=255, blank=True)
In this I need to save both user and his pets in a single Post request.
So I created a serializer like this
class UserCreateSerializer(ModelSerializer):
pet = PetDetailCreateSerializer(many=True)
class Meta:
model = Users
fields = ['first_name','last_name','job','age', 'pet']
def create(self, validated_data):
pets_data = validated_data.pop('pet')
user_obj = Users.objects.create(**validated_data)
for pet in pets_data:
PetDetails.objects.create(user=user_obj, **pet)
return user_obj
The issue I am facing is if a single person can have multiple pets.
For Example John is a user and he having two Pets.
So in this cases two users object will creating .How to resolve this
OR is there any other methods for handling this
My views is
class UserCreateView (CreateAPIView):
serializer_class = UserCreateSerializer
One way is to check if user already exists by using get_or_create:
user_obj = Users.objects.get_or_create(**audit_data)
But better way, I think, is to create user with multiple pets instead:
class UserCreateSerializer(ModelSerializer):
petdetails_set = PetDetailCreateSerializer(many=True)
class Meta:
model = Users
fields = ['first_name','last_name','job','age', 'petdetails_set']
def create(self, validated_data):
pets_data = validated_data.pop('pet')
user_obj = User.objects.create(**validated_data)
for pet in pets_data:
PetDetails.objects.create(user=user_obj, **pet)
return user_obj
Also, I advice to use separate endpoints/serializers for user creation.

Multiple type user's authority is messy when change user profile with UpdateView - Django

I have three user types in user model(create, query and common), multiple type user's authority is messy when I am changing user profile with UpdateView, for example, a user who is admin, when admin clicked a user who is common user, then that user in page is in common user's authority, my UpdateView is as below:
class UserUpdateView(UpdateView):
model = User
form_class = UserForm
context_object_name = 'user'
template_name = 'general/teachers/user_change_form.html'
def get_object(self):
return get_object_or_404(User, pk=self.kwargs['pk'])
models of user:
class User(AbstractUser):
name = models.CharField(max_length=100, verbose_name="姓名", default="", blank=True)
gender = models.CharField(
max_length=7,choices=(("male","男"),("female","女")),
default="female", verbose_name="性别",
)
department = models.ForeignKey(
Department,
on_delete=models.CASCADE, null=True, blank=True, verbose_name="所属部门",
)
job_title = models.CharField(max_length=100, verbose_name="职位", default="", blank=True)
mobile = models.CharField(max_length=11, verbose_name="手机号", default="", blank=True)
email = models.EmailField(max_length=50, verbose_name="邮箱", default="", blank=True)
is_employee = models.BooleanField(default=True, verbose_name='是否是普通用户')
is_teacher = models.BooleanField(default=False, verbose_name='是否是查询用户')
is_supervisor = models.BooleanField(default=False, verbose_name='是否是评测人')
add_time = models.DateTimeField(auto_now=True, verbose_name="添加时间")
forms of user:
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = ('username', 'department', 'gender', 'job_title', 'email', 'mobile')

How to join user profile to user topics in Django?

In Django 1.7, I am trying to make a user panel in which userprofile info (like avatar, country, etc.) are to be displayed along with their topics. Here is the view:
def topic(request, topic_id):
"""Listing of posts in a thread."""
posts = Post.objects.select_related('creator') \
.filter(topic=topic_id).order_by("created")
posts = mk_paginator(request, posts, DJANGO_SIMPLE_FORUM_REPLIES_PER_PAGE)
topic = Topic.objects.get(pk=topic_id)
topic.visits += 1
topic.save()
return render_to_response("myforum/topic.html", add_csrf(request, posts=posts, pk=topic_id,
topic=topic), context_instance=RequestContext(request))
The Topic model is:
class Topic(models.Model):
title = models.CharField(max_length=100)
description = models.TextField(max_length=10000, null=True)
forum = models.ForeignKey(Forum)
created = models.DateTimeField()
creator = models.ForeignKey(User, blank=True, null=True)
visits = models.IntegerField(default = 0)
And the UserProfile model:
class UserProfile(models.Model):
username = models.OneToOneField(User)
name = models.CharField(max_length=30, blank=True)
city = models.CharField(max_length=30, blank=True)
country = models.CharField(
max_length=20, choices= COUTNRY_CHOICES, blank=True)
avatar = ImageWithThumbsField(), upload_to='images', sizes=((32,32),(150,150),(200,200)), blank=True)
created_at = models.DateTimeField(auto_now_add=True, blank=True)
updated_at = models.DateTimeField(auto_now=True, blank=True)
However, when in topic.html I try to capture the userprofile info in template, e.g.
{{topic.creator.userprofile.name}}
or
{{topic.creator.userprofile.city}}
nothing is displayed. This happens for all fields that I try to fetch from UserProfile model, despite the fact that in the database the userprofile row for the user is not empty and I can get fields in other views.
I have been stuck on this for days so really appreciate your help.
Update: here is add_csrf, in case it might be relevant
def add_csrf(request, ** kwargs):
d = dict(user=request.user, ** kwargs)
d.update(csrf(request))
return d