how to get specific users from django user in another model - python

I have this model called UserTypes in this model i use User as OneToOne field and UserTypes model is inline with User model. I created this model to give the user a status just like we do is_staff=True.
now i want to display all the users whose staff_status = "Delivery Boy" in another model called Order which is in another app in the same project
model.py(app1)
class UserTypes(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
staff_choices = (
('', ''),
('Admin', 'Admin'),
('Chef', 'Chef'),
('Delivery Boy', 'Delivery Boy'),
)
staff_status = models.CharField(max_length=15, choices=staff_choices, default=staff_choices[0][0])
def __str__(self):
return self.staff_status
model.py(app2)
class Order(models.Model):
name = models.CharField(max_length=60)
email = models.EmailField(max_length=60,default=None, blank=True)
mobile_no = models.CharField(max_length=13, default=None)
address = models.CharField(max_length=150)
created = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
status_choices = (
('In Queue', 'In Queue'),
('Processing', 'Processing'),
('Ready', 'Ready'),
('Delivered', 'Delivered'),
('Paid', 'Paid'),
('Cancelled', 'Cancelled'),
)
status = models.CharField(max_length=15, choices=status_choices,
default=status_choices[0][0])
total = models.DecimalField(max_digits=10, decimal_places=2,default=0)
class Meta:
ordering = ('created', )
def __str__(self):
return 'Order {}'.format(self.id)
def get_total(self):
return sum(item.get_cost() for item in self.items.all())

Add a field in app2 models.py file to store the usertype in orders table:
from app1.models import UserTypes
user = models.OneToOneField(UserTypes, on_delete=models.CASCADE)
Add this code to admin.py file of your app2:
from app1.models import UserTypes
from .models import Order
class OrderAdmin(admin.ModelAdmin):
def get_form(self, request, obj=None, **kwargs):
form = super(OrderAdmin,self).get_form(request, obj,**kwargs)
# form class is created per request by modelform_factory function
# so it's safe to modify
# we modify the the queryset
form.base_fields['user'].queryset =
form.base_fields['user'].queryset.filter(staff_choices='Delivery Boy')
return form
admin.site.register(Order, OrderAdmin)

Related

Django Form with ForeignKey field NOT NULL constraint failed Error

Each model is chain-linked to the previous model. I make one form to fill in, since all the models are linked. When I try to link a model address to a project, an error appears
NOT NULL constraint failed: crm_project.address_id
/crm/views.py, line 39, in add_project
form_project.save()
Models
class City(models.Model):
obl = models.CharField(max_length=255, choices=REGIONS, default="24", verbose_name="Регион")
name = models.CharField(max_length=128, verbose_name="Город")
population = models.IntegerField()
def __str__(self):
return self.name
class Address(models.Model):
city = models.ForeignKey(City, on_delete=models.PROTECT, verbose_name="Город")
street = models.CharField(max_length=255, verbose_name="Улица")
numb = models.CharField(max_length=64, verbose_name="Номер дома")
def __str__(self):
return f"{self.street}, {self.numb}"
class Project(models.Model):
manager = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name="Сотрудник")
address = models.ForeignKey(Address, on_delete=models.PROTECT, verbose_name="Адрес")
# another fields
class ProjectDetail(models.Model):
project = models.OneToOneField(Project, on_delete=models.CASCADE, verbose_name="Проект")
# another fields
Forms
class AddressForm(forms.ModelForm):
class Meta:
model = Address
fields = ["city", "street", "numb"]
def __init__(self, *args, **kwargs):
city = kwargs.pop("city", "")
super(AddressForm, self).__init__(*args, **kwargs)
self.fields["city"] = forms.ModelChoiceField(queryset=City.objects.all())
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = ["file", "sq", "rent_tax"]
class ProjectDetailForm(forms.ModelForm):
class Meta:
model = ProjectDetail
exclude = ['project', 'comment', 'resume', 'complite', 'created_at']
Views
def add_project(request):
form_address = AddressForm(request.POST or None)
form_project = ProjectForm(request.POST or None)
form_detail = ProjectDetailForm(request.POST or None)
if request.method == 'POST':
if form_address.is_valid() and form_project.is_valid() and form_detail.is_valid():
address = form_address.save(commit=False)
form_project.manager = request.user
form_project.address = address
project = form_project.save(commit=False)
form_detail.project = project
form_address.save()
form_project.save()
form_detail.save()
context = {'form_address':form_address, 'form_project':form_project, 'form_detail':form_detail,}
return render(request, 'crm/project_form.html', context)
in your ProjectForm you specified these fields only fields = ["file", "sq", "rent_tax"]
but as per Your Model:
class Project(models.Model):
manager = models.ForeignKey(User, on_delete=models.PROTECT, verbose_name="Сотрудник")
address = models.ForeignKey(Address, on_delete=models.PROTECT, verbose_name="Адрес")
There two fields are null=FalseMeans every instance of Project must have these Values which you're not providing in the ProjectForm
to handle this error you can do 2 things as per your need.
replace this form with this:
class ProjectForm(forms.ModelForm):
class Meta:
model = Project
fields = '__all__"
or another option which is not how you should use foreign keys.
change your class with this and makemigrations and migrate again:
class Project(models.Model):
manager = models.ForeignKey(User, on_delete=models.PROTECT,null=True, blank=True, verbose_name="Сотрудник")
address = models.ForeignKey(Address, on_delete=models.PROTECT, null=True, blank=True,verbose_name="Адрес")

