Displaying choice from a Model form based on another model - python

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.

Related

How to get the username of the current user and assign it to a certain field in a form in django?

This is my models.py file
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Book(models.Model):
category_choices =(
#("Undefined","Undefined"),
("Action", "Action"),
("Romance", "Romance"),
("Horror", "Horror"),
("Comedy", "Comedy"),
("Adventure", "Adventure"),
("Dramatic", "Dramatic"),
("Crime","Crime"),
("Fantasy","Fantasy"),
)
name = models.CharField(max_length=100)
author = models.CharField(max_length=100, null=True)
content = models.TextField()
price = models.DecimalField(max_digits=5, decimal_places=2)
image = models.ImageField(upload_to= 'photos/%y/%m/%d', blank = True)
category = models.CharField(
max_length = 20,
choices = category_choices,
#default = 'Undefined'
)
publication_year = models.CharField(max_length=4, null=True)
ISBN = models.CharField(max_length=13, null=True, unique=True)
active = models.BooleanField(default= True)
def __str__(self):
return self.name
class Borrow(models.Model):
name = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
book = models.OneToOneField(Book, null=True, on_delete= models.SET_NULL)
period = models.PositiveIntegerField(default=0)
id = models.IntegerField(primary_key=True)
def __str__(self):
return str(self.book)
and this is my forms.py file
from django import forms
from .models import Borrow
class BorrowForm(forms.ModelForm):
class Meta:
model = Borrow
fields = ('name', 'book', 'period')
and this is the function in my views.py file that renders the form
#login_required
def borrowing(request):
momo = BorrowForm()
if request.method == 'POST':
momo = BorrowForm(request.POST)
if momo.is_valid():
instacne = momo.save(commit=False)
instacne.user = request.user.username
instacne.save()
return redirect('profile')
return render(request, 'books/book.html', {'momo': momo})
The role of this function is to render that form and to save the data that user will enter and automatically assign the username of the current user to the field 'name' in form.
I tried alot of things to get the username of the current user and assign it to the field 'name' but nothing works and that field stays blank.
You're using a models.ForeignKey(User) so that table will store a user id, not a username. I'd call this field user and not name, personally.
Therefore you need to provide a user instance to it like this;
#login_required
def borrowing(request):
initial = {}
if request.user.is_authenticated:
initial.update({'name': request.user})
momo = BorrowForm(initial=initial)
if request.method == 'POST':
momo = BorrowForm(request.POST)
if momo.is_valid():
instance = momo.save(commit=False)
instance.user = request.user
instance.save()
If you wanted to easily get the username for a Borrow instance you could do this;
class Borrow(models.Model):
name = models.ForeignKey(User, null=True, on_delete=models.SET_NULL)
book = models.OneToOneField(Book, null=True, on_delete= models.SET_NULL)
period = models.PositiveIntegerField(default=0)
id = models.IntegerField(primary_key=True)
def __str__(self):
return str(self.book)
#property
def username(self):
return self.name.username
If you want the form to offer users by username, you can either have the str method of your user model return username, or create custom choices as a tuple of user ID & username in the form __init__

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()

How to make Django select box option not selectable?

