filter none on django field - django

I have a model Person which sometimes has nothing in the birth_date field. Here is an example:
(Pdb) dude = Person.objects.get(pk=20)
(Pdb) dude
<Person: Bob Mandene>
(Pdb) dude.birth_date
(Pdb) dude.birth_date == None
True
How do I filter these records that have birth_date == None?
I have already tried the following with no success:
1: "birth_date__isnull" does not work.
Person.objects.filter(birth_date__isnull = True)
# does not return the required
# object. Returns a record that have birth_date set to
# NULL when the table was observed in MySQL.
The following does not return the the record with id 20.
Person.objects.filter(birth_date = "")
How do I filter on a field being None? It seems NULL and None are different. When I see the data using sequel pro (mysql graphical client) I see "0000-00-00 00:00:00", and the following did not work either
(Pdb) ab=Patient.objects.filter(birth_date = "0000-00-00 00:00:00")
ValidationError: [u"'0000-00-00 00:00:00' value has the correct format
(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) but it is an invalid date/time."]
model
class Person(models.Model):
person_no = models.IntegerField(primary_key=True)
locationid = models.IntegerField(null=True, db_column='LocationID', blank=True)
address = models.ForeignKey('Address', db_column = 'address_no')
birth_date = models.DateTimeField(null=True, blank=True)
class Meta:
managed = False
db_table = 'person'

NULL in mysql turns into None in python, so what you had with birth_date__isnull=True should be returning those that have birth_date as None.

Hmm I'm not sure why 0000-00-00 00:00:00 is casted into None in this case but you can try to use exact:
Person.objects.filter(birth_date__exact=None)

A bit of list comprehension could come in handy here:
persons = [person for person in Person.objects.all() if not person.birth_date]

Related

Django - What is wrong with my view function?

In this function, the script can't get past the second if statement.
def save_data(request):
if request.method == 'POST':
if request.POST.get('id')\
and request.POST.get('id1')\
and request.POST.get('id2'):
try:
print('if2')
data=Flow()
data.id = request.POST.get('id')
data.id1 = request.POST.get('id1')
data.id2 = request.POST.get('id2')
data.save()
except Exception as e:
print(e)
My question is pretty simple, why might this be happening?
If I remove the if/and block entirely I get this:
ValidationError ['“on” value must be either True or False.']
If I remove all of the ands except for one, I have the original problem - where nothing is showing up in my database but no errors are shown either.
URL pattern:
path('io/save_data', views.save_data, name='save_data')
Model:
class Flow(models.Model):
author = models.ForeignKey(User, on_delete=models.CASCADE, default=None)
datetime = models.DateTimeField(default=timezone.now)
id = models.BooleanField(default=False, blank=False)
id1 = models.BooleanField(default=True, blank=False)
id2 = models.DecimalField(max_digits = 100, decimal_places = 5, default=1)
Why do you need a try & except ? why not using an else statement at the end ?
also why this :
if request.POST.get('id')\
and request.POST.get('id1')\
and request.POST.get('id2'):
would love to see more code :)
Try changing to this:
data.id = True if request.POST.get('id') == “True” else False
data.id1 = True if request.POST.get('id1') == “True” else False
As I haven't seen your HTML template, I will add this point for good measure. Double check that the fields are named as you call them in your view.
You should also look into using Django-forms for better validation and checking within your codebase. Forms are very useful. See the docs here.
As for your code, after checking out the above two points, try this.
def save_data(request):
if request.method == 'POST':
id = request.POST.get('id')
id1 = request.POST.get('id1')
id2 = request.POST.get('id2')
Flow.objects.create(id=id, id1=id1, id2=id2)
Try this and let me know if anything is created.

django.db.utils.IntegrityError, invalid foreign key. Can someone help me and teach me what happens?

