Contained by with default ID as a parameter doesn't work - python

I want to check if the id of a page of exercises is inside of an array for solvedExercises. I thought this might be easy to do with a contained_by, but it doesn't work.
I've tried this line (but I also want to randomise the questions)
randomQuestions = Exercises.objects.filter(id__contained_by=(req.user.profile.exercitiiProvocari).order_by("?")
but it doesn't work.
I'm getting this error:
Unsupported lookup 'contained_by' for AutoField or join on the field not permitted, perhaps you meant contains or icontains?
I suppose this error comes from the fact that ID is an auto-generated field by django, but I have no idea how to fix it.
views.py
from django.shortcuts import render
from exercitii.models import Exercises
# Create your views here.
def index(req):
return render(req, "../templates/pagini/provocari.html")
def provocari(req):
randomQuestions = Exercises.objects.filter(id__contained_by=(req.user.profile.exercitiiProvocari).order_by("?")
print(randomQuestions)
return render(req, "../templates/pagini/provocare.html")
Exercitii model
from django.db import models
from django.contrib.postgres.fields import ArrayField
from lectii.models import Lectie
# Create your models here.
class Exercises(models.Model):
idLectie = models.ForeignKey(Lectie, on_delete=models.DO_NOTHING, blank=True, null=True)
intrebare = models.CharField(max_length = 300)
variante = ArrayField(models.CharField(max_length=300), null=True)
variantaCorecta = models.CharField(max_length = 1)
def __str__(self):
return self.intrebare
So what I'm actually doing is to try to make the difference of an array of all exercises with one with the IDs of already solved exercises, and randomising the result.
But when I'm trying to make this difference, I get that error.

Wouldn't a simple in lookup be sufficient for this case?
Assuming req.user.profile.exercitiiProvocari is some kind of array/list/container, you could try something like this:
randomQuestions = Exercises.objects.filter(id__in=req.user.profile.exercitiiProvocari)\
.order_by("?")
To exclude the seem questions, you could try using exclude(). This will return all questions that are NOT in req.user.profile.exercitiiProvocari and they should be in a random order:
randomQuestions = Exercises.objects.exclude(id__in=req.user.profile.exercitiiProvocari)\
.order_by("?")

Related

Stop affecting other objects of Django Many to Many model

I'm trying to replicate Blood Group as Model as defined in this picture.
.
In my models.py file I had my code to replicate the blood groups like this
class BloodGroup(models.Model):
name = models.CharField(
max_length=3
)
gives = models.ManyToManyField("self")
receives = models.ManyToManyField("self")
def __str__(self):
return self.name
And in my admin.py file I had registered the model as follows
class BloodGroupAdmin(admin.ModelAdmin):
model = BloodGroup
list_display = ['name', 'get_gives', 'get_receives']
def get_gives(self, obj):
return ", ".join([item.name for item in obj.gives.all()])
def get_receives(self, obj):
return ", ".join([item.name for item in obj.receives.all()])
admin.site.register(BloodGroup, BloodGroupAdmin)
Initially I created plain BloodGroup objects without their gives and receives attribute by providing just their names alone. Thus I create an object for all 8 types. Then as I added relationships to each object I found that adding gives or receives for one object affects other objects gives and receives too, making it impossible to replicate the structure in image.
How do I define relationships, without affecting other objects?
In my admin site, I see field names as "get_gives" and "get_receives". How would i make the admin page show field names as "gives" and "receives" but still displaying objects as strings like the image below?
For first question, probably it is better to have only one relation gives. receives can be found from the reverse query. Like this:
class BloodGroup(models.Model):
name = models.CharField(
max_length=3
)
gives = models.ManyToManyField("self", related_name="receives", symmetrical=False)
Then you only need to add objects to gives. receives will be generated automatically.
For second question, add short_description attribute to function(reference to docs). Like this:
get_gives.short_description = 'Gives'
get_receives.short_description = 'Receives'

Django model order by custom algorithm Using the difference between the current time and creation time

Django version 2.1.15
Python version 3.7.4
Djngo settings.py
LANGUAGE_CODE = 'ko-kr'
TIME_ZONE = 'Asia/Seoul'
I am not familiar with English.I will write in English as hard as possible.
Django model order by custom algorithm Using the difference between the current time and creation time
my model is
models.py
class Review(models.Model):
title = models.CharField(max_length = 100)
content = models.TextField()
movie = models.ForeignKey(Movie,on_delete=models.CASCADE)
user = models.ForeignKey(settings.AUTH_USER_MODEL,on_delete = models.CASCADE)
like_users=models.ManyToManyField(settings.AUTH_USER_MODEL,related_name='like_reviews')
created_at=models.DateTimeField(auto_now_add=True)
updated_at=models.DateTimeField(auto_now=True)
i want to
Descending order_by (Count(like_users)/(current_time - created_at + 60)) Review model
(current_time-created_at) : I want to change the difference between two hours to minutes. (integer)
I tested these things.
from django.db.models import ExpressionWrapper,F,Value
from django.db.models.fields import DurationField,DateTimeField
def test(request):
now = timezone.localtime()
test = Review.objects.annotate(diff_time=(ExpressionWrapper(Value(now, DateTimeField()) - F('created_at'), output_field=DurationField()))).annotate(diff_value=F('diff_time')+60).values()
But failed.
How can I get the results I want?
I used a translator to ask questions, but I hope my intentions are clearly communicated.
I'm so sorry for my poor English.
You can try something like this:
from django.utils import timezone
from django.db.models import F
Review.objects.annotate(time_since_creation=timezone.now()-F('created_at')).order_by('-time_since_creation')
Wasn't sure which way you wanted to order by but you can play around with the minus sign to get what you want.

How do I add a table limited to only one row in mysql/django?

I'm using Django for a small project and I want to make a table with one row to add the description of the project in it. I only need one row and nothing more since it's one description for the whole site and I don't want the user to be able to add more than one description.
Yes this can be done.
Lets say your model is MyDescModel.
class MyDescModel(models.Model):
desc = models.CharField('description', max_length=100)
def has_add_permission(self):
return not MyDescModel.objects.exists()
Now you can call this
MyDescModel.has_add_permission()
before calling
MyDescModel.save()
Hope this helps.
I solved the problem with the following code
Class Aboutus(models.Model):
....
def save(self):
# count will have all of the objects from the Aboutus model
count = Aboutus.objects.all().count()
# this will check if the variable exist so we can update the existing ones
save_permission = Aboutus.has_add_permission(self)
# if there's more than two objects it will not save them in the database
if count < 2:
super(Aboutus, self).save()
elif save_permission:
super(Aboutus, self).save()
def has_add_permission(self):
return Aboutus.objects.filter(id=self.id).exists()
Mar, 2022 Update:
The easiest and best way is using "has_add_permission()":
"models.py":
from django.db import models
class MyModel(models.Model):
name = models.CharField(max_length=50)
"admin.py":
from django.contrib import admin
from .models import MyModel
#admin.register(MyModel)
class MyModelAdmin(admin.ModelAdmin):
def has_add_permission(self, request): # Here
return not MyModel.objects.exists()
You can check the documentation about has_add_permission().

Django Smart Select

I have been searching for a solution to what I thought would be a common request but have found very little while Googling. I am trying to create a 'cascading' set of dropdown menus, the normal sort of UI feature usually found in location forms where a user would select Country, City, Town etc.
The solution I have been trying to work with is https://github.com/digi604/django-smart-selects. However the documentation, what little there is of it, is quite confusing. Here are the models as I have them so far:
models.py
class InstrumentModelType(models.Model):
model_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.model_type)
class InstrumentManufactuer(models.Model):
manufacturer_model_type = models.ForeignKey(InstrumentModelType)
manufacturer = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.manufacturer)
class InstrumentEquipmentType(models.Model):
equipment_manufacturer = models.ForeignKey(InstrumentManufactuer)
equipment_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.equipment_type)
class InstrumentDetails(models.Model):
instrument_model_type = models.ForeignKey(InstrumentModelType)
instrument_manufacturer = ChainedForeignKey(InstrumentManufactuer,
chained_field='instrument_model_type',
chained_model_field='manufacturer_model_type',
auto_choose = True,
show_all = False)
instrument_equipment_type = ChainedForeignKey(InstrumentEquipmentType,
chained_field='instrument_manufacturer',
chained_model_field='equipment_manufacturer',
auto_choose = True,
show_all = False)
def __unicode__(self): # Python 3: def __str__(self):
return '%s %s %s' % (self.instrument_model_type, self.instrument_manufacturer, self.instrument_equipment_type)
When I choose an option from the first dropdown (instrument_model_type) neither of the other two dropdowns populate as expected. Ideally I want to be able to filter first by model type and then by manufacturer to show available equipment types. Can anyone see where I am going wrong?
I have included the reference in urls.py as described in the docs and have tried numerous combinations of field references (chained_field/chained_model_field) to ensure I have understood the relations correctly. I also noticed that simplejson referenced in widgets.py has been depreciated so I replaced this with json.
While trawling the posts here I found http://www.dajaxproject.com/forms/ but the author on the Github page recommends not to use the library.
Am I wrong in thinking this is a common request? Is there a Django solution baked in that I have missed? If it matters at all I am using Django 1.6.
Thanks in advance.
I just finished similar project and I guess your solution is:
class InstrumentEquipmentType(models.Model):
manufacturer_model_type = models.ForeignKey(InstrumentModelType)
instrument_manufacturer = ChainedForeignKey(InstrumentManufactuer,
chained_field='instrument_model_type',
chained_model_field='manufacturer_model_type',
auto_choose = True,
show_all = False)
equipment_type = models.CharField(max_length=100)
def __unicode__(self): # Python 3: def __str__(self):
return unicode(self.equipment_type)
Let me know if it did not work to send you my example
Try Django Clever Selects
https://github.com/PragmaticMates/django-clever-selects
I use it in my Django 1.6 project. It is more usefull to operate chains in views and forms (in clever selects), not in models (like smart selects do).

