i'm trying to give condition to an annotate field to return a BooleanField
class Employee(models.Model):
date_of_expire = models.DateTimeField()
my views.py
from django.db.models import Case,When,BooleanField
def lists(request):
lists = Employee.objects.annotate(is_expire=Case(When(
date_of_expire__lte=timezone.now()
),output_field=BooleanField())).order_by('-date_of_expire')
#others
but it doesnt work , still return all existing data even some of object's date_of_expire is less than current time
is there something else i should try please ?
as Mr #willem Van Onsem mentioned a link in the comment
from django.db.models import BooleanField,ExpressionWrapper,Q
lists = Employee.objects.annotate(is_expire=ExpressionWrapper(Q(date_of_expire__lte=timezone.now()),output_field=BooleanField()).order_by('-date_of_expire')
ExpressionWrapper
I have a variable 'cptCodeTBX' which is not present as fields in django models. I need to apply filter on 'cptCodeTBX' variable. Something roughly equivalent to
cptCodeTBX = '00622'
select * from cpt where cpt.code like cptCodeTBX or cptCodeTBX is != ''
In dot net entity framework we could do it by
b = cptContext.CPTs.AsNoTracking().Where(
a =>
(String.IsNullOrEmpty(cptCodeTBX) || a.Code.StartsWith(cptCodeTBX))
This may not be the most performant solution, but I was able to get it working.
Step 1: Read the Django Filter docs.
https://django-filter.readthedocs.io/en/stable/index.html
Step 2: Add a property to your Django model named cptCodeTBX.
from django.db import models
class MyModel(models.Model):
field = models.CharField(max_length=60)
#property
def cptCodeTBX(self):
"""
Does all the code tbx cpt stuff, can do whatever you want.
"""
cptCodeTBX = 2323 #whatever value you want
return cptCodeTBX
Step 3: Add a Django Filter.
import django_filters
class CptCodeTBXFilter(django_filters.FilterSet):
"""
Filter that will do all the magic, value comes from url query params.
Replace filters.NumberFilter with any filter you want like
filters.RangeFilter.
"""
cptCodeTBX = django_filters.NumberFilter(
field_name="cptCodeTBX",
method="filter_cptCodeTBX",
label="Cpt Code TBX",
)
def filter_cptCodeTBX(self, queryset, name, value):
objects_ids = [
obj.pk for obj in MyModel.objects.all() if obj.cptCodeTBX == value
]
if objects_ids:
queryset = MyModel.objects.filter(pk__in=objects_ids)
else:
queryset = MyModel.objects.none()
return queryset
Step 4: Pass the value through the url as a query parameter.
http://example.com/?cptCodeTBX=00622
I have a django model named Persona:
class Persona(models.model):
name=models.CharField(max_length=100,primary_key=True)
pages_visited = models.ManyToManyField(Page)
items_searched = models.ManyToManyField(ItemsSearched)
visits = models.IntegerField(null=True,blank=True)
connect = models.CharField(max_length=True,null=True,blank=True)
image = models.ForeignKey('Image',on_delete=models.CASCADE)
def __str__(self):
return self.name
I have an object for this model:
<QuerySet [<Persona: aman>]>
Now when i am trying to get the values of all fields for this object i can see all fields and their corresponding values except fields which are ManyToManyField type.
I get the following result when i execute this : Persona.objects.filter(name='aman').values()
<QuerySet [{'visits': None, 'image_id': 3, 'name': 'aman', 'connect': 'call'}]>
I cannot see 'items_searched' and 'pages_visited' fields and their corresponding values though when i log into admin i can see them.
These are the images which show you my execution:
Command Prompt
Admin Panel
To access m2m filed in django there is .all() keyword refer this
p1 = Persona.objects.filter(name='aman')
p1_m2m = p1.pages_visited.all()
which will give the result you wanted
I believe what you're looking for is Inlines.
In your admin file, add
from .models import Page # Edit this import according to your project structure
class PagesVisitedInline(admin.TabularInline):
model = Page
class PersonaAdmin(admin.ModelAdmin):
[...] # admin code goes here
inlines = [PagesVisitedInline, ]
You could use StackedInline aswell if you prefer, read more here.
After upgrading from Django 1.8 to 1.11 I've been looking at a means of merging some records - some models have multiple entries with the same name field, for example. There's an answer here that would appear to have what I would need:
https://stackoverflow.com/a/41291137/1195207
I tried it with models like this:
class GeneralType(models.Model):
#...
domains = models.ManyToManyField(Domain, blank=True)
#...
class Domain(models.Model):
name = models.TextField(blank=False)
#...
...where Domain has various records with duplicate names. But, it fails at the point indicated:
def merge(primary_object, alias_objects=list(), keep_old=False):
"""
Use this function to merge model objects (i.e. Users, Organizations, Polls,
etc.) and migrate all of the related fields from the alias objects to the
primary object. This does not look at GenericForeignKeys.
Usage:
from django.contrib.auth.models import User
primary_user = User.objects.get(email='good_email#example.com')
duplicate_user = User.objects.get(email='good_email+duplicate#example.com')
merge(primary_user, duplicate_user)
"""
# ...snip....
for alias_object in alias_objects:
for related_object in alias_object._meta.related_objects:
related_name = related_object.get_accessor_name()
if related_object.field.many_to_one:
#...snip...
elif related_object.field.one_to_one:
#...snip...
elif related_object.field.many_to_many:
related_name = related_name or related_object.field.name
for obj in getattr(alias_object, related_name).all():
getattr(obj, related_name).remove(alias_object) # <- fails here
getattr(obj, related_name).add(primary_object)
The problem is apparently that 'GeneralType' object has no attribute 'generaltype_set'. Adding a related_name to GeneralType doesn't fix this - the script fails in the same manner but quoting the name I've now given it. I'm not quite sure what Django is up to here so any suggestions would be welcome.
Edit:
In a Django shell I can successfully reference GeneralType from Domain, so it's something about the script above that I'm not getting. Example:
>>> d = Domain.objects.first()
>>> d
<Domain: 16s RNA>
>>> d.generaltype_set
<django.db.models.fields.related_descriptors.ManyRelatedManager object at 0x11175ba90>
>>> d.generaltype_set.first()
<GeneralType: Greengenes>
>>> getattr(d,'generaltype_set')
<django.db.models.fields.related_descriptors.ManyRelatedManager object at 0x10aa38250>
I managed to come up with a workaround. It seems that everything would function if I referenced generaltype.domains in the getattr(obj, related_name) part of the script, so I modified it as follows just before the line marked as failing in the question above:
if obj.__class__.__name__ == 'GeneralType':
related_name = 'domains'
Everything ran as it should after that, it seems.
I've defined a User class which (ultimately) inherits from models.Model. I want to get a list of all the fields defined for this model. For example, phone_number = CharField(max_length=20). Basically, I want to retrieve anything that inherits from the Field class.
I thought I'd be able to retrieve these by taking advantage of inspect.getmembers(model), but the list it returns doesn't contain any of these fields. It looks like Django has already gotten a hold of the class and added all its magic attributes and stripped out what's actually been defined. So... how can I get these fields? They probably have a function for retrieving them for their own internal purposes?
Django versions 1.8 and later:
You should use get_fields():
[f.name for f in MyModel._meta.get_fields()]
The get_all_field_names() method is deprecated starting from Django
1.8 and will be removed in 1.10.
The documentation page linked above provides a fully backwards-compatible implementation of get_all_field_names(), but for most purposes the previous example should work just fine.
Django versions before 1.8:
model._meta.get_all_field_names()
That should do the trick.
That requires an actual model instance. If all you have is a subclass of django.db.models.Model, then you should call myproject.myapp.models.MyModel._meta.get_all_field_names()
As most of answers are outdated I'll try to update you on Django 2.2
Here posts- your app (posts, blog, shop, etc.)
1) From model link: https://docs.djangoproject.com/en/stable/ref/models/meta/
from posts.model import BlogPost
all_fields = BlogPost._meta.fields
#or
all_fields = BlogPost._meta.get_fields()
Note that:
all_fields=BlogPost._meta.get_fields()
Will also get some relationships, which, for ex: you can not display in a view.
As in my case:
Organisation._meta.fields
(<django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
and
Organisation._meta.get_fields()
(<ManyToOneRel: crm.activity>, <django.db.models.fields.AutoField: id>, <django.db.models.fields.DateField: created>...
2) From instance
from posts.model import BlogPost
bp = BlogPost()
all_fields = bp._meta.fields
3) From parent model
Let's suppose that we have Post as the parent model and you want to see all the fields in a list, and have the parent fields to be read-only in Edit mode.
from django.contrib import admin
from posts.model import BlogPost
#admin.register(BlogPost)
class BlogPost(admin.ModelAdmin):
all_fields = [f.name for f in Organisation._meta.fields]
parent_fields = BlogPost.get_deferred_fields(BlogPost)
list_display = all_fields
read_only = parent_fields
The get_all_related_fields() method mentioned herein has been deprecated in 1.8. From now on it's get_fields().
>> from django.contrib.auth.models import User
>> User._meta.get_fields()
I find adding this to django models quite helpful:
def __iter__(self):
for field_name in self._meta.get_all_field_names():
value = getattr(self, field_name, None)
yield (field_name, value)
This lets you do:
for field, val in object:
print field, val
This does the trick. I only test it in Django 1.7.
your_fields = YourModel._meta.local_fields
your_field_names = [f.name for f in your_fields]
Model._meta.local_fields does not contain many-to-many fields. You should get them using Model._meta.local_many_to_many.
It is not clear whether you have an instance of the class or the class itself and trying to retrieve the fields, but either way, consider the following code
Using an instance
instance = User.objects.get(username="foo")
instance.__dict__ # returns a dictionary with all fields and their values
instance.__dict__.keys() # returns a dictionary with all fields
list(instance.__dict__.keys()) # returns list with all fields
Using a class
User._meta.__dict__.get("fields") # returns the fields
# to get the field names consider looping over the fields and calling __str__()
for field in User._meta.__dict__.get("fields"):
field.__str__() # e.g. 'auth.User.id'
def __iter__(self):
field_names = [f.name for f in self._meta.fields]
for field_name in field_names:
value = getattr(self, field_name, None)
yield (field_name, value)
This worked for me in django==1.11.8
A detail not mentioned by others:
[f.name for f in MyModel._meta.get_fields()]
get, for example
['id', 'name', 'occupation']
and
[f.get_attname() for f in MyModel._meta.get_fields()]
get
['id', 'name', 'occupation_id']
If
reg = MyModel.objects.first()
then
reg.occupation
get, for example
<Occupation: Dev>
and
reg.occupation_id
get
1
MyModel._meta.get_all_field_names() was deprecated several versions back and removed in Django 1.10.
Here's the backwards-compatible suggestion from the docs:
from itertools import chain
list(set(chain.from_iterable(
(field.name, field.attname) if hasattr(field, 'attname') else (field.name,)
for field in MyModel._meta.get_fields()
# For complete backwards compatibility, you may want to exclude
# GenericForeignKey from the results.
if not (field.many_to_one and field.related_model is None)
)))
Just to add, I am using self object, this worked for me:
[f.name for f in self.model._meta.get_fields()]
At least with Django 1.9.9 -- the version I'm currently using --, note that .get_fields() actually also "considers" any foreign model as a field, which may be problematic. Say you have:
class Parent(models.Model):
id = UUIDField(primary_key=True)
class Child(models.Model):
parent = models.ForeignKey(Parent)
It follows that
>>> map(lambda field:field.name, Parent._model._meta.get_fields())
['id', 'child']
while, as shown by #Rockallite
>>> map(lambda field:field.name, Parent._model._meta.local_fields)
['id']
So before I found this post, I successfully found this to work.
Model._meta.fields
It works equally as
Model._meta.get_fields()
I'm not sure what the difference is in the results, if there is one. I ran this loop and got the same output.
for field in Model._meta.fields:
print(field.name)
In sometimes we need the db columns as well:
def get_db_field_names(instance):
your_fields = instance._meta.local_fields
db_field_names=[f.name+'_id' if f.related_model is not None else f.name for f in your_fields]
model_field_names = [f.name for f in your_fields]
return db_field_names,model_field_names
Call the method to get the fields:
db_field_names,model_field_names=get_db_field_names(Mymodel)
Combined multiple answers of the given thread (thanks!) and came up with the following generic solution:
class ReadOnlyBaseModelAdmin(ModelAdmin):
def has_add_permission(self, request):
return request.user.is_superuser
def has_delete_permission(self, request, obj=None):
return request.user.is_superuser
def get_readonly_fields(self, request, obj=None):
return [f.name for f in self.model._meta.get_fields()]
Why not just use that:
manage.py inspectdb
Example output:
class GuardianUserobjectpermission(models.Model):
id = models.IntegerField(primary_key=True) # AutoField?
object_pk = models.CharField(max_length=255)
content_type = models.ForeignKey(DjangoContentType, models.DO_NOTHING)
permission = models.ForeignKey(AuthPermission, models.DO_NOTHING)
user = models.ForeignKey(CustomUsers, models.DO_NOTHING)
class Meta:
managed = False
db_table = 'guardian_userobjectpermission'
unique_together = (('user', 'permission', 'object_pk'),)