Django add user to 'team' - django

I want the logged in user to be able to add users to a team they have created. At the moment I have created a form which lets the user select the user and the team they want to add them to, but they can select from every team in the database rather than just those they have created. Any ideas? These are my models, view and the form i have created. Also help with what to put in my HTML file would be appreciated.
Models:
class UserTeams(models.Model):
userID = models.ForeignKey(User,on_delete=models.CASCADE)
teamID = models.ForeignKey(Team,on_delete=models.CASCADE)
class Team(models.Model):
name = models.CharField(max_length=100)
venue = models.CharField(max_length=100)
countryID = models.ForeignKey(Countries, on_delete=models.CASCADE)
owner = models.ForeignKey(User)
View:
def invite(request):
if request.method == 'POST':
form = InvitePlayerForm(request.POST)
if form.is_valid():
userteam = form.save(commit=False)
userteam.save()
else:
form = InvitePlayerForm()
query = UserTeams.objects.all()
return render(request, 'teammanager/invite.html', {
"invite": query,
"form": form
})
Form:
class InvitePlayerForm(forms.ModelForm):
class Meta:
model = UserTeams
fields = ['userID','teamID']
HTML:
{% extends "teammanager/header.html" %}
{% block content %}
<html>
<body>
<h4>Invite players to your team</h4>
<form method="post">
{% csrf_token %}
{{ form.as_p }}
</form>
{% endblock %}

Modify your form like so it will do the FK filter based on the userteam object.
class InvitePlayerForm(forms.ModelForm):
class Meta:
model = UserTeams
fields = ['userID','teamID']
def __init__(self,user,*args,**kwargs):
super(InvitePlayerForm,self ).__init__(*args,**kwargs)
self.fields['teamID'].queryset = Team.objects.filter(id__in = UserTeam.objects.filter(userID = user))

Related

Making a CreateForm with choices based on database values

I am making a django project and I have a form for the User to add a Vehicle Manually that will be assigned to him. I also would like to had an option for the user to choose a vehicle based on the entries already present in the database.
vehicles/models.py
class Vehicle(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE)
nickname = models.CharField(unique = True, max_length=150)
date_joined = models.DateTimeField(default=timezone.now)
brand = models.CharField(max_length=150)
battery = models.CharField(max_length=150)
model = models.CharField(max_length=150)
def __str__(self):
return self.nickname
def get_absolute_url(self):
return reverse('vehicle-list')
class Meta:
db_table = "vehicles"
I created a form so the user can add his Vehicles as such:
vehicles/forms.py
class VehicleAddFormManual(forms.ModelForm):
class Meta:
model = Vehicle
fields = ('brand','model', 'battery', 'nickname')
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
super().__init__(*args, **kwargs)
self.fields['brand']
self.fields['model']
self.fields['battery']
self.fields['nickname']
The corresponding view:
vehicles/views.py
class AddVehicleViewManual(LoginRequiredMixin, CreateView):
model = Vehicle
form_class = VehicleAddFormManual
def get_form_kwargs(self):
kwargs = super().get_form_kwargs()
kwargs['user'] = self.request.user
return kwargs
def form_valid(self, form):
form.instance.user = self.request.user
return super().form_valid(form)
The html file:
vehicles/templates/vehicles/vehicle_form.html
{% extends "blog/base.html" %}
{% block content %}
{% load crispy_forms_tags %}
<div class="content-section">
<form method="POST">
{% csrf_token %}
<fieldset class="form-group">
<legend class="border-bottom mb-4">New Vehicle</legend>
{{ form|crispy }}
</fieldset>
<div class="form-group">
<button class="btn btn-outline-info" type="submit">Submit</button>
</div>
</form>
</div>
{% endblock content %}
I would like to add another form in which the user has a dropdown with option with the brands, models and batteries that already exist in the database. If there's a car in the database with brand: Tesla, model: Model 3, battery: 50 kWh, then it would appear in the dropbox as a choice for each field.
I'm not sure how to do this and sorry for the newbie question... Thanks in advance!
I once had to do something similar, but I needed a form which had one checkbox for each item in a list of externally-supplied strings. I don't know if this is the cleanest way, but I used python metaclasses:
class SockSelectForm(forms.Form):
#staticmethod
def build(sock_names):
fields = {'sock_%s' % urllib.parse.quote(name):
forms.BooleanField(label=name, required=False)
for name in sock_names}
sub_class = type('DynamicSockSelectForm', (SockSelectForm,), fields)
return sub_class()
In my get() method, I instantiate it as:
form = SockSelectForm.build(names)
and the corresponding form handling in the post() method is:
form = SockSelectForm(request.POST)
I suspect if you look under the covers of Django's ModelForm, you'd see something similar, but I couldn't use ModelForm because it's too closely tied to the model system for what I needed to do.
model.py
class DropdownModel(models.Model):
brand = models.CharField(max_length=150)
battery = models.CharField(max_length=150)
model = models.CharField(max_length=150)
def __str__(self):
return self.brand.
form.py
from .models import DropdownModel
all_brand = DropdownModel.objects.values_list('brand','brand')
all_battery = DropdownModel.objects.values_list('battery','battery')
all_model= DropdownModel.objects.values_list('model','model')
class DropdownForm(forms.ModelForm):
class Meta:
model = DropdownModel
fields = "__all__"
widgets = {
'brand':forms.Select(choices=all_brand),
'battery':forms.Select(choices=all_battery),
'model':forms.Select(choices=all_model),
}
view.py
from django.shortcuts import render
from .form import DropdownForm
# Create your views here.
def HomeView(request):
form = DropdownForm()
context = {'form':form}
return render(request,'index.html',context)
index.html
{% extends "base.html" %}
{% load static %}
{% block title %}
Index | Page
{% endblock title %}
{% block body %}
{{form.as_p}}
{% endblock body %}
Output-
Note- if u can't see updated values in dropdown do server restart because localhost not suport auto update value fill in dropdown it's supoorted on live server
Thank you