I have made a Django Form using Django Crispy Forms. I used the Foreign Key concept to display dropdowns in my page. I would like the first option of the dropdown ('Choose..') to be shown to the user but he/she must not be able to select it.
It is very easy to do with JavaScript but I'm not sure how to do it with Django.
My page with the dropdowns
I am also attaching the code for my forms.py and models.py.
models.py
from django.db import models
from django import forms
class Organization(models.Model):
orgname = models.CharField(max_length = 100, blank=True)
def __str__(self):
return str(self.orgname)
class Team(models.Model):
teamID = models.AutoField(primary_key=True)
teamName = models.CharField(max_length = 100, blank=True)
org = models.ForeignKey(Organization, on_delete=models.CASCADE)
def __str__(self):
return str(self.teamName)
class AgileTeam(models.Model):
agileTeamID = models.AutoField(primary_key=True)
agileTeamName = models.CharField(max_length = 100, blank=True)
org = models.ForeignKey(Organization, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
def __str__(self):
return str(self.agileTeamName)
class Employee(models.Model):
name = models.CharField(max_length=100)
assoc_id = models.CharField(max_length=10)
username = models.CharField(max_length=50, blank=True)
password = models.CharField(max_length=50, blank=True)
organization = models.ForeignKey(Organization, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete=models.CASCADE)
agile_team = models.ForeignKey(AgileTeam, on_delete=models.CASCADE)
forms.py
from django import forms
from django.forms import ModelForm
from .models import Organization, Team, AgileTeam, Employee
class EmployeeForm(forms.ModelForm):
password = forms.CharField(widget=forms.PasswordInput(render_value = True))
class Meta:
model = Employee
fields = ('name', 'assoc_id', 'username', 'password', 'organization', 'team', 'agile_team',)
labels = {
'name':'Name',
'assoc_id':'Associate ID',
'username': 'Username',
'password': 'Password',
'organization':'Organization Name',
'team': 'Team Name',
'agile_team': 'Agile Team'
}
def __init__(self, *args, **kwargs):
super(EmployeeForm,self).__init__(*args, **kwargs)
# Code to make fields optional and to set the first option of dropdown as "Choose.."
self.fields['organization'].required = False
self.fields['organization'].empty_label = "Choose.."
self.fields['team'].required = False
self.fields['team'].empty_label = "Choose.."
self.fields['agile_team'].required = False
self.fields['agile_team'].empty_label = "Choose.."
This is my first question on StackOverflow. I hope I have been able to explain my problem properly.
Thanks in advance!
May the force be with you.

how to get specific users from django user in another model

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)

How to use two model forms on one view

I'm still new to django, I'm working on a project where I'll need users to enter some information about houses they want to rent out. I want the users to upload a minimum of 6 pictures and from what I've gathered, the best way to do this on django is to use two models, one collects basic information about the houses and the second stores images of the houses. How am I supposed to code the views.py. I've tried all to no avail.
forms.py
class MyHouseEditForm(forms.ModelForm):
class Meta:
model = Myhouses
fields = ('name_of_accomodation',
'type_of_apartment','Number_of_rooms', 'house_rent',
'availability', 'location', 'nearest_institution',
'description',)
class ImageForm(forms.ModelForm):
class Meta:
model = Image
fields = ('__all__' )
models.py
class Myhouses(models.Model):
Available = 'A'
Not_Available = 'NA'
Availability = (
(Available, 'Available'),
(Not_Available, 'Not_Available'),
)
Flat = 'F'
Self_contained = 's'
Bungalow = 'b'
Mini_flat = 's'
Duplex = 'D'
Room = (
(Flat, 'Flat'),
(Self_contained, 'Self_contained'),
(Bungalow, 'Bungalow'),
(Mini_flat, 'Mini_flat'),
(Duplex, 'Duplex'),
)
time = models.DateTimeField(default = datetime.now, blank = True)
name_of_accomodation = models.CharField(max_length=20)
type_of_apartment = models.CharField(max_length=2, choices=Room, )
Number_of_rooms = house_rent = models.IntegerField()
house_rent = models.IntegerField()
availability = models.CharField(max_length=2, choices=Availability, default=Available,)
location = models.CharField(max_length=200)
nearest_institution = models.CharField(max_length=200)
description = models.TextField(blank=True)
author = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.SET_NULL, null=True, blank=True, related_name='author')
def __str__(self):
return self.name_of_accomodation
def get_absolute_url(self):
return reverse('search-detail', args=[str(self.id)])
class Meta:
ordering = ["-time"]
class Image(models.Model):
myhouses = models.ForeignKey(Myhouses, related_name='images', on_delete=models.PROTECT)
image = models.ImageField(upload_to='documents/')
views.py
def addlisting(request):
if request.method == 'POST':
Hform = MyHouseEditForm(request.POST, files=request.FILES, )
Iform = ImageForm(request.POST, request.FILES, )
if Hform.is_valid() and Iform.is_valid():
Houses = Hform.save(commit=False)
Houses.author=request.user
Houses.save()
image = iform.save(commit=False)
Houses.image.myhouses = myhouses
Houses.save()
messages.success(request, 'Listing Created Succesfully successfully')
return redirect('addlisting')
else:
Hform = MyHouseEditForm()
Iform = ImageForm()
return render(request, 'houses/addlisting.html', {'Hform':Hform, 'Iform': Iform}, )

Categories