Django Object Names , can't compare values - django

the problem about 2 things ; First of all in admin panel and webpage foreign keys are shown as object(1) ,Yes I know the solution of this we use str stuff but when I try to compare id of them it takes the value of str function result let me show in code;
Im checking logged in user's connected company id that equals to only students who are connected with same company
model.py - Student
class Student(models.Model):
id = models.AutoField(primary_key=True, verbose_name='StudentID')
parentid = models.ForeignKey(Parent, on_delete=models.CASCADE, verbose_name='ParentID')
companyid = models.ForeignKey(Company, on_delete=models.CASCADE, verbose_name='CompanyID')
classid = models.ForeignKey(Classes, on_delete=models.CASCADE, verbose_name='ClassID')
gender = models.CharField(max_length=1, default='N', verbose_name='Gender')
name = models.CharField(max_length=30, verbose_name='Name')
surname = models.CharField(max_length=30, verbose_name='Surname')
dob = models.DateTimeField(verbose_name='Doğum Yılı')
bloodtype = models.ForeignKey(BloodType, on_delete=models.CASCADE, verbose_name='Blood Type')
status = models.BooleanField(verbose_name='State')
list_display = ('id', 'parentid', 'companyid', 'classid', 'gender', 'name', 'surname', 'dob', 'bloodtype', 'status')
def __str__(self):
return "%s %s - %s" % (self.name, self.surname, self.gender)
model.py - Company
class Company(models.Model):
id = models.AutoField(primary_key=True, verbose_name='CompanyID')
name = models.CharField(
max_length=100, verbose_name='Company Name')
contactname = models.CharField(max_length=30)
contactsurname = models.CharField(
max_length=30)
address = models.CharField(max_length=200)
city = models.CharField(max_length=20)
phone = models.CharField(max_length=12)
weburl = models.URLField(max_length=80)
email = models.CharField(max_length=80)
studentcapacity = models.BigIntegerField(verbose_name='Student Capacity')
classcapacity = models.BigIntegerField(verbose_name='Class Capacity')
notes = models.TextField(max_length=200)
status = models.BooleanField(verbose_name='State')
list_display = ('id', 'name', 'contactname', 'contactsurname', 'address', 'city', 'phone',
'weburl', 'email', 'studentcapacity', 'classcapacity', 'notes', 'status')
def __str__(self):
return "%s - %s" % (self.id, self.name)
views.py
#login_required()
def student_update(request, pk):
student = get_object_or_404(Student, pk=pk)
usercompanyid = UserProfile.objects.filter(userid=request.user.id).only('companyid')
print('before control')
a = usercompanyid.values_list('companyid', flat=True)[0]
print(a)
print(student.companyid)
if student.companyid == a:
print('passed if')
if request.method == 'POST':
form = StudentForm(request.POST, instance=student)
else:
form = StudentForm(instance=student)
return save_student_form(request, form, 'student_update_partial.html')
else:
return view_404(request)
at if state " student.companyid == a: " = Company ID - Company Name , output: 1 -Test CompanyName = 1 , I need it to return only field I call which is companyid, I know it is allias to "companyID - companyName". Is it possible to fix this with another way , I'm not pro of django python , just trying to do some project for learning if it's a dump question sorry for all :)

When you do this:
companyid = models.ForeignKey(...)
The database schema would actually have a field name of companyid_id.
So in your case, if you want to compare object IDs then you actually need to do this:
if student.companyid_id == a:
To avoid confusion, I would advise you not to append the 'id' part to your Django model field names.

There's a lot of unnecessary messing around with only and values here. No need for any of that. Just compare the objects directly:
def student_update(request, pk):
student = get_object_or_404(Student, pk=pk)
if student.companyid == request.userprofile.companyid:
...
As an aside, you shouldn't call your foreign keys "companyid", "parentid" etc; they're not IDs, they're objects. Call them "company", "parent" etc.

Related

Django ValueError: Cannot assign * must be a * instance