Django - saving model via a form is not working

I'm having a little problem with the .save() method in Django. For 1 form it works, for the other it doesn't. And I can't find the problem.
views.py
#login_required
def stock_add(request, portfolio_id):
if request.method == 'POST':
print('request.method is ok')
form = StockForm(request.POST)
print('form is ok')
if form.is_valid():
print('form is valid')
stock = form.save(commit=False)
stock.created_by = request.user
stock.portfolio_id = portfolio_id
stock.save()
return redirect('portfolio-overview')
else:
print("nope")
else:
print('else form statement')
form = StockForm()
context = {
'form':form
}
return render(request, 'portfolios/stock-add.html', context)
forms.py
class StockForm(ModelForm):
class Meta:
model = Stock
fields = ['quote', 'amount']
html
{% extends 'core/base.html' %}
{% block content %}
<div class="container">
<h1 class="title">Add Stock</h1>
<form method="POST" action=".">
{% csrf_token %}
{{ form.as_p }}
<button type="submit" class="button is-primary">Submit</button>
</form>
</div>
{% endblock %}
models
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class Portfolio(models.Model):
title = models.CharField(max_length=56)
description = models.TextField(blank=True, null=True, max_length=112)
created_by = models.ForeignKey(User, related_name='portfolios', on_delete=models.CASCADE)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name_plural = 'Portfolio'
def __str__(self):
return self.title
class Stock(models.Model):
Portfolio = models.ForeignKey(Portfolio, related_name='stocks', on_delete=models.CASCADE)
quote = models.CharField(max_length=10)
amount = models.IntegerField()
created_by = models.ForeignKey(User, related_name='stocks', on_delete=models.CASCADE)
created_at = models.DateField(auto_now_add=True)
def __str__(self):
return self.quote
If you look at the views.py file, when I submit the form, it won't even do print('request.method is ok')
I can add the stock via the admin page.
So I have no clew where to look anymore...
Cheers
When you post a form and need a special url (like your' with an attribute), i like to set action="{% url myview.views.stock_add portfolio_id %}"
action="." will save to the same page without taking care of extra parameters (if needed)
Just pass portfolio_id in the context and that will work
I found the answer, an InteregerField (from models.py) needs a default value.
Either default=None (or another value).
Cheers

add/remove fields in django forms

So I have a form where user can post "Parents" details also fields for Children from a different model.
What I need is that to allow users to add "Children" fields as many children as they have . Also for the children fields not to be required in case they do not have children.
But, if one of the children fields is filled the others are required.
models.py :
class Parent(models.Model):
title = models.CharField(max_length=250)
address = models.CharField(max_length=250)
class Kid(models.Model):
family = models.ForeignKey(Parent)
title = models.CharField(max_length=250)
age = models.CharField(max_length=250)
views.py
def add_family(request):
if request.method == 'POST':
parent_form = ParentForm(request.POST)
kid_form = KidForm(request.POST)
if parent_form.is_valid() and kid_form.is_valid():
parent = parent_form.save(commit=False)
parent.save()
kid = kid_form.save(commit=False)
kid.family = parent
kid.save()
return redirect('index')
else:
parent_form = ParentForm()
kid_form = KidForm()
template = 'add_family.html'
context = {'parent_form': parent_form, 'kid_form': kid_form}
return render(request, template, context)
template:
<form method="post">
{% csrf_token %}
{{ parent_form.title }}
{{ parent_form.address }}
{{ kid_form.title }}
{{ kid_form.age }}
<button type="submit">Send</button>
</form>
so if the "kid_form.title" is filled. then the age is required.
any help?

Django - Display imagefield in ManytoMany form instead of title

I am working on a Django project with crispy forms.
I want to use images instead of the the default Models title/label to select a instance in a Many to Many relation form.
Content models.py:
class Cloth(models.Model):
owner = models.ForeignKey(settings.AUTH_USER_MODEL)
title = models.CharField(max_length=200)
picture = ImageCropField(upload_to='cloth_pics/%Y-%m-%d/',
blank=True)
def __str__(self):
return self.title
class Outfit(models.Model):
owner = models.ForeignKey('profiles.Profile')
title = models.CharField(max_length=200)
cloths=models.ManyToManyField(Cloth)
Content forms.py
class ClothForm(forms.ModelForm):
class Meta:
model = Cloth
fields = ('title','type','picture')
class OutfitForm(forms.ModelForm):
class Meta:
model = Outfit
exclude= ["owner"]
Content views.py
def outfits_new(request):
if request.method == "POST":
form = OutfitForm(request.POST)
if form.is_valid():
outfit = form.save(commit=False)
outfit.owner = get_user(request)
outfit.created_date = timezone.now()
outfit.save()
pk=outfit.id
return HttpResponseRedirect(reverse('outfit_edit_delete', args=[pk]))
else:
cloths = Cloth.objects.filter(owner=request.user.id)
form = OutfitForm()
return render(request, '../templates/outfits_new.html', {'form': form, "cloths":cloths})
Content outfits_new.html
<form enctype="multipart/form-data" method="post">
{% csrf_token %}
{{ form|crispy }}
<div class="btn-group" role="group" aria-label="Basic example">
<input type="submit" value="Submit" name="edit" class="btn btn-success">
</div>
This code produces a Outfit form where I can select different cloths( displaying the cloths title). I want to select different cloths using a image from the cloths.picture field.
Thank you very much,
Patrick
Have a look at select2 at https://select2.github.io/examples.html. It allows you to do images in comboboxes
There is a Django package at https://github.com/applegrew/django-select2

How to filter queryset based on value of another model in Django?

I'm trying to make a simple search function. I'm using the User model and a UserProfile model with a OneToOne relationship. I've successfully managed to search by the username, first name and last name, all three field being in the User model. However, I want to filter by the fields present in UserProfile model, e.g. sex, age, location, etc.
views.py
def Home(request):
query = request.GET.get('query', '')
queryset = User.objects.none()
if request.method == "GET":
form = SearchForm(request.GET)
if form.is_valid():
if query != '':
queryset = User.objects.filter(Q(username__icontains=query)
| Q(first_name__icontains=query)
| Q(last_name__icontains=query)).exclude(is_staff=True)
else:
form = SearchForm()
return render(request, "main/home.html", {'form': form, 'queryset': queryset})
home.html
{% extends "base.html" %}
{% block body %}
<h3>Home</h3>
<p>
<form method="get" action="">
{{ form.as_p }}
<input type="submit" value="Search"/>
</form>
</p>
<p>
{% for user in queryset %}
{{ user.get_full_name }} <br/>
{% endfor %}
</p>
{% endblock %}
forms.py
class SearchForm(forms.Form):
query = forms.CharField(max_length=100, label="", widget=forms.TextInput(attrs={'placeholder': 'Search...'}), required=False)
age_from = forms.IntegerField(label="", widget=forms.NumberInput(attrs={'placeholder': 'Age from'}), required=False)
age_to = forms.IntegerField(label="", widget=forms.NumberInput(attrs={'placeholder': 'Age to'}), required=False)
models.py
UserProfile(models.Model):
sex_choices = (
('Male', 'Male'),
('Female', 'Female'),
('Other', 'Other'),
)
sex = models.CharField(max_length=6,
choices=sex_choices,
default='Male')
birth_date = models.DateField()
How can I include options to search based on other fields on UserProfile model which has a OneToOne relation with User model?
You need to use the related name.
As you haven't shared your models definition, let's suppose:
class UserProfile(models.Model):
user = models.OneToOneField(User)
sex = models.CharField(...)
...
So, when you query:
User.objects.filter(user_profile_set__sex='female')
EDIT
To query based in age, given that you ask for an 'age' in your form and you store a birthdate in your model, you could try something like this:
from datetime import datetime
age = 18 # this shoudl come from form
birth_year = datetime.now().year - age
User.objects.filter(user_profile_set__birth_date__year=birth_year)