can someone help me and teach me what happens?
For me not to make mistakes again?
I want to bind a foreign key (class category) to my course class. And I did something that doesn't allow me to get out of it.
Error: django.db.utils.IntegrityError: The row in table 'courses_course'
with primary key '3' has an invalid foreign key:
courses_course.category_id contains a value 'outros' that does not have a
corresponding value in courses_category.id.
CATEGORY = [('eng','ENGENHARIA'),('prog','PROGRAMAÇÃO'),('hum','HUMANAS'),('saude','SAÚDE'),
('outros','OUTROS')] // i'm from brazil
class Category(models.Model):
title_category = models.CharField('Nome da Categoria', max_length= 63 , choices = CATEGORY )
class Course(models.Model):
title = models.CharField('Nome', max_length= 100)
slug = models.SlugField('Atalho',max_length=50)
description = models.TextField('Descricao',blank = True)
follows = models.IntegerField(default = 0) //allows negative numbers, I know. I'll fix it ...
imagem = models.ImageField(upload_to = 'courses/images',verbose_name= 'Imagem',
null=True, blank = True)
category = models.ForeignKey('Category', on_delete = models.CASCADE)
created_at = models.DateTimeField('Criado em',auto_now_add = True )
updated_at= models.DateTimeField( 'Atualizado em', auto_now = True )
Does anyone imagine another structure or class that allows you to create educational courses / videos that have categories? Or am I on the right track for a beginner?
The only thing I can guess with the information you gave (you didn't say WHEN you get this error) is that you tried to do something such as :
my_course.category = 'outros'
my_course.save()
Which is incorrect since it isn't a Category object. A ForeignKey field must refer to an object of type to which you point to.
category = Category.objects.create(title_category='outros')
my_course.category = category
my_course.save()
This would work since you give a reference to a Category object in your Course object.
Do not hesitate to read the documentation about ForeignKey fields again.

django querset filter foreign key select first record

I have a History model like below
class History(models.Model):
class Meta:
app_label = 'subscription'
ordering = ['-start_datetime']
subscription = models.ForeignKey(Subscription, related_name='history')
FREE = 'free'
Premium = 'premium'
SUBSCRIPTION_TYPE_CHOICES = ((FREE, 'Free'), (Premium, 'Premium'),)
name = models.CharField(max_length=32, choices=SUBSCRIPTION_TYPE_CHOICES, default=FREE)
start_datetime = models.DateTimeField(db_index=True)
end_datetime = models.DateTimeField(db_index=True, blank=True, null=True)
cancelled_datetime = models.DateTimeField(blank=True, null=True)
Now i have a queryset filtering like below
users = get_user_model().objects.all()
queryset = users.exclude(subscription__history__end_datetime__lt=timezone.now())
The issue is that in the exclude above it is checking end_datetime for all the rows for a particular history object. But i only want to compare it with first row of history object.
Below is how a particular history object looks like. So i want to write a queryset filter which can do datetime comparison on first row only.
You could use a Model Manager method for this. The documentation isn't all that descriptive, but you could do something along the lines of:
class SubscriptionManager(models.Manager):
def my_filter(self):
# You'd want to make this a smaller query most likely
subscriptions = Subscription.objects.all()
results = []
for subscription in subscriptions:
sub_history = subscription.history_set.first()
if sub_history.end_datetime > timezone.now:
results.append(subscription)
return results
class History(models.Model):
subscription = models.ForeignKey(Subscription)
end_datetime = models.DateTimeField(db_index=True, blank=True, null=True)
objects = SubscriptionManager()
Then: queryset = Subscription.objects().my_filter()
Not a copy-pastable answer, but shows the use of Managers. Given the specificity of what you're looking for, I don't think there's a way to get it just via the plain filter() and exclude().
Without knowing what your end goal here is, it's hard to say whether this is feasible, but have you considered adding a property to the subscription model that indicates whatever you're looking for? For example, if you're trying to get everyone who has a subscription that's ending:
class Subscription(models.Model):
#property
def ending(self):
if self.end_datetime > timezone.now:
return True
else:
return False
Then in your code: queryset = users.filter(subscription_ending=True)
I have tried django's all king of expressions(aggregate, query, conditional) but was unable to solve the problem so i went with RawSQL and it solved the problem.
I have used the below SQL to select the first row and then compare the end_datetime
SELECT (end_datetime > %s OR end_datetime IS NULL) AS result
FROM subscription_history
ORDER BY start_datetime DESC
LIMIT 1;
I will select my answer as accepted if not found a solution with queryset filter chaining in next 2 days.

how to get the latest in django model

In this model:
class Rank(models.Model):
User = models.ForeignKey(User)
Rank = models.ForeignKey(RankStructure)
date_promoted = models.DateField()
def __str__(self):
return self.Rank.Name.order_by('promotion__date_promoted').latest()
I'm getting the error:
Exception Value:
'str' object has no attribute 'order_by'
I want the latest Rank as default. How do I set this?
Thanks.
Update #1
Added Rank Structure
class RankStructure(models.Model):
RankID = models.CharField(max_length=4)
SName = models.CharField(max_length=5)
Name = models.CharField(max_length=125)
LongName = models.CharField(max_length=512)
GENRE_CHOICES = (
('TOS', 'The Original Series'),
('TMP', 'The Motion Picture'),
('TNG', 'The Next Generation'),
('DS9', 'Deep Space Nine'),
('VOY', 'VOYAGER'),
('FUT', 'FUTURE'),
('KTM', 'KELVIN TIMELINE')
)
Genre = models.CharField(max_length=3, choices=GENRE_CHOICES)
SPECIALTY_OPTIONS = (
('CMD', 'Command'),
('OPS', 'Operations'),
('SCI', 'Science'),
('MED', 'Medical'),
('ENG', 'Engineering'),
('MAR', 'Marine'),
('FLT', 'Flight Officer'),
)
Specialty = models.CharField(max_length=25, choices=SPECIALTY_OPTIONS)
image = models.FileField(upload_to=image_upload_handler, blank=True)
This is the Rank_structure referenced by Rank in Class Rank.
THe User Foreign key goes to the standard User table.
The reason that you’re getting an error is because self.Rank.Name is not a ModelManager on which you can call order_by. You’ll need an objects in there somewhere if you want to call order_by. We can’t help you with the django formatting for the query you want unless you also post the model definitions as requested by several commenters. That said, I suspect that what you want is something like:
def __str__(self):
return self.objects.filter(Rank_id=self.Rank_id).order_by('date_promoted').latest().User.Name

Django DateTimeField User Input

So I'm trying to populate a model in django using a postgres (postgis) database. The problem I'm having is inputting the datetimefield. I have written a population script but every time I run it I get the error django.db.utils.IntegrityError: null value in column "pub_date" violates not-null constraint. The code below shows my model and the part of the population script that applies to the table.
The model:
class Article(models.Model):
authors = models.ManyToManyField(Author)
location = models.ForeignKey(Location)
article_title = models.CharField(max_length=200, unique_for_date="pub_date")
pub_date = models.DateTimeField('date published')
article_keywords = ArrayField(ArrayField(models.CharField(max_length=20, blank=True), size=8), size=8,)
title_id = models.CharField(max_length=200)
section_id = models.CharField(max_length=200)
And the population script:
def populate():
add_article(
id = "1",
article_title = "Obama scrambles to get sceptics in Congress to support Iran nuclear deal",
pub_date = "2015-04-06T20:38:59Z",
article_keywords = "{obama, iran, debate, congress, america, un, republican, democrat, nuclear, isreal}",
title_id = "white-house-scrambles-sceptics-congress-iran-nuclear-deal",
section_id = "us-news",
location_id = "1"
)
def add_article(id, article_title, pub_date, article_keywords, title_id, section_id, location_id):
article = Article.objects.get_or_create(article_title=article_title)[0]
article.id
article.article_title
article.pub_date
article.article_keywords
article.title_id
article.section_id
article.location_id
article.save()
return article
if __name__ == '__main__':
print "Starting Newsmap population script..."
populate()
I've searched around for ages but there seems to be no solution to this specific problem. Any help much appreciated!!
The issue is that you do not pass to Article.objects.get_or_create the data needed to create a new object in case none already exists.
What you need to do is (see the documentation for get_or_create):
article = Article.objects.get_or_create(
article_title=article_title,
pub_date=pub_date,
defaults={
'id': id,
'article_keywords': article_keywords,
# etc...
}
)[0]
The data passed using the defaults argument will only be used to create a new object. The data passed using other keyword arguments will be used to check if an existing object matches in the database.