I am getting this error but I don't know why.
models.py
class Year(models.Model):
year = models.CharField(max_length=5, unique=True)
class Meta:
ordering = ['-year']
def __str__(self):
return self.year
class Photo(models.Model):
title = models.CharField(max_length=64)
description = models.CharField(max_length=255)
created = models.DateTimeField(auto_now_add=True)
image = models.ImageField(upload_to='photos/')
thumbnail = ResizedImageField(blank=True, size=[360, 360], force_format='JPEG', upload_to='thumbnails/')
submitter = models.ForeignKey(get_user_model(), on_delete=models.CASCADE)
year = models.ForeignKey(Year, blank=True, on_delete=models.CASCADE)
views.py
def photo_create_view(request):
form = AddPhotoForm()
if request.method == 'POST':
image = request.FILES['image']
thumbnail = request.FILES['image']
title = request.POST.get('title')
description = request.POST.get('description')
year = request.POST.get('year')
people = request.POST.get('people')
tags = request.POST.get('tags')
photo = Photo(image=image, thumbnail=thumbnail, title=title, description=description, year=year,
people=people, tags=tags, submitter=request.user,)
photo.save()
return redirect('/photo/?page=1')
return render(request, 'photoapp/create.html', context={'form':form})
Cannot assign "123": "Photo.year" must be a "Year" instance. I have checked the Year table and year.id 123 exists. What am I missing?
year_id = int(request.POST.get('year'))
Photo(year_id=year_id, ...)
It's got to be the physical Year object
year = Year.objects.get_or_create(year=request.POST.get('year'))
Notes:
You could also use .get() or .filter().first(), must be the object and not a QuerySet
If you use a form you can get away with just the Pk in the request.POST
My own two sense: I don't think there's a benefit of having Year as it's own table, but maybe you're just using placeholders

Filtering output of foreign key data

Since I am making a online futsal booking system, i am currently doing timeslot validation. If a timeslot is already booked, the user should not be able to book that timeslot again.
models.py
class futsals(models.Model):
futsal_name = models.CharField(max_length=20)
futsal_address = models.CharField(max_length=40)
owner_email = models.EmailField(max_length=25)
owner_name = models.CharField(max_length=25)
def __str__(self):
return f'{self.futsal_name}'
class timeslot(models.Model):
timesslot = models.CharField(max_length=15)
name = models.CharField(max_length=15)
def __str__(self):
return f'{self.timesslot}'
class Booking(models.Model):
user_book = models.ForeignKey(User, on_delete=models.CASCADE)
futsal = models.ForeignKey(futsals, on_delete=models.CASCADE)
time_slot = models.ForeignKey(timeslot, on_delete=models.CASCADE)
def validate_date(date):
if date < timezone.now().date():
raise ValidationError("Date cannot be in the past")
booking_date = models.DateField( default=None, validators=[validate_date])
def __str__(self):
return f'{self.user_book}'
forms.py
def timeslot_validation(value):
v = Booking.objects.all().values_list('time_slot')
k = timeslot.objects.filter(pk__in=v)
if value == k:
raise forms.ValidationError("This timeslot is already booked!!")
else:
return value
But I am not able to do the validation. Since the output of variable 'k' looks like:
<QuerySet [<timeslot: 19:00 - 20:00>, <timeslot: 18:00 - 19:00>, <timeslot: 17:00 - 18:00>]>
The above shown timeslot is the timeslot booked by users. Now if another user enters this timeslot, it should show 'this timeslot is already booked.'
Now, I want this data to be shown as
[(19:00 - 20:00), (18:00 - 19:00), (17:00 - 18:00)]
Any help would be appreciated, or if anyone could provides me a better solution for validation?
You can add a unique constraint to the time_slot and booking_date field and your ModelForm will handle validating that the time_slot and booking_date is unique
class Booking(models.Model):
class Meta:
unique_together = (
('booking_date', 'time_slot'),
)

How to send info in URL?

I am trying to create a product filter.
I am sending the user choice in URL
if the user select size = L then using request.GET
I am receiving:
{'size': ['L']}
But I want to receive: {'size':{'op':'in','attri':'L'}}
Is this possible?
Please help
my models are
class ProductAttribute(models.Model):
slug = models.SlugField(max_length=50, unique=True)
name = models.CharField(max_length=100)
op = models.CharField(max_length=20,default='in')
class Meta:
ordering = ('slug', )
def __str__(self):
return self.name
def get_formfield_name(self):
return slugify('attribute-%s' % self.slug, allow_unicode=True)
def has_values(self):
return self.values.exists()
class AttributeChoiceValue(models.Model):
name = models.CharField(max_length=100)
slug = models.SlugField(max_length=100)
attribute = models.ForeignKey(
ProductAttribute, related_name='values', on_delete=models.CASCADE)
class Meta:
unique_together = ('name', 'attribute')
def __str__(self):
return self.name
class Product(models.Model):
name = models.CharField(max_length=128)
attributes = HStoreField(default={})
q2 = AttributeChoiceValue.objects.filter(attribute__name='size')
My size filter(filter.py) is:
size = django_filters.ModelMultipleChoiceFilter(queryset=q2.values_list('name', flat=True).distinct(),widget=forms.CheckboxSelectMultiple)
I am currently using the following query to filter my database in views.py
result = Product.objects.all()
for key, value in request.GET:result = result.filter(**{'attributes__{}__in'.format(key): value})
I want to make it
a=request.GET
for key, value in a:
result = result.filter(**{'attributes__{}__{}'.format(key,a['op']): value})
so that if I even use Price range as filter my query filter accordingly will be
attributes__price__range
You can send info to your views via "path converters":
https://docs.djangoproject.com/en/2.0/topics/http/urls/#path-converters
Or using regular expressions:
https://docs.djangoproject.com/en/2.0/topics/http/urls/#using-regular-expressions

