Use django query __isnull with field name containing spaces or hyphens - django

The basic problem is that I can't use the key-value-argument
field_variable_name__isnull=True/False
or
field_variable_name=None
when the field_variable_name contains spaces or hyphens (e.g. 'This is my field variable name', or 'This-is-another-one').
I looked up how to filter a models.object-list with 'varname__isnull=True', but didn't find a solution for the case that a name containing a space-character was given:
In my views.py I have the following function:
def currenttodos(request):
todos = Todo.objects.filter(user=request.user, time_completed__isnull=True)
return render(request, 'todo/currenttodos.html', {'todos': todos})
The model Todo in the models.py - file comprises the following field:
time_completed = models.DateTimeField(null=True, blank=True)
This way it works, but actually I wanted to call the time_completed - field differently, for example "Completion time" using the name-parameter:
time_completed = models.DateTimeField(null=True, blank=True, name="Completion time")
Now, the problem is that I can't use the __isnull - parameter since the name contains a space.
All of the following examples don't work:
todos = Todo.objects.filter(user=request.user, Completion time__isnull=True)
todos = Todo.objects.filter(user=request.user, "Completion time"__isnull=True)
todos = Todo.objects.filter(user=request.user, "Completion time"=None)
etc.
How can I make this work for names containing spaces or hyphens?

Here is a link to a similar post:
Filtering for empty or NULL names in a queryset
Basically, this user wanted to be able to exclude instances that were null or blank. As you can see there are several options to do this. My preferred approach is to chain together the filter criteria as to me it is more straightforward and easy to understand however you have some options.

You could delete the name argument. It is not necessary. django will create a field with label of the attribute time_completed but you just filter like this
todos = Todo.objects.filter(user=request.user, time_completed__isnull=True)

Related

Grouping (not ordering) objects into alphabetical list on a single Django page

I’m trying to display a list of objects in an alphabetic list for a directory page. Something that looks like this:
https://en.wikipedia.org/wiki/List_of_film_and_television_directors
To avoid having to click on the link, the list would be:
Surname starts with A
• Anderson, Wes
Surname starts with B
• Burton, Tim
Surname starts with C
• Coppola, Sofia
A simplified version of the model would be:
class Person(model.Models):
first_name = model.CharField
last_name = model.CharField
def __str__(self):
return "{}, {}".format(self.last_name, self.first_name)
Route 1. In the view?
If not filtering in the template, after that I thought it would be possible to filter the objects within the view and send each portion separately.
def person_list(request):
startswith_a = Person.objects.filter(last_name__startswith="a")
startswith_b = Person.objects.filter(last_name__startswith="b")
startswith_c = Person.objects.filter(last_name__startswith="c")
etc.
etc.
return render(request, "directory/person-list.html", {"startswith_a": startswith_a, "startswith_b": startswith_b})
But that feels wrong as I’d have to hard code the alphabet into the view definition, and then pass all 26 (or more) sets into the view.
Route 2. In the model?
Finally I thought it might be possible to have a new field in the model which would affix its location in the directory. This could be updated manually or (I guess?) by customising the save function on the model to automatically assign based on the first character of the last_name field.
class Person(model.Models):
directory_position = model.CharField # eg. "a"
first_name = model.CharField # eg. "Wes"
last_name = model.CharField # eg. "Anderson"
def __str__(self):
return "{}, {}".format(self.last_name, self.first_name)
With that set, it would be possible to use template tags to show the relevant objects in each portion of the page.
{{ person.directory_position="a" }}
But that still feels a bit hacky because the template would have to iterate over the whole returned list for each of the 26 characters (and more for special characters).
Again, I feel like I must be missing something obvious. There’s probably a single line of code that will do all of this (especially in Python!) but I just can’t figure it out.
Thanks in advance!!

Query intermediate through fields in django

I have a simple Relation model, where a user can follow a tag just like stackoverflow.
class Relation(models.Model):
user = AutoOneToOneField(User)
follows_tag = models.ManyToManyField(Tag, blank=True, null=True, through='TagRelation')
class TagRelation(models.Model):
user = models.ForeignKey(Relation, on_delete=models.CASCADE)
following_tag = models.ForeignKey(Tag, on_delete=models.CASCADE)
pub_date = models.DateTimeField(default=timezone.now)
class Meta:
unique_together = ['user', 'following_tag']
Now, to get the results of all the tags a user is following:
kakar = CustomUser.objects.get(email="kakar#gmail.com")
tags_following = kakar.relation.follows_tag.all()
This is fine.
But, to access intermediate fields I have to go through a big list of other queries. Suppose I want to display when the user started following a tag, I will have to do something like this:
kakar = CustomUser.objects.get(email="kakar#gmail.com")
kakar_relation = Relation.objects.get(user=kakar)
t1 = kakar.relation.follows_tag.all()[0]
kakar_t1_relation = TagRelation.objects.get(user=kakar_relation, following_tag=t1)
kakar_t1_relation.pub_date
As you can see, just to get the date I have to go through so much query. Is this the only way to get intermediate values, or this can be optimized? Also, I am not sure if this model design is the way to go, so if you have any recomendation or advice I would be very grateful. Thank you.
You need to use Double underscore i.e. ( __ ) for ForeignKey lookup,
Like this :
user_tags = TagRelation.objects.filter(user__user__email="kakar#gmail.com").values("following_tag__name", "pub_date")
If you need the name of the tag, you can use following_tag__name in the query and if you need id you can use following_tag__id.
And for that you need to iterate through the result of above query set, like this:
for items in user_tags:
print items['following_tag__name']
print items['pub_date']
One more thing,The key word values will return a list of dictionaries and you can iterate it through above method and if you are using values_list in the place of values, it will return a list of tuples. Read further from here .

