So I have been following this tutorial related to dependent dropdowns which can be found here and I seem to have gotten stuck at the last part the else if statement and am unable to implement the same in my project
postlog models.py:
from django.db import models
# Create your models here.
class FlightNum(models.Model):
fl_no =models.CharField(max_length=5,primary_key=True)
def __str__(self):
return self.fl_no
class Destination(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl1')
dest= models.CharField(max_length=15,blank=True)
def __str__(self):
return self.dest
class Parking(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl2')
park_bay= models.CharField(max_length=3)
def __str__(self):
return self.park_bay
class DepartureTime(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fl3')
dep_time= models.CharField(max_length=9)
def __str__(self):
return self.dep_time
class Flight(models.Model):
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE, primary_key=True, related_name='fl4')
park_bay= models.ForeignKey(Parking, on_delete=models.CASCADE)
dest= models.ForeignKey(Destination, on_delete=models.CASCADE)
dep_time= models.ForeignKey(DepartureTime, on_delete=models.CASCADE)
inbound= models.CharField(max_length=15,blank=True)
airline= models.CharField(max_length=15)
arr_time= models.TimeField()
status models.py:
from django.db import models
from postlog.models import FlightNum,Destination,Parking,DepartureTime
# Create your models here.
class FlightStatus(models.Model):
CLEANING_CHOICES = (
('Yes', 'Yes'),
('No','No'),
)
fl_no= models.OneToOneField(FlightNum,on_delete=models.CASCADE,related_name='fli_no',primary_key=True)
park_bay= models.ForeignKey(Parking,on_delete=models.CASCADE,related_name='parki_bay')
catering= models.CharField(max_length=9)
fuel= models.IntegerField()
pas_cnt= models.IntegerField()
dest= models.ForeignKey(Destination,on_delete=models.CASCADE,related_name='desti',null=True)
dep_time=models.ForeignKey(DepartureTime,on_delete=models.CASCADE,related_name='dept_time')
Cleaning = models.CharField( max_length=3, choices=CLEANING_CHOICES)
status forms.py:
from django.forms import ModelForm
from status.models import FlightStatus
from postlog.models import FlightNum,Destination,Parking,DepartureTime
class StatusForm(ModelForm):
class Meta:
model = FlightStatus
fields = ('fl_no', 'park_bay', 'catering', 'fuel', 'pas_cnt', 'dest','dep_time', 'Cleaning')
labels = {
'fl_no': ('Flight Number'),
'park_bay': ('Parking Bay'),
'catering': ('Catering'),
'fuel': ('Fuel'),
'pas_cnt': ('Passenger Count'),
'dest': ('Destination'),
'dep_time': ('Departure Time'),
'Cleaning': ('Cleaning'),
}
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.fields['park_bay'].queryset = Parking.objects.none()
self.fields['dest'].queryset = Destination.objects.none()
self.fields['dep_time'].queryset = DepartureTime.objects.none()
if 'fl_no' in self.data:
try:
flightid = int(self.data.get('fl_no'))
self.fields['park_bay'].queryset = Parking.objects.filter(fl_no=flightid).order_by('park_bay')
self.fields['dest'].queryset = Destination.objects.filter(fl_no=flightid).order_by('dest')
self.fields['dep_time'].queryset = DepartureTime.objects.filter(fl_no=flightid).order_by('dep_time')
except (ValueError, TypeError):
pass
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.park_bay_set.order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.park_bay_set.order_by('dep_time')
so if anyone could help me fix this part:
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.park_bay_set.order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.dep_time_set.order_by('dep_time')
I would really appreciate it
The error says there's no park_bay_set attribute for FlightNum, because you specified related_name='fl4' for your fl_no field inside your Flight model. Also, up to this point you are in a Flight instance, so you need one more relation to reach the park bays. Your status forms.py should be like this:
elif self.instance.pk:
self.fields['park_bay'].querysets = self.instance.fl_no.fl4.park_bay.all().order_by('park_bay')
self.fields['dest'].querysets = self.instance.fl_no.dest_set.order_by('dest')
self.fields['dep_time'].querysets = self.instance.fl_no.fl4.park_bay.all().order_by('dep_time')
Here's a diagram of how your models are currently related, not sure if this is exactly what you want, you might want to take a look and see if a normalization is needed.
Related
I'm trying to add custom field to the actor admin panel to show the movie counts each contributed in
admin panel..
from django.contrib import admin
from actors.models import Actor
#admin.register(Actor)
class ActorAdmin(admin.ModelAdmin):
search_fields = ('actor_name',)
list_filter = ('gender',)
list_display = ['actor_name', 'age', 'gender', 'movies_count']
readonly_fields = ['movies_count']
def movies_count(self, obj):
count = 0
for mv in Actor.objects.raw('select * from movies_movie_actors '
'where actor_id='
'(select id from actors_actor where actor_name="%s")', [obj]):
count += 1
return str(count)
movies_count.short_description = 'movie count'
but I get error
Exception Type: ProgrammingError
Exception Value: can't adapt type 'Actor'
what does the error mean, why is it show and how to solve it (different approach with the same goal is acceptable)
maybe relevant
actor model :
from django.db import models
GENDER_LIST = [('male', 'male'), ('female', 'female')]
class Actor(models.Model):
actor_name = models.fields.CharField(verbose_name='Name', max_length=25, unique=True)
gender = models.CharField(verbose_name='Gender', choices=GENDER_LIST, max_length=6, default='male')
age = models.IntegerField(default=0)
create_time = models.TimeField(verbose_name='Created at', auto_now=True)
update_time = models.TimeField(verbose_name='Updated at', auto_now=True)
def __str__(self):
return f'{self.actor_name}'
movies model :
from django.db import models
from django.db.models import CASCADE
from director.models import Director
class Movie(models.Model):
movie_name = models.fields.CharField(verbose_name='movie name', max_length=25, unique=True)
production_year = models.IntegerField(verbose_name='production year')
actors = models.ManyToManyField('actors.actor')
director = models.ForeignKey(Director, on_delete=CASCADE, related_name='movies')
create_time = models.TimeField(verbose_name='Created at', auto_now=True)
update_time = models.TimeField(verbose_name='Updated at', auto_now=True)
def __str__(self):
return f'{self.movie_name}'
def __unicode__(self):
return u'%s' % self.director.director_name
I found a way to reach the same goal (get movie count for each actor he/she contributed at) by using count() built in function with __set
def movies_count(self, obj):
return obj.movie_set.count()
but the question still rise what does can't adapt type exception means?! and why it happens with the raw query?!
For example, I have three Models in django:
class Car(models.Models):
range = models.DecimalField()
speed = models.DecimalField()
def __str__(self):
return self.speed
class Group_of_Cars(models.Models):
name = models.CharField()
starting_city = models. CharField()
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Arrival_time(models.Models):
Location_of_ArrivalPoint = models.CharField()
Last_known_location_of_CarGroup = models.CharField()
Group_of_Cars = models.ForeignKey(Group_of_Cars)
def function(self):
"Get speed of the "Car" in "Group_of_Cars"
def __str__(self):
return self. Location_of_ArrivalPoint
This is an example of what I want to do, not my actual models. The idea is for the user to input a series of values for the type of "Cars" such as speed and range. I'd like "Cars" to be selected when defining parameters for "a Group_of_Cars". What I'm not sure how to do is how to get the speed of the car, for the Group_of_Cars for which I need to calculate an arrival time (Group_of_Cars consists of one type of car and I'd like 'Arrival_time' to be its own table).
Thank you for any input.
models.py
from django.db import models
# Create your models here.
class Car(models.Model):
range = models.DecimalField(decimal_places=2,max_digits=5)
speed = models.DecimalField(decimal_places=2,max_digits=5)
def __str__(self):
return str(self.speed)
class Group_of_Cars(models.Model):
name = models.CharField(max_length=50)
starting_city = models. CharField(max_length=50)
car = models.ManyToManyField(Car)
def __str__(self):
return self.name
class Arrival_time(models.Model):
Location_of_ArrivalPoint = models.CharField(max_length=50)
Last_known_location_of_CarGroup = models.CharField(max_length=50)
Group_of_Cars = models.ForeignKey(Group_of_Cars, on_delete=models.CASCADE)
def function(self):
# "Get speed of the "Car" in "Group_of_Cars"
return self.Group_of_Cars.car.all()
def __str__(self):
return self. Location_of_ArrivalPoint
In views.py
from django.shortcuts import render
from core.models import Arrival_time
from django.http import HttpResponse
# Create your views here.
def home(request):
arp = Arrival_time.objects.get(Location_of_ArrivalPoint='Newyork')
for i in arp.function():
print(i)
return HttpResponse()
I have made a Django model form but the problem is in my logic I am using something else and now I want to figure out a way to validate it by either defining a Meta class and choosing the fields that I want to display to the user but of course this won't validate the form.
Now I want to know if there is a way to validate the form without touching the models and pass the data required for the logic and after take care of the information needed for the data of the model to be saved.
Here is the models:
from django.db import models
from django.db import models
from django.contrib.auth.models import User
# Create your models here.
class RoomCategory(models.Model):
name = models.CharField(max_length=59)
price = models.IntegerField()
beds = models.PositiveIntegerField()
capacity = models.PositiveIntegerField()
size = models.CharField(max_length=59)
def __str__(self):
return self.name
class Room(models.Model):
room_number = models.CharField(max_length=60)
room_category = models.ForeignKey(RoomCategory, on_delete=models.CASCADE)
def __str__(self):
return f"The room {self.room_number} {self.room_category} has a maximum of {self.room_category.capacity} person and cost {self.room_category.price}/night "
class Booking(models.Model):
customer = models.ForeignKey(User, on_delete=models.CASCADE)
room = models.ForeignKey(RoomCategory, on_delete=models.CASCADE)
check_in = models.DateField()
check_out = models.DateField()
adults = models.PositiveSmallIntegerField()
children = models.PositiveSmallIntegerField()
def __str__(self):
return f"{self.customer} has booked for {self.room} from {self.check_in} to {self.check_out}"
Here is the form:
class BookingForm(forms.ModelForm):
class Meta:
model = Booking
fields = ['room', 'check_in', 'check_out', 'adults', 'children']
here is the views.py
data = form.cleaned_data
roomlist = Room.objects.filter(room_category__name=data['room'])
available_rooms = []
for room in roomlist:
if data['adults'] + data['children'] > room.room_category.capacity:
return HttpResponse(f'Sorry !! But this category of room cannot handle more than {room.room_category.capacity}')
else:
if check_availability(room.room_category.name, data['check_in'], data['check_out'], data['adults'], data['children']):
available_rooms.append(room)
if len(available_rooms) > 0:
room = available_rooms[0]
new_booking = Booking.objects.create(
customer=self.request.user,
room=room,
check_in=data['check_in'],
check_out=data['check_out'],
adults=data['adults'],
children=data['children']
)
new_booking.save()
return HttpResponse(new_booking)
else:
return HttpResponse('All the rooms of this type are not available')
It is not printing the data means that the form is not valid and it fall down to the else statement.
You can validate any field in the form by writing a method in this way : def clean_(field_name) i.e def clean_room(self) read more:
https://docs.djangoproject.com/en/3.1/ref/forms/validation/#cleaning-a-specific-field-attribute
I have an app in two different models, The error is 'cannot import name sku', which i believe is because of a circular import. How can I still reference this app.model without referencing the model import the way I am currently.
Model PurchaseOrderDetail
App Purchase_order
from product.models import InventoryTransaction
class PurchaseOrderDetail(AuditMixin, models.Model):
purchase_order = models.ForeignKey(PurchaseOrder,
on_delete=models.PROTECT)
sku = models.ForeignKey(Sku, on_delete=models.PROTECT)
qty_received = models.IntegerField(default=0, null=True, blank=True)
reason_code = models.IntegerField(default=0, null=True, blank=True)
def _get_sku_code(self):
return self.sku.sku_code
def _set_sku_code(self, value):
tenant = self.purchase_order.tenant
sku = Sku.objects.get(tenant=tenant, sku_code=value)
self.sku = sku
sku_code = property(_get_sku_code, _set_sku_code)
def calc_received(self):
# calculate sum of qty_received from inventory_transactions
sum_quantity = InventoryTransaction.objects.filter(
sku=self.sku,
po_number=self.purchase_order,
transaction_type='100'
).aggregate(
quantity_sum=Sum(F('quantity'))
)
return sum_quantity
Model Inventorytransaction
app Product
from purchase_order.models import PurchaseOrderDetail
class InventoryTransaction(models.Model):
tenant = models.ForeignKey(Tenant)
po_number = models.CharField(max_length=100)
inventory_transaction = models.ForeignKey(PurchaseOrderInventoryTransaction)
def save(self, *args, **kwargs):
super().save(*args, **kwargs)
# update the PO detail with the qty_received
obj = PurchaseOrderDetail.objects.get(
purchase_order=self.po_number,
sku=self.inventory_transaction.sku
)
obj.qty_received = obj.calc_received()
obj.save()
If you don't want this problem to appear, simply import your PurchaseOrderDetails inside your def save function.
def save(self, *args, **kwargs):
from purchase_order.models import PurchaseOrderDetail
...
I am trying to use the ModelForm to add my data. It is working well, except that the ForeignKey dropdown list is showing all values and I only want it to display the values that a pertinent for the logged in user.
Here is my model for ExcludedDate, the record I want to add:
class ExcludedDate(models.Model):
date = models.DateTimeField()
reason = models.CharField(max_length=50)
user = models.ForeignKey(User)
category = models.ForeignKey(Category)
recurring = models.ForeignKey(RecurringExclusion)
def __unicode__(self):
return self.reason
Here is the model for the category, which is the table containing the relationship that I'd like to limit by user:
class Category(models.Model):
name = models.CharField(max_length=50)
user = models.ForeignKey(User, unique=False)
def __unicode__(self):
return self.name
And finally, the form code:
class ExcludedDateForm(ModelForm):
class Meta:
model = models.ExcludedDate
exclude = ('user', 'recurring',)
How do I get the form to display only the subset of categories where category.user equals the logged in user?
You can customize your form in init
class ExcludedDateForm(ModelForm):
class Meta:
model = models.ExcludedDate
exclude = ('user', 'recurring',)
def __init__(self, user=None, **kwargs):
super(ExcludedDateForm, self).__init__(**kwargs)
if user:
self.fields['category'].queryset = models.Category.objects.filter(user=user)
And in views, when constructing your form, besides the standard form params, you'll specify also the current user:
form = ExcludedDateForm(user=request.user)
Here example:
models.py
class someData(models.Model):
name = models.CharField(max_length=100,verbose_name="some value")
class testKey(models.Model):
name = models.CharField(max_length=100,verbose_name="some value")
tst = models.ForeignKey(someData)
class testForm(forms.ModelForm):
class Meta:
model = testKey
views.py
...
....
....
mform = testForm()
mform.fields["tst"] = models.forms.ModelMultipleChoiceField(queryset=someData.objects.filter(name__icontains="1"))
...
...
Or u can try something like this:
class testForm(forms.ModelForm):
class Meta:
model = testKey
def __init__(self,*args,**kwargs):
super (testForm,self ).__init__(*args,**kwargs)
self.fields['tst'].queryset = someData.objects.filter(name__icontains="1")
I know this is old; but its one of the first Google search results so I thought I would add how I found to do it.
class CustomModelFilter(forms.ModelChoiceField):
def label_from_instance(self, obj):
return "%s %s" % (obj.column1, obj.column2)
class CustomForm(ModelForm):
model_to_filter = CustomModelFilter(queryset=CustomModel.objects.filter(active=1))
class Meta:
model = CustomModel
fields = ['model_to_filter', 'field1', 'field2']
Where 'model_to_filter' is a ForiegnKey of the "CustomModel" model
Why I like this method:
in the "CustomModelFilter" you can also change the default way that the Model object is displayed in the ChoiceField that is created, as I've done above.
is the best answer:
BookDemoForm.base_fields['location'] = forms.ModelChoiceField(widget=forms.Select(attrs={'class': 'form-control select2'}),queryset=Location.objects.filter(location_for__fuel=True))