Drop-down dependency using Django and Python

im still new in using django and python.. I am working on a drop-down dependency in HWname and HWType. I tried many codes but they didn't worked.. Here are my codes. Please help me :)
What I want to happen is for example in HWType I have Flexi and Flexi2, then in HWName I have Female and Male .. If I choose Flexi in HWType, only "Female" will be display in my HWName and If I choose Flexi2, HWName will display "Male" ..
Models.Py (Codes)
class HWName(models.Model):
hwnid = models.AutoField(max_length=6, primary_key=True, db_column='id')
hwnname = models.CharField(max_length=255, db_column='name')
class Meta:
db_table=u'hw_name'
def __unicode__(self):
return unicode((self.hwnname))
class HWType(models.Model):
hwtid = models.AutoField(max_length=6, primary_key=True, db_column='id')
hwtname = models.CharField(max_length=255, db_column='name')
class Meta:
db_table=u'hw_type'
def __unicode__(self):
return unicode((self.hwtname))
SCBT Inventory(advance search)
class Inventory (models.Model):
id = models.AutoField(max_length=6, primary_key=True, db_column='id')
hwname = models.ForeignKey(HWName, db_column='hw_name', default=1)
hwtype = models.ForeignKey(HWType, db_column='hw_type', default=1)
class Meta:
db_table=u'inventory'
def __unicode__ (self):
return unicode((self.assetnumber, self.serialnumber, self.hwname, self.hwtype))
Advanced Search Hardware Form
class AdvancedSearchForm (ModelForm):
hwname = forms.ModelChoiceField(queryset=HWName.objects.all(), label="Hardware Name")
hwtype = forms.ModelChoiceField(queryset=HWType.objects.all(), label="Hardware Type")
class Meta:
model = Inventory
exclude = ('id', 'assetnumber', 'serialnumber', 'remarks')
Views.Py (Codes)
def inventory (request):
##advanced search form:##
form = AdvancedSearchForm(request.POST or None)
##check if form is not empty##
hwname = request.GET.get('hwname', 0)
hwtype = request.GET.get('hwtype',0)
if hwname == 'None':
hwname = ''
if hwtype == 'None':
hwtype = ''
try "django-smart-selects"
that looks like what you need
https://github.com/digi604/django-smart-selects

TypeError - expected string or buffer for date field in django when using SelectDateWidget

I have a date field in my model, and I am using SelectDateWidget() to provide the user date selection option. The name of the field is deadline and here is how I set the widget in the model form
widgets = {
'deadline' : SelectDateWidget(),
}
Now the problem is when I submit the form I get the following error
TypeError - expected string or buffer. I did some tweaking and found out that the Datewidget is returning a bool value instead of string.
If I remove the date widget and submit the date normally in YYYY-MM-DD format, everything works fine. Can anybody please help to understand what is actually going wrong here?
Edit: Adding my Model and Model form
class UniData(models.Model):
name = models.CharField(max_length=500)
slug = models.SlugField(blank=True, unique=True)
SCORE_CHOICES = (
(0 , 'Not Sent'),
(1 , 'Sent'),
)
YES_NO = (
(0 , 'NO'),
(1 , 'YES'),
)
Score = models.IntegerField(choices=SCORE_CHOICES, default=0)
creator = models.ForeignKey(User, blank=True, null=True)
deadline = models.DateField(blank=True, null=True)
submitted = models.IntegerField(choices=YES_NO, default=1)
created_date = models.DateTimeField(null = True)
class Meta:
ordering = ('-created_date',)
def __unicode__(self):
return u'%s' %(self.name)
def save(self, *args, **kwargs):
self.slug = slugify(self.universityName)
super(UniData, self).save(*args, **kwargs)
def get_absolute_url(self):
return "/ScoreTracker/%s/" % self.slug
And the model form is
class UniForm(ModelForm):
class Meta:
fields = ['name', 'Score','deadline', 'submitted']
widgets = {
'name': TextInput(attrs={'value':'University Name', 'class':'default-value',}),
'Score': RadioSelect(choices=SCORE_CHOICES),
'submitted': RadioSelect(choices=YES_NO),
'deadline': SelectDateWidget(),
}