Django: Filter a model with multiple parameters for a single ManyToManyField

I have following models.
class Contents (models.Model):
...
tags = models.ManyToManyField('Tag')
class Tag (models.Model):
...
name = models.CharField(max_length=20)
Just to consider, I am trying to get contents which are tagged with both tag1 and tag2.
Is there a way in Django to do something like Contents.objects.filter(tags__name = ['tag1','tag2'])
Here tag1,tag2,... are dynamically generated.
Update:
I have been using for loop. I am looking for an efficient solution.
If you're looking for a list, then you should be able to use the look up __in:
Contents.objects.filter(tags__name__in = ['tag1','tag2'])
See the docs.
For a queryset with both and only both tags, you may need to chain your filter calls:
tags = ['tag1','tag2']
contents = Contents.objects.all()
for tag in tags:
contents = contents.filter(tags__name = tag)
That should filter the queryset so that you only have a queryset where both tags match. The method copied from this quesiton: Django queryset to match all related objects

Extracting Object values from a Queryset without a for loop

I have a model called
class UserTag(models.Model):
name = models.CharField(max_length=64, unique= True)
users = models.ManyToManyField(User)
I am trying to filter its contents based on the user like this
usertags = UserTag.objects.filter(users=request.user)
now I want a list of all the tag names for this particular query. I know I can probably use a loop
for tag in usertags:
tags.append(tag.name)
But what if a user has a 1000 tags? wont this slow down the response?
Is there a more efficient way to handling this?
If you just want the tag names, use a values_list query:
tags = UserTag.objects.filter(users=request.user).values_list('name', flat=True)

How to write this class for Django's data model (converting from Propel's YML format)