How to filter/hide fields in django rest framework HTML form using authenticated user

I created two models:
parcel (package) model,
'shelf' model to which parcels can be assigned.
class Parcel(models.Model):
owner = models.ForeignKey(get_user_model(), on_delete=models.PROTECT)
name = models.CharField(max_length=100, blank=False)
contents = models.TextField(blank=False, validators=[MaxLengthValidator(1500)])
size = models.CharField(max_length=50, blank=True, validators=[package_size_validator])
weight = models.PositiveIntegerField(blank=True, null=True)
contact = models.CharField(max_length=50, blank=True)
creation_date = models.DateTimeField(auto_now_add=True)
last_modification = models.DateTimeField(auto_now=True)
code = models.CharField(max_length=30, unique=True, blank=False)
def __str__(self):
return f'Parcel: {self.code}, {self.owner}, {self.name}'
class ParcelShelf(models.Model):
owner = models.ForeignKey(get_user_model(), on_delete=models.PROTECT)
name = models.CharField(max_length=100, blank=False)
creation_date = models.DateTimeField(auto_now_add=True)
last_modification = models.DateTimeField(auto_now=True)
parcels = models.ManyToManyField('Parcel', blank=True, related_name='shelf_parcel')
def __str__(self):
return f'ParcelShelf: {self.owner}, {self.name}'
I came to a solution where the logged-in user can see only his packages and shelves. The problem I have is with the many-to-many relationship where parcels can be added to shelves. I want to come to a solution where the logged in user can add to the shelf only those parcels which he is the owner, creator. It will look better in pictures.
All packages created by user t2#t2.com (user id = 17):
parcels list
Now the view when the user t2#t2.com wants to create a shelf:
shelf list
All packages are visible, while only those created by the user t2#t2.com should be available.
Code to serializer:
class ParcelShelfSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
parcels = serializers.HyperlinkedRelatedField(many=True, read_only=False, view_name='parcels_detail_view',
# queryset=Parcel.objects.filter(owner=17)
queryset=Parcel.objects.all()
)
class Meta:
model = ParcelShelf
fields = ('id', 'owner', 'name', 'creation_date', 'last_modification', 'parcels')
Below is a picture where only packages for a given, logged-in user are available:
shelf list
Code to serializer:
class ParcelShelfSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
parcels = serializers.HyperlinkedRelatedField(many=True, read_only=False, view_name='parcels_detail_view',
queryset=Parcel.objects.filter(owner=17)
# queryset=Parcel.objects.all()
)
class Meta:
model = ParcelShelf
fields = ('id', 'owner', 'name', 'creation_date', 'last_modification', 'parcels')
I got to the point where the 'solution' is in the 'queryset' argument.
All users: queryset=Parcel.objects.all()
Logged in user: queryset=Parcel.objects.filter(owner=17)
The problem is, this is hardcoded, and it should be something like: (owner=request.user). Unfortunately, I don't know how to achieve this in the serializer. I looked through other similar topics, but I didn't find a solution how to use the request method in the serializer field.
In addition, code in views:
class ParcelsShelfList(generics.ListCreateAPIView):
# queryset = ParcelShelf.objects.all()
serializer_class = ParcelShelfSerializer
def get_queryset(self):
user = self.request.user
if bool(user and user.is_staff and user.is_admin):
return ParcelShelf.objects.all()
else:
return ParcelShelf.objects.filter(owner=user)
def perform_create(self, serializer):
serializer.save(owner=self.request.user)
UPDATE
Thanks to the help of #Amrez, who gave me a link to a similar topic, i was able to do it.
mentioned link: How can I filter DRF serializer HyperlinkedRelationField queryset based on request data?
I add this to my code in serializers.py:
def hyperlinked_related_field_by_owner(model, view_name, owner):
return serializers.HyperlinkedRelatedField(
many=True,
view_name=view_name,
queryset=model.objects.filter(owner=owner)
)
class ParcelShelfSerializer(serializers.ModelSerializer):
owner = serializers.ReadOnlyField(source='owner.email')
parcels = serializers.HyperlinkedRelatedField(many=True,
read_only=False,
view_name='parcels_detail_view',
# queryset=Parcel.objects.filter(owner=17)
queryset=Parcel.objects.all()
)
def get_fields(self):
fields = super().get_fields()
owner = self.context['request'].user
fields['parcels'] = hyperlinked_related_field_by_owner(Parcel, 'parcels_detail_view', owner)
return fields
class Meta:
model = ParcelShelf
fields = ('id', 'owner', 'name', 'creation_date', 'last_modification', 'parcels')

