I have model Skill
class Skill(models.Model):
hero= models.ForeignKey(Hero)
name = models.CharField(max_length=255)
And I have model Hero
class Hero(models.Model):
name = models.CharField(max_length=255)
I use multiple choice field to select skills
OPTIONS = (
("sharingan", "sharingan"),
("rasengan", "rasengan"),
("fireball", "fireball"),
)
skills= forms.MultipleChoiceField(widget=forms.CheckboxSelectMultiple(),
choices=OPTIONS)
I use get request to send my form and my search page url becomes something like:
mysite.com/search?skills=shiringan&skills=rasengan
In my views.py I have
def vip(request):
heroes = Hero.objects.all
return render(request, 'app_name/search.html',{'heroes': heroes})
What should I write in views.py to select all heroes with chosen skills?
You probably want to use ManyToManyField Instead.
like this:
# models.py
from django.db import models
class Skill(models.Model):
name = models.CharField(max_length=255)
class Hero(models.Model):
name = models.CharField(max_length=255)
skills = models.ManyToManyField(Skill)
and use forms like this:
# forms.py
from django import forms
from .models import Hero
class HeroForm(forms.ModelForm):
class Meta:
model = Hero
fields = '__all__'
and finally your views:
# views.py
from .models import Hero, Skill
from .forms import HeroForm
def my_heroes(request):
heroes = Hero.objects.all()
return render(request, 'your_template.html', {'heroes':heroes})
def hero_skill_select(request):
if request.method == 'POST':
form = HeroForm(request.POST)
# do something
else:
form = HeroForm()
return render(request, 'template_with_form.html', {'form':form})
Shouldn't the Hero model have Skill as foreignfield, rather than the opposite? I don't understand the logic behind your classes.
Based on your current Classes and their relationship, you could do something like this:
chosen_skills = Skill.objects.values('hero').distinct().annotate(skill='name', hero_name='hero__name')
Haven't tested it, but basically, for every distinct hero, it returns the skill and the name. Let me know if this helps.
Related
So this is the scenario. I allow my user to first input their vehicle brand with one form and then use another form to list down the models available for that vehicle brand. The information on the vehicles and the brands is stored in my database.
Refer to this image to get a better idea:
And this is my views.py:
def driver_dashboard_trip_brand (request, brand):
if request.method == "POST":
form = AddVehicleForm(request.POST)
else:
form = AddVehicleForm()
brands = VehicleBrand.objects.all()
context = {
"form":form,
"brands":brands,
"chosen_brand":brand
}
return render (request, "app/driver_dashboard.html", context)
And my forms.py:
class AddVehicleForm(forms.ModelForm):
model = forms.ModelChoiceField(queryset=VehicleModel.objects.all())
vehicle_colour = forms.ChoiceField(choices=COLOURS)
vehicle_number = forms.CharField(max_length=8, widget=forms.TextInput(attrs={'placeholder': 'eg: CAB-1234'}))
class Meta:
model = Vehicle
fields = ['model', 'vehicle_colour', 'vehicle_number']
So in order to set a query in the forms.py, I would first need to send the data from views.py to forms.py, and then I also need to do a query.
So my question is how can I query for all the car models from the VehicleModel database and create choices attribute for the form, once the user chooses the car brand.
My models.py...
class VehicleModel (models.Model):
brand = models.ForeignKey(VehicleBrand, on_delete=models.CASCADE)
model = models.CharField(max_length=30)
def __str__ (self):
return f"{self.brand} - {self.model}"
Its honestly not so hard, i kinda figured it out...
So this is my forms.py...
class AddVehicleForm(forms.ModelForm):
def __init__(self, brand=None, *args, **kwargs):
super(AddVehicleForm, self).__init__(*args, **kwargs)
self.fields['model'].queryset = VehicleModel.objects.filter(brand=brand)
model = forms.ModelChoiceField(queryset=VehicleModel.objects.all())
vehicle_colour = forms.ChoiceField(choices=COLOURS)
vehicle_number = forms.CharField(max_length=8, widget=forms.TextInput(attrs={'placeholder': 'eg: CAB-1234'}))
class Meta:
model = Vehicle
fields = ['model', 'vehicle_colour', 'vehicle_number']
class AddVehicleFormPost(forms.ModelForm):
model = forms.ModelChoiceField(queryset=VehicleModel.objects.all())
vehicle_colour = forms.ChoiceField(choices=COLOURS)
vehicle_number = forms.CharField(max_length=8, widget=forms.TextInput(attrs={'placeholder': 'eg: CAB-1234'}))
class Meta:
model = Vehicle
fields = ['model', 'vehicle_colour', 'vehicle_number']
Where the form AddVehicleForm allowed me to send the parameter as shown by typing form = AddVehicleForm(VehicleBrand.objects.filter(brand=brand).first()) in my views.py, but then when I wanted to save my form I needed to create another form in the forms.py without taking any query which is shown in AddVehicleFormPost.
Then i casually did,
if request.method == "POST":
form = AddVehicleFormPost(request.POST)
if form.is_valid():
In my views.py...
Here you have a nice tutorial on how to create dependent fields, you need to understand what's going on on the Server, and what's going on on the Client
I am trying to select all class for a user and then load all of the classes objects that are corresponding. Here is my model.py file:
from django.db import models
from django.contrib.auth.models import User
class Class(models.Model):
name = models.CharField(max_length=150)
description = models.TextField()
teacher = models.ForeignKey(User)
class UserClasses(models.Model):
class_name = models.ForeignKey(Class)
user = models.ForeignKey(User)
And here is the call i'm making:
def index(request):
#grab all classes for a user
users_classes = UserClasses.objects.filter(user=request.user)
#pass the array of class objects and get their info
classes = Class.objects.select_related(self=users_classes)
context_dict = {}
return render(request, 'dashboard/index.html', context_dict)
How can I achieve the above?
You can do
users_classes = UserClasses.objects.filter(user=request.user)
classes = Class.objects.filter(class_name__in=users_classes)
Now classes objects contains all class which user belongs to.
I still cant seem to put a simple program together. I am thinking of a simple program where my coworkers and I could propose a bet with each other. (example: I bet the detriot Lions dont win another game this season) If someone is feeling up to the task of taking that bet they can just hit an accept button. I want the user to be logged in and upon submitting the bet_name and bet_desc of the bet, their username, bet_name, bet_desc, and timestamp is saved to a table. Then a relationship table would save the bet id, win, tie, created_user_id, accepted_user_id, accepted_timestamp, and cancelled. Then userprofile table to keep their username, wins, losses, ties, bets_made, and bets_accepted.
models.py
from django.db import models
from django.contrib.auth.models import User
from datetime import datetime
class UserProfiles(models.Model):
username = models.OneToOneField(User)
wins = models.PositiveIntegerField(default=0)
losses = models.PositiveIntegerField(default=0)
ties = models.PositiveIntegerField(default=0)
bets_made = models.PositiveIntegerField(default=0)
bets_accepted = models.PositiveIntegerField(default=0)
def __str__(self):
return "%s's profile" % self.username
class Bets2(models.Model):
bet_name = models.CharField(max_length=30)
bet_desc = models.CharField(max_length=300)
timestamp = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
created_user = models.OneToOneField(UserProfiles, primary_key=True)
accepted_user = models.PositiveIntegerField(default=0)
accepted_timestamp = models.DateTimeField(auto_now=True)
win = models.BooleanField(default=True)
tie = models.BooleanField(default=True)
cancelled = models.BooleanField(default=True)
def __str__(self):
return "%s's profile" % self.bet_name
As far as forms.py and views this is all i have so far:
forms.py
from django import forms
from django.core.exceptions import ValidationError
from .models import Bets2, UserProfiles
class BetForm(forms.ModelForm):
class Meta:
model = Bets2
fields = ['bet_name', 'bet_desc',]
def clean_name(self):
bet_name = self.cleaned_data.get('bet_name')
#write code here
return name
def clean_bet(self):
bet_desc = self.cleaned_data.get('bet_desc')
#write code here
return bet
views.py
from django.shortcuts import render
from django.conf import settings
from .forms import BetForm
from .models import Bets2, UserProfiles
def home(request):
title = "2015 Boardbets"
queryset = Bets2.objects.all().order_by('timestamp')
queryuser = UserProfiles.objects.all()
context = {
"title": title,
"queryset" : queryset,
"queryuser" : queryuser,
}
return render(request, "home.html", context)
def boardbet(request):
form = BetForm(request.POST or None)
bet_variables = Bets2.objects.all()
context = {
"form" : form,
"bet_variables" : bet_variables,
}
if form.is_valid():
form.save()
return render(request, "bets.html", context)
This is where i get stumped, i dont know how to incorporate the other two models into the view so that all three tables get created and also how to reference them in the template.
Edit: changed it to one model for Bets
I want to get specialization count for all the doctors and want to show it in the admin panel
Here are the models
class Doctor(models.Model):
name = models.CharField(max_length=1300)
specialization = models.ForeignKey(Specialization)
clinic = models.ForeignKey(Clinic)
class Specialization(models.Model):
name = models.CharField(max_length=30)
For instance, I want to show like:
Dermatologist: 10
Ophthalmologist: 15
I'm very new to Django and have no clue on how to go about it.
Don't use obj.doctor_set.count() recipe. This method will be called for each Specialization record.
Use single SQL query with aggregation:
# admin.py
from django.contrib import admin
from django.db.models import Count
from app.models import Specialization
class SpecializationAdmin(admin.ModelAdmin):
list_display = ['name', 'doctor_count_display']
def get_queryset(self, request):
qs = super(SpecializationAdmin, self).get_queryset(request)
return qs.annotate(doctor_count=Count('doctor')).order_by('-doctor_count')
def doctor_count_display(self, obj):
return obj.doctor_count
doctor_count_display.short_description = 'Number of doctors'
doctor_count_display.admin_order_field = 'doctor_count'
admin.site.register(Specialization, SpecializationAdmin)
you can accomplish this in this way for example:
#admin.py
class SpecializationAdmin(admin.ModelAdmin):
list_display = ('get_count',)
def get_count(self, obj):
return u"{}: {}".format(obj.name, obj.doctor_set.count())
get_count.short_description = "Number of Doctors"
and register this like:
# also in admin.py
admin.site.register(Specialization, SpecializationAdmin)
dont forget to import Specialization model into admin.py
You need to understand about queries Django Queries
To show the number of dermatologist:
Doctor.objects.filter(specialization__name="Dermatologist").count()
To show the number of ophthalmologist
Doctor.objects.filter(specialization__name="Ophthalmologist").count()
I'm making a game link site, where users can post links to their
favorite web game.
When people post games they are supposed to check what category the
game falls into.
I decided to allow many categories for each game since some games can
fall into many categories.
So the question is, how do I handle this in my view?
And how can I show it as Checkboxes, where at least one has to be
checked?
And how can I show this as checkboxes in the Admin as well?
Here is the code
Models:
class Category(models.Model):
category = models.CharField(max_length=200)
def __unicode__(self):
return self.category
class Game(models.Model):
name = models.CharField(max_length=200)
url = models.CharField(max_length=200)
poster = models.ForeignKey(User, related_name='game_poster_set')
postdate = models.DateTimeField(default=datetime.now)
cats = models.ManyToManyField(Category)
hits = models.IntegerField(default=0)
post = models.BooleanField(default=False)
Views:
def submit(request):
form = GameForm(request.POST or None)
if form.is_valid():
game = form.save(commit=False)
game.poster = request.user
game.save()
next = reverse('gamesite.games.views.favorites')
return HttpResponseRedirect(next)
return render_to_response(
'games/submit.html',
{'form': form},
context_instance = RequestContext(request),)
Forms:
class GameForm(forms.ModelForm):
name = forms.CharField(max_length=15, label='Name')
url = forms.URLField(label='URL', initial='http://')
class Meta:
model = Game
fields = ('name','url')
Thanks!
class GameForm(forms.ModelForm):
name = forms.CharField(max_length=15, label='Name')
url = forms.URLField(label='URL', initial='http://')
cats = forms.ModelMultipleChoiceField(
queryset=Category.objects.all(),
widget=forms.CheckboxSelectMultiple,
required=True)
class Meta:
model = Game
fields = ('name','url','cats')
that should fix your view, but i'm not sure about the admin. still looking... will edit if i find anything.
Here is how I solved it (Edit: and the admin thing)
Forms:
cats = forms.ModelMultipleChoiceField(widget=forms.CheckboxSelectMultiple, queryset=Category.objects.all())
(It was the queryset part I couldn't find..)
View:
cats = form.cleaned_data['cats']
game.cats = cats
And that's all the code needed to save the data.
Edit:
here is a solution for the admin
Models:
from django.contrib import admin
from django.forms import CheckboxSelectMultiple
class MyModelAdmin(admin.ModelAdmin):
formfield_overrides = {
models.ManyToManyField: {'widget': CheckboxSelectMultiple},
}
Admin:
from gamesite.games.models import Game, MyModelAdmin
admin.site.register(Game, MyModelAdmin)
It's kind of quirky in looks, but works!
If someone finds a way to make it more "clean" please post!
Cheers!
Found this on from Chase Seibert, Engineering Manager of Dropbox
Source from Chase Seibert
from django.db import models
from django.forms.models import ModelForm
from django.forms.widgets import CheckboxSelectMultiple
class Company(models.Model):
industries = models.ManyToManyField(Industry, blank=True, null=True)
class CompanyForm(ModelForm):
class Meta:
model = Company
fields = ("industries")
def __init__(self, *args, **kwargs):
super(CompanyForm, self).__init__(*args, **kwargs)
self.fields["industries"].widget = CheckboxSelectMultiple()
self.fields["industries"].queryset = Industry.objects.all()