I am converting a web project that currently uses the Propel ORM, to a django project.
My first task is to 'port' the model schema to django's.
I have read the django docs, but they do not appear to be in enough detail. Case in point, how may I 'port' a (contrived) table defined in the Propel YML schema as follows:
demo_ref_country:
code: { type: varchar(4), required: true, index: unique }
name: { type: varchar(64), required: true, index: unique }
geog_region_id: { type: integer, foreignTable: demo_ref_geographic_region, foreignReference: id, required: true, onUpdate: cascade, onDelete: restrict }
ccy_id: { type: integer, foreignTable: demo_ref_currency_def, foreignReference: id, required: true, onUpdate: cascade, onDelete: restrict }
flag_image_path: { type: varchar(64), required: true, default: ''}
created_at: ~
_indexes:
idx_f1: [geog_region_id, ccy_id, created_at]
_uniques:
idxu_f1_key: [code, geog_region_id, ccy_id]
Here is my (feeble) attempt so far:
class Country(models.Model):
code = models.CharField(max_length=4) # Erm, no index on this column .....
name = models.CharField(max_length=64) # Erm, no index on this column .....
geog_region_id = models.ForeignKey(GeogRegion) # Is this correct ? (how about ref integrity constraints ?
ccy_id = models.ForeignKey(Currency) # Is this correct?
flag_image_path = models.CharField(max_length=64) # How to set default on this col?
created_at = models.DateTimeField() # Will this default to now() ?
# Don't know how to specify indexes and unique indexes ....
[Edit]
To all those suggesting that I RTFM, I understand your frustration. Its just that the documentation is not very clear to me. It is probably a Pythonic way of documentation - but coming from a C++ background, I feel the documentation could be improved to make it more accesible for people coming from different languages.
Case in point: the documentation merely states the class name and an **options parameter in the ctor, but doesn't tell you what the possible options are.
For example class CharField(max_length=None,[**options])
There is a line further up in the documentation that gives a list of permissible options, which are applicable to all field types.
However, the options are provided in the form:
Field.optionname
The (apparently implicit) link between a class property and a constructor argument was not clear to me. It appears that if a class has a property foo, then it means that you can pass an argument named foo to its constructor. Does that observation hold true for all Python classes?
The indexes are automatically generated for your references to other models (i.e. your foreign keys). In other words: your geog_region_id is correct (but it would be better style to call it geog_region).
You can set default values using the default field option.
import datetime
class Country(models.Model):
code = models.CharField(max_length=4, unique=True)
name = models.CharField(max_length=64)
geog_region = models.ForeignKey(GeogRegion)
ccy = models.ForeignKey(Currency, unique=True)
flag_image_path = models.CharField(max_length=64, default='')
created_at = models.DateTimeField(default=datetime.now())
(I'm no expert on propel's orm)
Django always tries to imitate the "cascade on delete" behaviour, so no need to specify that somewhere. By default all fields are required, unless specified differently.
For the datetime field see some more options here. All general field options here.
code = models.CharField(max_length=4) # Erm, no index on this column .....
name = models.CharField(max_length=64) # Erm, no index on this column .....
You can pass the unique = True keyword argument and value for both of the above.
geog_region_id = models.ForeignKey(GeogRegion) # Is this correct ? (how about ref integrity constraints ?
ccy_id = models.ForeignKey(Currency) # Is this correct?
The above lines are correct if GeogRegion and Currency are defined before this model. Otherwise put quotes around the model names. For e.g. models.ForeignKey("GeogRegion"). See documentation.
flag_image_path = models.CharField(max_length=64) # How to set default on this col?
Easy. Use the default = "/foo/bar" keyword argument and value.
created_at = models.DateTimeField() # Will this default to now() ?
Not automatically. You can do default = datetime.now (remember to first from datetime import datetime). Alternately you can specify auto_now_add = True.
# Don't know how to specify indexes and unique indexes ....
Take a look at unique_together.
You'll see that the document I have linked to is the same pointed out by others. I strongly urge you to read the docs and work through the tutorial.
I'm sorry, you haven't read the docs. A simple search for index, unique or default on the field reference page reveals exactly how to set those options.
Edit after comment I don't understand what you mean about multiple lines. Python doesn't care how many lines you use within brackets - so this:
name = models.CharField(unique=True, db_index=True)
is exactly the same as this:
name = models.CharField(
unique=True,
db_index=True
)
Django doesn't support multi-column primary keys, but if you just want a multi-column unique constraint, see unique_together.
Class demo_ref_country(models.Model)
code= models.CharField(max_length=4, db_index=True, null=False)
name= models.CharField(max_length=64, db_index=True, null=False)
geog_region = models.ForeignKey(geographic_region, null=False)
ccy = models.ForeignKey(Currency_def, null=False)
flag = models.ImageField(upload_to='path to directory', null=False, default="home")
created_at = models.DateTimeField(auto_now_add=True, db_index=True)
class Meta:
unique_together = (code, geog_region, ccy)
You can set default values,, db_index paramaeter creates indexes for related fields. You can use unique=True for seperate fields, but tahat unique together will check uniqueness in columns together.
UPDATE: First of all, i advice you to read documentatin carefully, since django gives you a lot of opportunuties, some of them have some restrictions... Such as, unique_together option is used just for django admin. It means if you create a new record or edit it via admin interface, it will be used. If you will alsa insert data with other ways (like a DataModel.objects.create statement) its better you use uniaue=True in field definition like:
code= models.CharField(max_length=4, db_index=True, null=False, unique=True)
ForeignKey fields are unique as default, so you do not need to define uniqueness for them.
Django supports method override, so you can override Model save and delete methods as you like.
check it here. Django also allows you to write raw sql queries you can check it here
As i explained, unique together is a django admin feature. So dont forget to add unique=True to required fields.
Unique together also allows you to define diffrent unique pairs, such as;
unique_together = (('id','code'),('code','ccy','geog_region'))
That means, id and code must be unique together and code, ccy and geog_region must be unique together
UPDATE 2: Prior to your question update...
It is better yo start from tutorials. It defines basics with good examples.
As for doc style, let me give you an example, but if you start from tutors, it will be easier for you...
There are from model structure... Doc here
BooleanField
class BooleanField(**options)
that defines, the basic structure of a database field, () is used, and it has some parameters taken as options. that is the part:
models.BooleansField()
Since this is a field struvture, available options are defines as:
unique
Field.unique
So,
models.BooleansField(unique=True)
That is the general usage. Since uniqu is a basic option available to all field types, it classified as field.unique. There are some options available to a single field type, like symmetrical which is a ManyToMany field option, is classified as ManyToMany.Symmetrical
For the queryset
class QuerySet([model=None])
That is used as you use a function, but you use it to filter a model, with other words, write a filter query to execute... It has some methods, like filter...
filter(**kwargs)
Since this takes some kwargs, and as i told before, this is used to filter your query results, so kwargs must be your model fields (database table fields) Like:
MyModel.objects.filter(id=15)
what object is defines in the doc, but it is a manager that helps you get related objects.
Doc contains good examples, but you have to start from tutors, that is what i can advice you...