Displaying choice from a Model form based on another model

Working on a project that I am stumped on and I can't seem to find a good solution to this. An overview of the problem I need to resolve. I have 3 models (Games, GameRoles, and Groups) I have a defined list of games and a user can create a group from that list. The games also have roles associated with them. So the idea is I want a user to create a group based on a game from my game model, each game has different roles associated with it. When the user creates a group I want those roles to display in a checkbox field so they can add these roles if they need them.
My problem is I can't seem to find a good way to do this. I read the docs and I think what I need is an Iterating relationship choice class in my forms.py
Games model.py
from django.db import models
from django.db.models.aggregates import Max
from django.db.models.fields.related import ForeignKey
# Create your models here.
class Game(models.Model) :
GENRE_CHOICES = [
('Action', 'Action'),
('Acion-Adventure', 'Action-Adventure'),
('Adventure', 'Adventure'),
('MMO', 'MMO'),
('Puzzle', 'Puzzle'),
('Role Playing', 'Role Playing'),
('Simulation', 'Simulation'),
('Strategy', 'Strategy'),
('Sports', 'Sports')
]
RATING_CHOICES = [
('E', 'Everyone'),
('E10+', 'Everyone 10+'),
('T', 'Teen'),
('M', 'Mature 17+'),
('A', 'Adults Only 18+'),
('RP', 'Rating Pending')
]
PLATFORM_CHOICES = [
('Multi', 'Multi Platform'),
('PC', 'PC'),
('XBOX', 'XBOX'),
('Playstation', 'Playstation'),
('Nintendo', 'Nintendo')
]
name = models.CharField(max_length=200)
platform = models.CharField(max_length=20,
null=True,
choices=PLATFORM_CHOICES,
default='Select'
)
publisher = models.CharField(max_length=100)
genre = models.CharField(max_length=100,
null=True,
choices=GENRE_CHOICES,
default='Select'
)
rating = models.CharField(max_length=15,
null=True,
choices=RATING_CHOICES,
default='Select'
)
release_date = models.DateField()
tags = models.CharField(max_length=200)
picture = models.ImageField(
max_length=200,
default='games/default.png',
null=True,
upload_to='games/'
)
is_new = models.BooleanField(null=True)
is_popular = models.BooleanField(null=True)
is_featured = models.BooleanField(null=True)
def __str__(self):
return self.name
class GameRole(models.Model):
game = models.ForeignKey(Game, on_delete=models.CASCADE)
role = models.CharField(max_length=200)
def __str__(self):
return self.role
Group models.py
from django.contrib.auth.models import User
from django.db import models
from django.db.models.aggregates import Max
from games.models import Game, GameRole
# Create your models here.
class Group(models.Model):
name = models.CharField(max_length=200)
game = models.ForeignKey(Game, on_delete=models.CASCADE)
size = models.IntegerField(default=1)
total_size = models.IntegerField(null=True)
play_time = models.DateTimeField(null=True)
description = models.TextField(max_length=200)
is_full = models.BooleanField(default=False)
is_active = models.BooleanField(default=True)
discord = models.URLField(max_length=200, null=True)
user = models.ForeignKey(User, null=True, on_delete=models.CASCADE)
def __str__(self):
return self.name
class GroupRole(models.Model):
group = models.ForeignKey(Group, on_delete=models.CASCADE)
role = models.ForeignKey(GameRole, on_delete=models.CASCADE)
def __str__(self):
return self.role
forms.py
from django import forms
from django.contrib.auth.models import User
from django.forms import fields, widgets
from LFG.models import Group, GroupMembers, GroupRole
from games.models import Game, GameRole
class DateTimeInput(forms.DateTimeInput):
input_type = 'datetime-local'
class CheckboxInput(forms.CheckboxInput):
input_type = 'checkbox'
class RoleSelect(form.Select):
def creation_option(self, name, value, label, selected, index, subindex=None, attrs=None):
option = super().create_option(name, value, label, selected, index, subindex, attrs)
class GroupForm(forms.ModelForm):
game = forms.ModelChoiceField(queryset=Game.objects.all())
class Meta():
model = Group
fields = ['game', 'name']
class GroupTwoForm(forms.ModelForm):
ROLE_CHOICES = []
roles= forms.ModelMultipleChoiceField(ROLE_CHOICES)
class Meta():
model = Group
fields = ['name', 'total_size', 'play_time', 'description', 'discord']
widgets = {
'play_time':DateTimeInput(),
#'roles':CheckboxInput()
}
def role_display(game_id):
roles = GameRole.object.all()
for role in roles:
if role.game_id == game_id:
r = role
ROLE_CHOICES[r] = r
return ROLE_CHOICES
class GroupMemberForm(forms.ModelForm):
class Meta():
model = GroupMembers
fields = [ 'group', 'member', 'role']
views.py
#login_required(login_url='/login')
def create_group_2_view(request, group_id):
profile = request.user.userprofile
form_user = Group.objects.filter(pk=group_id).values('user')
formID = Group.objects.filter(pk=group_id).first()
roles = GameRole.objects.all()
print(form_user)
if request.method == 'POST':
form = GroupTwoForm(request.POST or None, instance=formID)
# if group_id == form.pk:
if form.is_valid():
form.save()
messages.success(request, 'Group created!')
return redirect('lfg')
else:
print(form.errors)
messages.error(request, form.errors)
return redirect('create-group-2', formID)
else:
form = GroupTwoForm(instance=formID)
context = {
'title':'Create a Group',
'year':datetime.now().year,
'profile':profile,
'form':form,
'roles':roles,
}
return render(request, 'lfg/create-group-2.html', context)
As you can see in forms.py I was attempting to create a role section class that will do this and then pass it to GroupTwoForm. Sorry if this is a bit confusing, still learning Django, if clarification is needed I will clarify.