Accessing Django custom models through Manager returns empty set

From all I've read, it appears this should Just Work, but it doesn't.
I have a custom model:
from django.db import models
from django.contrib.auth.models import *
class Feed(models.Model):
user = models.ForeignKey(User, blank=True, null=True)
link = models.CharField(max_length=200)
startDate = models.CharField(max_length=8)
endDate = models.CharField(max_length=8)
def __unicode__(self):
return str(self.id)
def __init__(self, link, sDate, eDate, user=None):
super(Feed, self).__init__()
self.link = link
self.startDate = sDate
self.endDate = eDate
self.user = user
And I'm also using the User model included in 'django.contrib.auth.models'.
When I create a feed, e.g.
feed = Feed(link, sDate, eDate)
feed.save()
(or a similar one with a user specified) it appears to store it in the database (I get its PK which keeps incrementing), but 'Feed.objects.all()' returns an empty list. Trying to filter by an existing pk also returns an empty list and trying to get() an existing pk gives me the following error
TypeError: __init__() takes at most 5 arguments (6 given)
Looking at how I should be retrieving objects from custom models, it appears that I've done everything I should, but that is clearly not the case...
Whoa.
Why are you overriding your model's __init__? There are very few good reasons to do this, and if you do, you must absolutely keep the interface the same- because that __init__ is called every time django pulls one of your models from the db (which is why you get the error when you call .get())
What are you hoping to accomplish with your __init__?
You should probably just delete your __init__ and then you can create Feed objects the normal, django way:
feed = Feed(link=link, startDate=sDate, endDate=eDate)
That line will create the correct feed object you want.
Did you try named arguments, e.g.
feed = Feed(link=link, startDate=sDate, endDate=eDate)
How did you use get()? It should also be used with named arguments, e.g.:
Feed.objects.get(pk=6)

Categories

Resources