Take the current admin

serializers.py
class RegSerializer(serializers.ModelSerializer):
admin = serializers.SlugRelatedField(slug_field='username', read_only=True)
class Meta:
model = Registration
fields = [
'id', 'rooms', 'first_name', 'last_name','admin', 'pasport_serial_num', 'birth_date', 'img', 'visit_date',
'leave_date', 'guest_count', 'room_bool']
models.py
class Rooms(models.Model):
objects = None
room_num = models.IntegerField(verbose_name='Комната')
room_bool = models.BooleanField(default=True, verbose_name='Релевантность')
category = models.CharField(max_length=150, verbose_name='Категория')
price = models.IntegerField(verbose_name='Цена (сум)', null=True)
def __str__(self):
return f'{self.room_num}'
class Meta:
verbose_name = 'Комнату'
verbose_name_plural = 'Комнаты'
class Registration(models.Model):
objects = None
rooms = models.ForeignKey(Rooms, on_delete=models.CASCADE, verbose_name='Номер',
help_text='Номер в который хотите заселить гостя!',
)
first_name = models.CharField(max_length=150, verbose_name='Имя')
last_name = models.CharField(max_length=150, verbose_name='Фамилия')
admin = models.ForeignKey(User, on_delete=models.CASCADE, verbose_name='Администратор')
pasport_serial_num = models.CharField(max_length=100, verbose_name='Серия паспорта', help_text='*AB-0123456')
birth_date = models.DateField(verbose_name='Дата рождения')
img = models.FileField(verbose_name='Фото документа', help_text='Загружайте файл в формате .pdf')
visit_date = models.DateField(
default=django.utils.timezone.localdate, verbose_name='Дата прибытия')
leave_date = models.DateField(blank=True, null=True, verbose_name='Дата отбытия', default='После ухода!')
guest_count = models.IntegerField(default=1, verbose_name='Кол-во людей')
room_bool = models.BooleanField(default=False, verbose_name='Релевантность',
help_text='При бронирование отключите галочку')
price = models.IntegerField(verbose_name='Цена (сум)', null=True)
def __str__(self):
return f'{self.rooms},{self.last_name},{self.first_name},{self.room_bool}'
class Meta:
verbose_name = 'Номер'
verbose_name_plural = 'Регистрация'
how can I make it so that the name of the user who registered room is indicated in the admin field and without the right to change only readonly?
can this be done at all?
thanks in advance for your reply
You can pass additional attributes to serilizer's save method. In your view, you can call serializer save() with admin argument like this:
def your_view(request):
# your code
serializer.save(admin=request.user)
Or if you want to do it on admin page, you can override your admin's save_model method. Also you should specify admin as a readonly:
class RegistrationAdmin(admin.ModelAdmin):
readonly_fields = ('admin',)
def save_model(self, request, obj, form, change):
if not obj.pk:
# Only set admin during the first save.
obj.admin = request.user
super().save_model(request, obj, form, change)
I set serializers.HiddenField and by default set CurrentUserDefault() from serializers
automatically substitutes the value of the current admin and at the same time the admin field now goes to the api
class RegSerializer(serializers.ModelSerializer):
admin = serializers.HiddenField(default=serializers.CurrentUserDefault())
class Meta:
model = Registration
exclude = ['price', 'visit_date']

how to check and pass the instance of the user in my form in Django?

Hi I'm trying to create a form that accepts Log from the user however I don't know how to pass the instance of the user. I'm used to creating a CreateView for this, however since I'm planning to use customized widgets and settings, I'm using a modelform to create logs for the user.
My question is is this the same way as create view to check the instance of the user?
Is it still the same as what I did to my createview which is:
def form_valid(self,form) :
form.instance.testuser = self.request.user
return super().form_valid(form)
Or do I have to do something else entirely?
Here is my Forms.py:
from django import forms
from profiles.models import User
from .models import DPRLog
class DateInput (forms.DateInput):
input_type = 'date'
class Datefield (forms.Form):
date_field=forms.DateField(widget=DateInput)
class dprform(forms.ModelForm):
class Meta:
model = DPRLog
widgets = {'reportDate':DateInput()}
fields = ['status','login','logout','reportDate','mainTasks','remarks']
Models.py:
from django.db import models
from profiles.models import User
from django.urls import reverse
# Create your models here.
class Points(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
points = models.IntegerField(default=0, null=False)
def __str__(self):
return self.user.username
class Profile(models.Model):
user = models.OneToOneField(User, on_delete=models.CASCADE)
image = models.ImageField(default='default.png', upload_to='profile_pics')
def __str__(self):
return f'{self.user.username} Profile'
class Manager(models.Model):
manager = models.OneToOneField(User, on_delete=models.CASCADE)
def __str__(self):
return self.manager.full_name
class Member(models.Model):
manager = models.ForeignKey(Manager, on_delete=models.CASCADE)
member = models.OneToOneField(User, on_delete=models.CASCADE)
name = models.CharField(max_length=30, null=True)
def __str__(self):
return self.member.full_name
class Job(models.Model):
manager = models.ForeignKey(Manager, on_delete=models.CASCADE)
member = models.ForeignKey(Member, on_delete=models.CASCADE)
title = models.CharField(max_length=30, blank=False, null=False)
description = models.TextField()
datePosted = models.DateTimeField(auto_now=True)
file = models.FileField(null=True, blank=True, upload_to='job_files')
def __str__(self):
return self.title
def get_absolute_url(self):
return reverse('job-detail', kwargs={'pk': self.pk})
class DPRLog(models.Model):
STATUS_CHOICES = (
('PENDING', 'PENDING'),
('CANCELLED', 'CANCELLED'),
('COMPLETED', 'COMPLETED'),
)
TASKS_CHOICES = (
('TESTS EXECUTION', 'TESTS EXECUTION'),
('TESTS DESIGN', 'TESTS DESIGN'),
('MOBILE TESTING WORKSHOP', 'MOBILE TESTING WORKSHOP'),
('BENCH ACTIVITY', 'BENCH ACTIVITY'),
('DEFECT ANALYSIS','DEFECT ANALYSIS'),
)
testuser = models.ForeignKey(User,on_delete = models.CASCADE)
status = models.CharField(max_length=30, choices=STATUS_CHOICES,null=True)
reportDate = models.DateField(blank=False, null=False)
login = models.TimeField(blank=False, null=False)
logout = models.TimeField(blank=False, null=False)
mainTasks = models.CharField(max_length=50, blank=False, choices=TASKS_CHOICES, null=True)
remarks = models.CharField(max_length=30,null=True)
def __str__(self):
return f'{self.testuser.full_name} DPR Log'
Views.py:
def dprmodelform(request):
if request.method=='POST':
form = dprform(request.POST)
if form.is_valid():
form.save()
form = dprform()
return render (request,'users/dprform.html',{'form':form})
def form_valid(self,form) :
form.instance.testuser = self.request.user
return super().form_valid(form)
class dprview(LoginRequiredMixin,ListView):
model = DPRLog
template_name = 'users/dpr_view.html'
context_object_name = 'log'
If you pass commit=False to form.save() you can get the instance from the validated form without saving to the database. You can then set the user attribute on the instance before calling save again
if form.is_valid():
instance = form.save(commit=False)
instance.testuser = request.user
instance.save()

Categories